Skip to content

Subagents

A subagent is a separate agent the model starts to handle one self-contained task, such as a piece of research, a large read, or a delimited bit of work. The subagent does the task in its own context, and only a short result returns to the main conversation. You do not start subagents yourself; the model does, when a task is bounded enough to hand off.

A subagent is worth spawning for one or more of these reasons:

  • Context protection. The subagent’s work, including the false starts, the long tool output, and the dead ends, stays in its own context. Only the result reaches the main conversation.
  • Context freshness. A subagent starts with no history, so it reads the task without the assumptions the main conversation has already built up. Even the same model, run fresh, often takes a different approach.
  • Restricted permissions. A subagent can run with a narrower permission set than the main conversation’s, which limits what it may do. See Permissions.

Polytoken manages a subagent’s context the same way it manages the main conversation’s context. When the subagent’s work grows toward its model’s context limit, Polytoken compacts the context: a summary replaces the work so far, and the subagent continues from the summary with the record of its progress preserved. If compaction cannot make the context fit, the subagent ends with an error saying its context grew too large.

  • researcher: investigates a question against your codebase, the web, or both. The model chooses it when a task is about finding something out.
  • general-purpose-mini: a cheap general delegate for simple, repetitive, or mechanical bounded tasks. It has the same shape as general-purpose but runs on a smaller, faster model.
  • general-purpose: a general delegate for bounded tasks that need judgment or cut across several areas. It is also the escalation point when a general-purpose-mini run falls short.
  • plan-reviewer: reviews a handoff plan against the codebase and project context, then returns findings to resolve before execution.

The model chooses a subagent type by the kind of work. By default, Polytoken uses the model configured for that type rather than the main conversation’s current model. The model can pass model_override to the subagent tool to select a configured model or a prefixed model-group reference for that run.

A subagent runs in one facet for its whole run. The model cannot switch a subagent’s facet: when a subagent calls switch_facet, Polytoken returns an error explaining that facet switching is unavailable to subagents. Facet switching belongs to the main conversation.

Subagents run asynchronously alongside the main conversation and appear as jobs. Watch subagents in the async jobs pane or with /jobs. Each subagent has a handle such as researcher:curie. The model can pass name to the subagent tool to replace the generated suffix with a descriptive name. Polytoken adds a numeric suffix if the handle already exists. See Managing Work.

When a subagent finishes, Polytoken sends a notification and returns a short result to the model, not the subagent’s whole conversation. By default these notifications auto-drain: as soon as the result arrives, Polytoken starts a turn so the model can act on it, even if the main conversation was idle and waiting for you to type. To have the model wait for your next prompt instead, turn auto-drain off; see the configuration reference. Turning auto-drain back on immediately processes any notifications that queued while it was off.

The model can request several independent copies with the count input to the subagent tool. Polytoken prepares every copy in the batch before launching any of them, so a preparation or capacity failure starts no partial batch. Omit count for the default of 1. Polytoken returns one handle per launched copy in clone order, and each handle has independent status, cancellation, results, and notifications.

Every subagent launch receives subagent_batch.ordinal (one-based) and subagent_batch.count in its templates, including a single-copy launch where ordinal is 1 and count is 1.

A subagent can finish while a turn is still running. When Polytoken compacts that turn before the result notification reaches the model, the compacted context names the finished subagent, the outcome, and a short summary of the result, so the model can act on the finished work instead of waiting. Polytoken still delivers the queued notification after the turn ends.

Set daemon.max_concurrent_subagents to limit how many subagents Polytoken runs at once. When the limit is reached, later subagents remain queued in reservation order instead of failing to start. The job status reports queued, and the subagent starts when an earlier subagent reaches a terminal state. In the jobs pane, the status shows queued while the subagent waits and updates again when the subagent starts. Omit the key, or set it to 0, to allow unlimited concurrent subagents.

Clients older than the queued-status feature cannot parse the queued job status. Update the CLI before connecting it to a newer daemon.

Polytoken applies the limit when the daemon starts. Restart the daemon after changing daemon.max_concurrent_subagents. A queued subagent stays cancellable while it waits for a slot, and the overall deadline that bounds every subagent run still holds during the wait.

When a subagent fails, the failure notification identifies what went wrong and tells the model to re-dispatch the task when appropriate. A subagent that cannot produce a usable result after bounded recovery reports a harness failure, not a successful apology. The notification includes the available result text when one exists and suggests trying a different model or reasoning effort when re-dispatching.

Polytoken also reports a subagent as failed when it detects persistent history corruption, with the recurring tool-call IDs when available. Start a fresh subagent for that task: do not refork the corrupted history. This recovery instruction is part of the failure notification so the model does not mistake an interrupted run for a successful result.

If Polytoken cannot launch a subagent, the launch error preserves the specific cause and includes the same retry and escalation guidance.

A subagent run is exactly the kind of wait cache warming covers: the main conversation sits idle while background work runs, so its prompt prefix can drop out of the provider’s cache. When your config enables warming, Polytoken refreshes the main conversation’s prefix while the subagent works, and a subagent’s conversation warms the same way while the subagent waits on its own background jobs. A refresh request never reads or changes the subagent’s work; it repeats only the waiting conversation’s own prefix.

Warming follows the daemon.cache_warming policy and each model’s cache_warming_interval_secs interval; see Sessions for both. Each refresh draws on your API spend or subscription quota. By default, Polytoken allows one successful refresh per subagent conversation during an idle stretch. The daemon.cache_warming_max_refreshes_subagent key sets that per-conversation limit, and a new successful ordinary provider attempt in that conversation resets the count. A completed refresh that reports zero cached tokens pauses warming for that subagent; cache usage that is unavailable does not count as a miss. The daemon.cache_warming_refresh_limit_enabled key disables this limit and miss-stop behavior when set to false. Every attempt shows a compact card in the conversation, naming the model and, for a subagent’s refresh, the subagent. The card belongs to the interface alone, not to the session, so it disappears when the conversation reloads, clears, or rewinds.

A subagent definition can select a model group (an ordered failover list of models; see Model groups and failover) instead of a single model. Reference the group in the definition frontmatter with a prefixed name:

---
name: plan-checker
description: Review a plan against the codebase and return findings.
polytoken:
model: "@mg:polytoken:plan_reviewer"
tools: [file_read, grep, glob]
---
Review the plan sections against the actual source files and
report any gaps.

The shipped general-purpose, general-purpose-mini, researcher, and plan-reviewer subagents each run through a reserved model group. Replacing polytoken:plan_reviewer, for example, redirects the built-in plan reviewer to your ordered list, including its failover candidates.

Polytoken assigns counted clones successive starting positions in the model group: the first clone starts at the first candidate, the second at the second, wrapping around the group. At launch, Polytoken skips candidates whose providers are in a rate-limit cooldown and starts at the next available candidate. If all candidates are cooling down, the launch waits for a provider to become available. Polytoken retries the current provider before moving to the next candidate. A successful candidate stays current until you or the model explicitly selects a group again or the provider fails and the route advances.

Templates record launch-time values that never change afterward: model_group.name, model_group.ordinal, and model_group.count identify the group and the candidate selected at launch. Provider failover or a configuration reload can change the current route without changing these recorded values or the rendered text.

A group-valued polytoken.model cannot be combined with polytoken.fallback_models; Polytoken rejects the definition at load time. Put the fallback order in the group itself.

A subagent starts in the working directory the main conversation is using. If the model has pushed into a subdirectory with the pushd tool, the subagent starts there; otherwise it starts at the project root.

The model can also start a subagent in a specific directory by passing cwd when it spawns the subagent. The directory has to exist, and a relative path resolves against the main conversation’s working directory. Directories outside the project ask for chdir permission approval, and approving one also grants read access so the subagent can use file tools there without a second prompt. Once a subagent starts, it cannot popd above its start directory, though it can still pushd deeper if it has that tool.

The model can send a text message to a running subagent with the message_subagent tool. Polytoken queues the message and delivers the message before the subagent’s next step, never mid-response. The tool returns immediately after queuing. If the subagent has already completed, the tool returns an error saying the subagent is no longer running and does not deliver the message. The model can check the subagent’s state with job_status before sending.

Messages appear in the subagent’s conversation as new input. The subagent responds to them as part of its normal work.

Only the main conversation can use message_subagent.

A subagent’s work does not have to end when the subagent completes. The model can fork a completed subagent’s conversation into a new subagent, letting the same context carry forward into a new task. This is how the model takes a research subagent’s findings and turns them into an implementation subagent without re-explaining everything it already discovered.

The model passes resume_from with the prior subagent’s job handle, and the new prompt becomes a directive appended after the prior conversation. The fork creates a new subagent with its own job handle, so the source subagent stays unchanged. The fork uses the subagent type and model chosen for it, not the source’s.

Multiple forks from the same source are possible. Each fork gets a new handle and its own independent context from that point forward. The fork starts with the source’s full conversation, so the forked subagent sees everything the source saw, including tool results and earlier reasoning.