Marathon: long-running agent tasks (CLI)
Marathon runs an Agent across multiple sessions from your terminal with the runtype CLI. It streams output in real time and gives the Agent local file tools and a verification-command tool. It also compacts context automatically, pauses at checkpoints, and saves resumable state on disk.
By default, a marathon moves through three phases: research, planning, and execution. In the planning phase, the Agent writes a plan to .runtype/marathons/<task>/plan.md in your project. The execution phase then carries out that plan. To replace these phases with your own milestones, use a playbook.
Before you begin
Complete these steps before you start a marathon:
- Install the Runtype CLI with
npm install -g @runtypelabs/cli. - Sign in with
runtype login. For other sign-in options, see Authentication. - Open a terminal in the root of the project that the Agent works on. The local file tools can reach only files inside the directory where you run the command.
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. The runtype agents task command accepts the same arguments and flags.
To find an Agent by name, the CLI compares the name, without regard to case, against your 50 most recently created Agents. If none of them matches, the CLI creates a new Agent with that name and saves the selected model and tools on it. To avoid creating an Agent by mistake, pass the Agent ID, which starts with agent_.
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.--planning-model <model-id>and--execution-model <model-id>: Set the model for the research and planning phases, or for the execution phase.--fallback-model <model-id>: Set a model to use when the primary model fails.--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.-t, --tools <tool-name...>: Enable built-in tools, such asexaorfirecrawl.--sandbox <provider>: Enable sandboxed code execution. Set<provider>toruntype-sandbox,daytona,cloudflare-worker, orquickjs.--no-session-search: Turn off search over earlier session output. By default, the Agent can callsearch_session_historyto look up output from earlier sessions.--no-auto-compact: Turn off automatic context compaction. To change when compaction starts, set--compact-thresholdto a percentage, such as90%, or to a token count.--checkpoint-timeout <seconds>: Set how long a checkpoint waits before Marathon continues. For more information, see Use checkpoints.--track: Sync progress to anagent-taskrecord named after the task, so that you can follow the run in the dashboard.--json: Print the final result as JSON.--name <task-name>: Set the task name for state files. The default is the Agent ID.--resume [message]: Continue from saved state, optionally with a new message.--session <task-name>: Select a saved task by name. Use it with--resume.--fresh: Start a new run and ignore saved state for the task.--state-dir <path>: Store state files in a different directory.
Replace each angle-bracket value in a flag with the value for your task. For the full list of flags, run runtype marathon --help.
--fallback-model and a playbook’s fallbackModels change the Agent’s saved error-handling configuration. The fallback chain stays on the Agent after the marathon ends and applies to the Agent’s other runs. For more information, see Error handling.
When the marathon ends, the CLI prints a summary with the final status, the session count, the total cost, and the path to the state file.
Where Marathon stores state
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 where Marathon saves large tool outputs to keep them out of the model context. Keep <task>/outputs/ with <task>.json and <task>.tree.jsonl when you move or back up a marathon task.
The task plan is in your project at .runtype/marathons/<task>/plan.md, not in the state directory.
Local tools
Marathon gives the Agent the following local tools:
read_file,list_directory,search_repo,glob_files, andtree_directory: Read and explore project files.write_fileandedit_file: Create and change files. Marathon saves a checkpoint of each file before the Agent changes it.restore_file_checkpoint: Restore a file from its checkpoint.read_offloaded_output: Read a large tool output that Marathon saved to<task>/outputs/.run_check: Run a verification command, such as a test or lint command. For the commands that it accepts, see Verification commands.search_session_history: Search output from earlier sessions.run_sandbox_codeanddeploy_sandbox: Run code and deploy a preview in a sandbox. These tools are available only when you pass--sandbox.deploy_sandboxrequires theruntype-sandboxordaytonaprovider.
The file tools can reach only paths inside the directory where you started Marathon. A symlink that points outside that directory is also blocked. They also block the .git and .runtype directories and sensitive files, such as .env files and private keys. The Agent can still write its plan file. A blocked path returns an Access denied error to the Agent.
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. In the planning phase, the Agent can write only to the plan file. 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
By default, Marathon pauses at a checkpoint after each session and at the end of the task. At a checkpoint after a session, Marathon continues automatically after 10 seconds if you don’t type anything. The checkpoint at the end of the task waits for your input. At a checkpoint, press Enter to continue, enter a message to steer the next session, or enter a slash command.
To change how long Marathon waits before it continues, set --checkpoint-timeout <seconds>. The runtype marathon --help output lists --no-checkpoint and --no-local-tools, but neither flag has an effect: checkpoint pauses and the local file tools stay on.
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. Enter/sandboxwith no provider to turn off the sandbox./reflect: Write guidance that asks the Agent to reassess its approach before the next session./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 from the --sandbox flag.
The help panel and the command menu also list /plan, /status, and /revert. These commands have no effect at a checkpoint. Marathon sends the text to the Agent as a steering message. To read the plan, open .runtype/marathons/<task>/plan.md in your project.
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. It labels entries that are not messages, such as saved artifacts and compaction summaries, as metadata.
Resume a marathon
To resume a saved task with its full history, run the following command:
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.
The session and cost caps include the sessions and cost from earlier runs of the task. For example, a task that stopped at 50 sessions has no sessions left when you resume it with the default --max-sessions of 50. To continue it, pass a higher --max-sessions value. If the task stopped at the cost cap, pass a higher --max-cost value.
If you pass --resume without --name or --session, Marathon offers the most recent task. In a script or CI job, always pass --name with --resume, or pass --fresh.
When a marathon ends
The summary at the end of a run shows one of these statuses:
complete: The Agent finished the task.max_sessions: The run reached the session cap. Resume with a higher--max-sessionsvalue.budget_exceeded: The run reached the cost cap. Resume with a higher--max-costvalue.stalled: Several sessions in a row ended without a tool action. Change the goal or the model, and then resume.paused: The run stopped before it finished, for example because you stopped it. Resume it with--resume.error: The run failed. The summary shows the last error.
Troubleshoot resume errors
The following errors are the most common reasons that a start or resume fails:
Local marathon state already exists at <path>. Use --resume to continue it or --fresh to start over.: Saved state exists for the task, and the terminal can’t show the resume prompt. Pass--resumeor--fresh.--resume without --name or --session is ambiguous in non-interactive mode.: Pass--name <task-name>with--resume.Cannot use --resume and --fresh together.: Pass only one of the two flags.No state files found to resume.: No saved task exists in the state directory. Run without--resumeto start a new task, or check--state-dir.
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}}, which resolves to the task’s plan file.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. Marathon saves the fallback chain to the Agent.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: The milestone never advances. The run ends only when the Agent sendsTASK_COMPLETEand the milestone setscanAcceptCompletion: true.- Hook reference: Set
typeto a completion hook reference for custom logic.
Set policies
Use the policy block to narrow runtime behavior. A playbook policy can’t 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 the discovery toolssearch_repo,glob_files,tree_directory, andlist_directory.requirePlanBeforeWrite: Require the plan before non-plan writes.requireVerification: Require a passing verification command before Marathon acceptsTASK_COMPLETE. The Agent runs the command with therun_checktool.outputRoot: For creation tasks, limit new files to a directory.
Verification commands
The run_check tool accepts one non-destructive check command at a time. It accepts commands that match these patterns:
pnpm,npm,yarn, orbunfollowed bytest,lint,build,check, ortypecheck, directly or throughrun.pnpm exec,npm exec,yarn exec, orbun execfollowed bytsc,vitest,eslint,prettier, orjest.vitest,jest,pytest,eslint,ruff,mypy, ortsc.playwright test,prettier --check,cargo test,cargo check,go test,deno test,deno check, orgit diff --check.makeorjustfollowed bytest,lint,build,check, ortypecheck.
The tool rejects pipes, &&, ;, redirects, and command substitution. It also rejects commands such as rm, curl, git push, and package installs. A script command, such as pnpm test, is also rejected when package.json has uncommitted changes or the project isn’t a Git repository. The same rule applies to make with its Makefile and to just with its justfile. Each command times out after 120 seconds by default, and the Agent can raise the timeout to 600 seconds.
A rejected command can’t satisfy requireVerification. If the Agent’s verification is blocked for two sessions in a row, Marathon waives the requirement for the rest of the run.
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 following table lists each behavior slot and the built-in hooks that it accepts:
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.
Plugins run with your user privileges when the playbook loads, and verification commands run with the same privileges. Load only playbooks that you trust.
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.
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, including its fallback models.
- Agent tools: configure tools for the Agent.
- Manage agents as code: version-control Agent definitions.
- Timeouts and long-running work: compare Marathon with other ways to run long work.
- Runtype CLI reference: install the
runtypeCLI and look up each command group.