Run Mode
The RunMode provides autonomous operation capabilities for the Penguin AI assistant, allowing it to switch from interactive conversation to task-driven execution mode.
Overview
Run Mode enables Penguin to:
- Execute specific tasks with defined goals
- Run continuously to process multiple tasks
- Maintain workspace state across tasks
- Operate with time limits and graceful shutdowns
Task Execution Flow (_execute_task)
The core logic for executing a task within RunMode resides in the _execute_task method.
- Check for Engine: It first checks if the
PenguinCoreinstance has an initializedEngine. - Delegate to Engine (Preferred): If the
Engineexists,_execute_taskdelegates the entire multi-step reasoning and action loop toEngine.run_task(task_prompt_full, max_iterations=self.max_iterations). TheEnginehandles the iterations, LLM calls, action execution, and stop conditions. - Legacy Fallback: If the
Engineis not available (e.g., failed initialization),_execute_taskfalls back to its internal legacy loop:- It prepares the initial task prompt and adds it to the conversation.
- It iterates up to
max_iterations:- Calls
PenguinCore.get_response()to get the next LLM response and potential actions based on the current conversation state. - Displays assistant output and action results.
- Checks for completion or stop phrases in the response.
- Continues the loop, building upon the conversation history.
- Calls
- Handle Completion/Error: Returns the final status (completed, interrupted, error) and message.
Continuous Mode Operation
Initialization
def __init__(
self,
core,
max_iterations: int = MAX_TASK_ITERATIONS,
time_limit: Optional[int] = None,
):
Parameters:
core:PenguinCoreinstance to use for operations.RunModewill usecore.engineif available.max_iterations: Maximum iterations per task (used primarily in legacy fallback loop). Default from config.time_limit: Optional time limit in minutes for continuous mode.
Key Methods
Start Single Task
async def start(
self,
name: str,
description: Optional[str] = None,
context: Optional[Dict[str, Any]] = None,
) -> None
Starts autonomous execution for a specific task by calling _execute_task.
Start Continuous Mode
async def start_continuous(self, specified_task_name: Optional[str] = None, task_description: Optional[str] = None) -> None:
Starts continuous operation mode that processes tasks sequentially, calling _execute_task for each task.
Task Execution (_execute_task)
async def _execute_task(
self,
name: str,
description: Optional[str] = None,
context: Optional[Dict[str, Any]] = None,
) -> Dict[str, Any]
Executes a task. Crucially, this method now attempts to delegate the entire execution loop to PenguinCore.engine.run_task if the Engine is available. If not, it falls back to its internal iterative loop using PenguinCore.get_response. Returns a dictionary with the task status and final message.
Task Completion & Control Phrases
RunMode uses special phrases, typically checked within the Engine loop or the legacy fallback loop, to manage task flow:
TASK_COMPLETION_PHRASE(e.g., "TASK_COMPLETED"): Signals that a specific task's objective has been met.CONTINUOUS_COMPLETION_PHRASE(e.g., "CONTINUOUS_MODE_COMPLETE"): Signals the end of the entire continuous mode session (not just one task).NEED_USER_CLARIFICATION_PHRASE(e.g., "NEED_USER_CLARIFICATION"): Indicates the AI needs more input from the user to proceed with the current task. This typically pauses the continuous mode.EMERGENCY_STOP_PHRASE: Signals immediate termination of operations.
Task Flow Summary
When running a task (start or within start_continuous), RunMode primarily:
- Retrieves or prepares task details (name, description, context).
- Calls
_execute_task. _execute_taskchecks forcore.engine.- If Engine exists: Delegates to
Engine.run_taskto handle the multi-step process until completion, stop condition, or error. - If Engine doesn't exist: Initiates its own loop, calling
core.get_responseiteratively, checking for completion phrases itself. - Handles the result (success, error, interruption, clarification needed).
- In continuous mode, loops to get the next task.
Continuous Mode
In continuous mode, RunMode:
- Initializes with a time limit if specified
- Enters a loop that:
- Gets the next highest priority task from project manager
- Executes the task
- Marks task as complete when finished
- Performs health checks periodically
- Handles interruptions gracefully
- Monitors for shutdown requests
- Performs graceful shutdown when time limit is reached or shutdown requested
Health Monitoring
RunMode periodically checks system health:
async def _health_check(self) -> None
This monitors memory usage, CPU usage, and other diagnostic metrics to ensure stable operation.
Graceful Shutdown
async def _graceful_shutdown(self) -> None
Ensures clean shutdown by:
- Completing current task if possible
- Saving state information
- Cleaning up resources
- Logging shutdown information
Example Usage
# Create a RunMode instance
run_mode = RunMode(core, time_limit=60) # 60 minute limit
# Run a specific task
await run_mode.start(
name="build_data_parser",
description="Create a parser for CSV data files"
)
# Run in continuous mode to process tasks automatically
await run_mode.start_continuous()
Command Line Usage
RunMode is activated through slash commands inside the Penguin CLI:
penguin # start the CLI
/run task build_data_parser "Create a parser for CSV files"
# Start continuous mode for 2 hours
/run --247 --time 120
Integration with Task Manager
RunMode integrates with the ProjectManager to:
- Retrieve task details by name
- Mark tasks as complete when finished
- Get the next highest priority task in continuous mode
- Track metadata for completed tasks
This allows for a seamless workflow where tasks can be created interactively and then executed autonomously.
DAG-Based Task Selection
When a project has tasks created from a Blueprint, RunMode uses DAG-based scheduling instead of simple priority ordering:
Tie-Breaker Order
When multiple tasks are ready (no pending dependencies), selection uses:
- Priority -
critical>high>medium>low - Value/Effort ratio - Higher value, lower effort wins (WSJF)
- Risk - Higher risk first (fail fast principle)
- Sequence - Explicit ordering from blueprint
Example
# In continuous mode with a Blueprint-synced project
await run_mode.start_continuous()
# RunMode will:
# 1. Check if project has a DAG
# 2. Get tasks with no pending dependencies
# 3. Apply tie-breakers to select next task
# 4. Execute task through ITUV workflow
# 5. Mark task complete, update DAG
# 6. Repeat until no tasks remain
ITUV Workflow Integration
RunMode can execute tasks through the ITUV (Implement, Test, Use, Verify) lifecycle when orchestration is enabled:
Enabling ITUV
# config.yml
orchestration:
backend: native # or "temporal" for durability
phase_timeouts:
implement: 600
test: 300
use: 180
verify: 120
Workflow Commands
# Start ITUV workflow for a specific task
/workflow start task-123
# Check workflow status
/workflow status ituv-task-123-abc
# Pause/resume/cancel
/workflow pause ituv-task-123-abc
/workflow resume ituv-task-123-abc
/workflow cancel ituv-task-123-abc
See Orchestration for detailed workflow documentation.
See Also
- Blueprints - Spec-driven task creation
- Orchestration - ITUV workflow execution
- Project Management - Task and project APIs