Marathon: long-running agent tasks (CLI)
Marathon: long-running agent tasks (CLI)
Marathon lets you run a saved Agent across multiple sessions with the runtype CLI. It streams output in real time and provides local file and shell tools, automatic context compaction, checkpoints, and resumable state on disk.
Start a marathon
To start a marathon with a goal, run the following command:
Replace <agent-id-or-name> with the Agent ID or name. Replace the goal text with the work that you want the Agent to complete.
Use the following flags to control the marathon:
--max-sessions <session-count>: Set the session cap. The default is50.--max-cost <amount-usd>: Set a cost cap in USD.--model <model-id>: Override the Agent’s configured model.--max-tokens <token-count>and--temperature <temperature>: Override the per-session output-token budget and sampling temperature. Set the temperature from0to2. The CLI applies these values to every phase. Playbook milestones can override them per phase.--name <task-name>: Set the task name for state files. The default is the Agent name.--resume [message]: Continue from saved state, optionally with a new message.--fresh: Start a new run and ignore saved state for the task.--sandbox <provider>: Enable sandboxed code execution.--session-search: Enable session context indexing and thesearch_session_historylocal tool. Both are enabled by default.--no-session-search: Disable session context indexing and thesearch_session_historylocal tool.
Replace each angle-bracket value in a flag with the value for your task.
Marathon stores state in ~/.runtype/projects/<hash>/marathons/. The <hash> value identifies the project. The directory contains a <task>.json snapshot and a <task>.tree.jsonl session tree. It also contains a <task>.events/ directory for raw stream events and a <task>/outputs/ directory for large tool outputs that the context ledger offloads. Keep <task>/outputs/ with <task>.json and <task>.tree.jsonl when you move or back up a marathon task.
Steer a running Agent
While Marathon streams an Agent session, press Enter to open the steering composer. Use the following keys in the composer:
- Press Enter to queue your message. The current session wraps up at the next tool call, and Marathon delivers the message at the start of the next session.
- Press Tab to switch delivery between
next turnandafter all work. A follow-up message runs after the task would otherwise finish. - Press Esc to close the composer and keep your draft.
The CLI displays queued-message counts while messages wait. If Marathon is in a planning phase, file writes are restricted to the plan. A steering message that requests an immediate write takes effect after the plan is updated.
To stop the current session, press Esc twice while the Agent works. The session stops immediately. Marathon preserves observed cost and progress and creates a stopped checkpoint. It restores queued steering messages and the composer draft in the checkpoint input. Edit the input and press Enter to continue, or press Enter with empty input to exit. Resume a stopped task with --resume.
Use checkpoints
With checkpoint pauses enabled, Marathon pauses after each session and at the end of the task. At a checkpoint, press Enter to continue, enter a message to steer the next session, or enter a slash command.
Use the following commands at a checkpoint:
/model: Change the model for subsequent sessions./tools: Toggle local tools on or off./sandbox <provider>: Switch the sandbox provider./plan: Show the task plan./status: Show subtask completion./revert <file>: Restore a file from its checkpoint./reflect: Open the reflection editor to reassess the approach./tree: Browse session branches and switch between them./fork: Branch the conversation from an earlier message./copy: Copy the session JSON to the clipboard./copy-trimmed: Copy the session JSON with large payloads trimmed./open: Open the state file./stop: Stop the marathon and save state./help: Show all commands and shortcuts.
Replace <provider> with a sandbox provider and <file> with the path to a checkpointed file.
Manage session branches
Marathon records the conversation in <task>.tree.jsonl as a tree with parent links. Use /fork to branch from an earlier user message, or use /tree to switch to another checkpoint.
Use these commands to navigate session branches:
- Enter
/forkand select a user message on the current branch. Enter a new instruction to create a branch from that message. The next session uses history truncated at that message, and the original branch remains in the tree. - Enter
/treeand select a checkpoint to switch branches. The next session continues from that checkpoint and its branch history. The tree view marks the current head and labels ledger rows such as artifacts and compaction summaries as metadata.
Resume a marathon
To resume a saved task with its full history, run runtype marathon <agent-id-or-name> --name <task-name> --resume. Replace <agent-id-or-name> with the Agent ID or name and <task-name> with the task name.
Marathon opens a resume checkpoint before the next session. Use it to steer the task, switch branches, or change settings.
Use playbooks
Use a playbook to replace the default Marathon workflow of research, planning, and execution with milestones that define instructions, models, completion rules, and runtime guardrails. To run a playbook named release-notes, use the following command:
The CLI checks playbook paths in this order:
- An exact file path.
.runtype/marathons/playbooks/<playbook-name>.yaml,.yml,.json,.ts, or.mtsin the current project.- The same paths under
~/.runtype/.
Replace <playbook-name> with the value that you pass to --playbook.
Define milestones
The CLI runs milestones in order. The following YAML defines a two-milestone playbook:
Use these fields to configure each milestone:
instructions: Define the prompt for the milestone. Support{{key}}interpolation from run state, such as{{planPath}}.toolGuidance: Add guidance lines to the prompt’s tools section.modelandfallbackModels: Set the milestone’s model and its fallback chain for errors and stall escalation.maxTokensandtemperature: Set the output-token budget and sampling temperature from0to2. These fields take precedence over the CLI flags and top-level defaults.fallbackOnEmpty: Enable fallback models when the model returns no visible text after a successful request. The default is off. SetfallbackModelsto provide a fallback chain.completionCriteria: Define when the milestone advances.recovery: Add a message after the configured number of consecutive empty sessions. The default is2.transitionSummary: Add a message when the milestone completes. Use{{nextPhase}}to reference the next phase.canAcceptCompletion: Set this field totrueon the final milestone to accept the Agent’sTASK_COMPLETEsignal. Without an accepting milestone, the loader warns and the run can end only by stalling or exhausting its budget.
Set these fields at the playbook level:
policy: Narrow runtime behavior.stallPolicy: Configure recovery, model escalation, and stalled-run thresholds.maxTokensandtemperature: Set defaults for milestones without their own values. CLI flags take precedence.fallbackOnEmpty: Enable empty-output fallback for milestones without their own setting.plugins: Load custom hook modules.
Set completion criteria
Choose a built-in completion criterion or a hook reference:
evidence: Advance after the Agent reads at leastminReadFilesfiles. The default is1.sessions: Advance after at leastminSessionssessions run in the milestone. The default is1.planWritten: Advance after the Agent writes its plan artifact.never: Do not advance automatically. Only the Agent’sTASK_COMPLETEsignal can finish whencanAcceptCompletionistrue.- Hook reference: Set
typeto a completion hook reference for custom logic.
Set policies
Use the policy block to narrow runtime behavior. A playbook policy cannot override global safety denials, so paths such as .env files and private keys remain blocked. Marathon adds the policy rules to the Agent’s tool guidance.
Use the following fields in the policy block:
allowedReadGlobs: Block reads outside matching paths.allowedWriteGlobs: Block writes outside matching paths. The plan file remains allowed.blockedTools: Block named tools.blockDiscoveryTools: Block broad discovery tools.requirePlanBeforeWrite: Require the plan before non-plan writes.requireVerification: Require a passing verification command beforeTASK_COMPLETE.outputRoot: For creation tasks, limit new files to a directory.
Configure stall handling
Use stallPolicy to react when consecutive sessions perform no tool actions. A text-only session counts as empty. Use the following fields to configure the response:
nudgeAfter: Inject a recovery message into the next session after the configured number of consecutive empty sessions.escalateModelAfter: Switch the milestone to its next fallback model and restart after the configured number of consecutive empty sessions.stopAfter: Mark the run as stalled after the configured number of consecutive empty sessions. The default is3.
Milestone recovery messages and stallPolicy use the same counter. A session that contains text but no tool action still increments the counter.
Reference hooks
Use a registered hook name in any behavior slot instead of inline content. The builtin: namespace exposes hooks from the default workflow. Use these hooks to reuse one behavior without redefining it.
The following YAML uses built-in hooks for instructions, completion, and interception:
The loader rejects unknown hooks and hooks used in the wrong behavior slot while it loads the playbook.
Load plugins
To add custom hooks to a YAML playbook, list JavaScript modules in its plugins field. Use paths relative to the playbook. Each path must resolve inside the playbook directory.
The following YAML loads a custom hook module:
The module exports a recovery hook:
Register hooks under a namespace that you choose, such as acme:. Reference the hook from a behavior slot, such as recovery: acme:strict-recovery. The plugin runs with your privileges when the playbook loads. Verification commands that Marathon runs use the same privilege level.
Write a TypeScript playbook
Create a playbook as a TypeScript module with a .ts or .mts extension. The CLI loads it at runtime without a build step. TypeScript playbooks accept plain functions in every behavior slot, so you can define custom logic without a plugin or hook registration.
The following TypeScript module defines a playbook:
The definePlaybook helper comes from @runtypelabs/sdk. Install the package as a devDependency to get editor types. You can also export a plain object with the same shape without installing the package. To register named hooks, export a factory that receives { registerWorkflowHook }.
Next steps
Continue with these guides:
- What are Agents?: understand the Agent that you pass to
runtype marathon. - Creating and configuring Agents: build and configure an Agent.
- Agent tools: configure tools for the Agent.
- Manage agents as code: version-control Agent definitions.