Skip to content

Agents and delegation ​

Other languages: 한국어

A subagent is one delegated task running in its own session. It inherits your working directory, your mode, your provider and your backend, and nothing else: it cannot see this conversation, it cannot ask you a question, and only its final message comes back. That isolation is the point — a search that would flood your context with a hundred file excerpts costs you one paragraph instead.

The agent delegates with the delegate_task tool. You can do it yourself with /delegate <agent> <task>, or with the $<agent> <task> shorthand at the start of a prompt.

text
$explore where does the daemon decide the reply language?
/delegate reviewer look at the change in tools/fs.py

One task, one agent ​

Delegation goes wrong in one particular way: the same work gets two owners. Two children editing one file produce half of each change, and a parent that delegates a task and then does it anyway pays for it twice. So the rule the agent is held to is one task, one agent, and two guards make it true rather than merely stated.

A duplicate is refused. While a child is working, a second delegate_task with the same agent and the same brief comes back as an error naming the child that is already on it. Whitespace and capitalisation do not make a brief different. If you genuinely want two attempts at one task — best-of-N — the tool takes force: true.

A running sibling owns the files it wrote. When two children work in parallel and one writes a file the other then tries to edit, the second is refused with file_owned_by_sibling and told to report the collision instead. The parent then serialises the work. The guard follows the tools.readBeforeWrite setting, and it only applies while the sibling is still running: once it has reported, an ordinary re-read is all that is needed.

Parallel delegation without worktrees is therefore only safe across disjoint files. /team gives every worker its own git worktree and does not have this limit.

The built-in agents ​

NameWhat it is for
exploreread-only search: finds where something lives and reports it as path:line evidence
reviewerread-only review: a verdict plus findings, each with the evidence behind it
executor, architect, verifier, test-engineerrole prompts, with every tool available
writerdocumentation (README, manuals, API docs, changelog, comments): checks every command it documents, updates every language copy, does not change code; the delegation lead hands it docs, the /team pipeline gives it no stage
explorer, criticread-only-by-default team roles (read_file, glob, grep) unless a definition explicitly broadens tools

explore and reviewer carry a tool allowlist, so they are read-only in fact and not only by instruction: no write_file, no edit_file, no shell. A definition of the same name in <project>/.snowpea/agents/ overrides the built-in one completely.

explore vs explorer, reviewer vs critic ​

Two pairs read like duplicates and are not. explore and reviewer are the built-in agents you delegate to: read-only, tool-allowlisted, meant for one question or one diff. explorer and critic are team roles, filled by the pipeline's explore and review stages, but read-only by default (read_file, glob, grep) unless a definition explicitly adds more tools. Pick the built-in when you are asking for something now; the role name is what a roster is written in.

Delegate toTeam roleDifference
exploreexplorerexplore is the built-in read-only search agent; explorer owns the pipeline's explore stage
reviewercriticreviewer is the built-in on-request review agent; critic owns the pipeline's review stage

snowpea agents prints the same sentence in each description, so the list itself says which is which.

Where a definition came from ​

Each row carries the root it was read from, not just the word project:

sourceRead from
builtinshipped with snowpea
global~/.snowpea/agents/
project<project>/.snowpea/agents/
claude-global~/.claude/agents/
claude-project<project>/.claude/agents/

Claude Code's own agent directories are read as they are, and labelled as theirs, so an agent you did not write for snowpea is recognisable at a glance.

explore takes a thoroughness level in the brief — quick, medium, or very thorough — and reports findings as text with absolute paths, never as file dumps. reviewer opens the files it judges and answers with one of three verdicts:

text
VERDICT: APPROVE
VERDICT: REQUEST_CHANGES
VERDICT: NEEDS_MORE_EVIDENCE

Findings without evidence are opinions, so each finding names a location, what goes wrong, and the condition that triggers it.

Delegation mode ​

By default the agent does the work itself and delegates only when it judges a task worth it. Delegation mode turns the session's agent into a lead: it plans (or follows the plan it wrote in plan mode), hands implementation to executor, tests to test-engineer, design questions to architect and broad searches to explorer, documentation to writer, and has verifier check the result before it reports the work as done. Trivial edits and single commands it still does itself: up to agents.leadDirectCalls (default 3) write or exec calls per turn. Further ones are refused with an instruction to hand the step to a team agent with delegate_task, so a model that ignores the brief cannot keep implementing everything itself.

text
/delegation          # what is in force, and why
/delegation on       # this session delegates (kept across a resume)
/delegation off      # this session does the work itself
/delegation auto     # follow agents.delegateByDefault again

The team is the session's active team (/team use), else the agents.default_team roster, else the built-in roles. To make every new session start delegating, set "agents": {"delegateByDefault": true} in settings.json. While it is on, the terminal UI shows ⇄ team beside the mode.

Reviews happen when you ask for them ​

Nothing starts a review on its own. /review runs one over whatever is uncommitted in your working tree, and relays the verdict:

text
/review
/review the error handling in the new parser

/ralph also ends its loop with a review. It uses your own architect definition when the project has one, and the built-in reviewer otherwise.

Team mode can review each task before it is accepted, which is off by default:

json
{ "team": { "review": true } }

With it on, a reviewer child reads the merge of each finished task. A REQUEST_CHANGES verdict sends that task back to the same worker once, with the findings attached; anything else lets the merge stand.

Teams and workers are two commands ​

text
/workers 3 "add docstrings to the three parser modules"   # three identical workers
/team "add docstrings to the three parser modules"        # your team, by role

They used to be one command told apart by whether the first word was a number, which was a puzzle rather than a grammar. A team is the people you assembled, each doing the job their role implies. Workers are N copies of one anonymous agent racing through a task list. /team 3 "…" still runs worker mode, and says once that /workers N is the current spelling.

/workers <N> "<task>" (alias /worker) is the mode that moved: N identical workers, one git worktree each, branches merged by the lead as tasks finish.

/team "<task>" runs the members of your active project team, each in the role its name implies, one stage after another in your own checkout:

text
explore? -> plan -> implement -> test? -> verify? -> review? -> fix? -> review?

Every stage is an ordinary subagent, so you see the whole pipeline in the agent tree. Who fills which stage comes from the roster, never from the model:

StageTaken byIf nobody fits
exploreexplore, then explorerskipped
planarchitect, then plannerthe lead plans for itself
implementexecutorthe command stops and tells you
testtest-engineerskipped
verifyverifierskipped, with a note in the report
reviewcritic, then reviewerskipped

Picking which team runs it ​

/team "<task>" uses the project's active team. To run a different one just this once, name it:

text
/team external "add docstrings to the three parser modules"

The named team may be one of the project's own or a global one from your settings.json, and running it changes nothing: the project's active team is exactly what it was afterwards. An unknown name is answered with the list of teams you do have.

/team list shows every team, where it came from, and the stage each member fills, so a roster is never just a list of names. A member matching no stage is named too, rather than quietly ignored. /team use <name> switches the active team and /team use none clears it, which puts delegation back to unrestricted.

The same list reaches a client through agent.list: one row per team with kind: "team", carrying active, source (global or project), agents, stages, and hasGuide when a guide file exists. A team with no implementer is listed with an empty stages, so a picker can show it and say why it cannot run.

Team guides: persona and routing ​

A team guide is a markdown file with optional frontmatter that tells the lead how this team works and which agent to pick for which kind of work. Guides live at:

text
<workdir>/.snowpea/teams/<team>.md     # project — wins on a name clash
~/.snowpea/teams/<team>.md             # global

The reserved name default applies when the project has no active team (/team use none). It does not fall back when an active team has no guide of its own.

Example:

markdown
---
description: Platform delivery team
---
# Persona
You are the platform team. Prefer small, reviewable diffs and run the project's checks before you report done.

## Routing
- database migrations, SQL, schema changes -> sql-reviewer
- UI work, styling, accessibility -> designer
- everything else -> executor

Commands:

bash
/team guide
/team guide <team>
/team guide set <team|default> [--global] <persona...>
/team guide route <team|default> [--global] <agent> <when...>
/team guide unroute <team|default> [--global] <agent|index>
/team guide delete <team|default> [--global]

snowpea team guide show [team]
snowpea team guide set <team> <persona...> [--global]
snowpea team guide route <team|default> <agent> <when...> [--global]
snowpea team guide unroute <team|default> <agent|index> [--global]
snowpea team guide delete <team> [--global]

Where the text lands:

  • Lead (the main session, and the pipeline's explore/plan/review/verify stages) gets the persona plus a Who does what routing table.
  • Workers (delegated children and the pipeline's implement/test/fix stages) get the persona and a one-line reminder of which team they are on — not the routing table, because they do not delegate.

After /team create, add a persona with /team guide set <name> …. RPC clients use team.guide.get, team.guide.set, team.guide.delete, and team.guide.list; writes emit teams.changed.

There are no worktrees here, so the plan has to keep the work apart by hand: the plan stage names the files each task owns, tasks claiming the same file are merged into one before anything runs, and tasks with disjoint files run together up to agents.max_concurrent. A task that names no file runs on its own.

The test, verify and review stages each answer with one explicit line — TESTS: PASS or TESTS: FAIL, VERIFY: PASS or VERIFY: FAIL, VERDICT: APPROVE or VERDICT: REQUEST_CHANGES. A report with no such line, an empty report, a denied approval, or an approval with no tool call behind it counts as NEEDS_MORE_EVIDENCE, which is not a pass. The final report says Nothing was left unfinished. only when the tests really passed and the review really approved; otherwise it lists what did not, and a headless run fails.

A REQUEST_CHANGES verdict buys one fix pass by whoever wrote the code the findings point at, and one more review. If the reviewer still wants changes after that, the run ends and the report says what is unfinished — there is no third round.

Three settings shape it:

json
{ "team": { "pipeline": { "maxTasks": 8, "review": true, "test": false } } }

maxTasks caps the plan. review and test are on whenever your roster has somebody for that stage; set either to false to turn the stage off anyway.

Stage hand-offs and audit trail ​

Between pipeline stages, agents pass a concise 10–20 line structured hand-off block (handoff ... ) containing:

  • Decided: key decisions made during the stage
  • Files touched: files edited or checked
  • Findings: concrete findings with path:line references
  • Remaining: unfinished tasks or "nothing"
  • Risks: potential risks or caveats

If no fence is present, the first 20 lines are kept. Hand-offs are stored on disk under:

text
<workdir>/.snowpea/handoffs/<team-run-id>/<stage>.md

Each subsequent stage receives all prior hand-offs verbatim, plus git diff --stat and git diff capped at 20,000 characters (spilled to a cache file with a reader pointer if larger). At the end of the run, the summary lists all hand-off file paths and prints a telemetry table with per-stage rounds, budgets, and token usage.

Tool round budgets and grace call ​

The per-checkpoint budget matches Hermes defaults: 500 tool-use rounds for the main agent, and 50 per child, independent of the parent's allowance. All child roles use the same default unless explicitly overridden.

Main-agent work keeps the same conversation and renews its budget automatically up to agent.auto_budget_continuations times (default 10, 0 disables). Afterwards an attended run asks Continue/Stop; an unattended run saves a partial report and stops. Stop, permissions, completion verification and Stop hooks still apply. Unlike Hermes's single-window cap, automatic renewals remain enabled: the default main path permits 11 windows of 500 rounds, excluding report calls.

Example settings.json (existing agent.max_tool_rounds remains supported; max_turns wins if both are present):

json
{
  "agent": {
    "max_turns": 500,
    "auto_budget_continuations": 10,
    "verify_continue_rounds": 20,
    "provider_retries": 3,
    "no_progress_rounds": 40,
    "turn_max_minutes": 0,
    "turn_max_tokens": 0
  },
  "agents": {
    "defaultToolRounds": 50,
    "incompleteRetries": 3
  }
}

A model call that fails transiently (timeout, connection reset, HTTP 429/5xx) is retried agent.provider_retries times (default 3) with 2 s, 4 s, 8 s backoff before the turn ends with an error; a refused request (HTTP 400, a bad key) is not retried.

Turn safeguards ​

At a budget checkpoint, verification and Stop-hook continuations grant agent.verify_continue_rounds rounds (default 20) and count against the same per-turn auto_budget_continuations limit. Productive work still receives the normal 500-round automatic renewals.

agent.no_progress_rounds (default 40, 0 disables) stops repeated rounds that produce no new file edits, distinct tool-call arguments, or tool output content. Reading a new file or range counts as progress; repeating the same read does not. The turn saves a partial report with reason stalled.

Optional agent.turn_max_minutes and agent.turn_max_tokens ceilings default to 0 (unlimited). They are checked at safe round boundaries; token accounting uses provider-reported input and output usage. Reaching a ceiling saves a partial report with reason budget. Round-window settings must be positive; renewal, no-progress, time and token limits must be nonnegative.

Evidence across rounds and workflows ​

Each safe model-round boundary saves the main conversation, including tool calls and results. Every child attempt (failed, incomplete, or successful) queues a bounded evidence handoff with agent/session IDs, terminal reason, report, errors, and recent tool results; the next model request receives it after outstanding tool calls are resolved. /ralph, /team, and /workers persist progress before the final summary, so switching back to ordinary prompts retains earlier failures and later repairs. Sensitive results are redacted. Compaction preserves relevant failure/verification evidence and trace references, not unlimited raw output.

Incomplete re-issue ​

When a child stops with reason: budget or a ran-child empty error, SubagentManager.run re-issues the task up to agents.incompleteRetries times (default 3) with a continuation brief that includes the prior report, last tool calls, and a bounded checkpoint of recent tool outputs / work state. This is a new child turn, not an extension of the same round counter — the Hermes/OMC pattern of re-issuing incomplete work while preserving what the previous child actually learned. Set agents.incompleteRetries to 0 to disable. Interrupted, timeout, and permission-denied stops are never re-issued.

Role assignment ​

When agent is omitted, the runtime picks a role:

  1. prefer=(...) specialised roles (team roster first, then builtins)
  2. agents.generalAgent (default executor)
  3. agents.missingRole: general (stop after step 2), anonymous (unnamed child), or parent (reason: parent — main agent does the work, do not re-delegate)

/deepinit runs in two phases: explorer / explore maps each directory (read-only), then writer / executor writes AGENTS.md from those notes; the root is outlined by architect (falling back to explorer) before the same write roles create the file. Map and write do not fall through to a read-only generalist for the write phase. /ultrawork and /ralph prefer executor.

Configuring round budgets ​

Budgets are resolved in this order (for both main and child sessions):

  1. agents.maxToolRoundsBy (role, then default / *)
  2. Agent-definition max_tool_rounds / tool_rounds
  3. agents.maxToolRounds
  4. Legacy agents.toolRounds (role, then default, then *, or scalar)
  5. Child: agents.defaultToolRounds (50); main: agent.max_turns (500)

Definition budgets outrank scalar agents.maxToolRounds; maxToolRoundsBy outranks definitions. Previous built-in role caps, including explore's 8 rounds, were removed: every child role now defaults to 50. Explicit overrides remain.

Toolless grace call on budget exhaustion ​

Modeled on Hermes Agent, when a subagent exhausts its tool rounds (rounds_left <= 0), the run is not aborted abruptly. The loop invokes one final toolless "grace" call (_budget_report), giving the model a final turn with no tools to summarize what was done, what was learned, and what remains unfinished. The result is returned with reason budget and status done.

What a report is and is not ​

A child's report is a self-report. It says what the child believes it did, which is not the same as what happened. For anything with an effect outside the session — a file written, something uploaded, a service called — ask for a handle in the brief (a path, a URL, an id) and check it yourself before telling anyone it worked.

The result the agent reads starts with three lines:

text
status: done
reason: budget
roundsUsed: 40

reason says why the child stopped. complete means it finished; budget and timeout mean it ran out of rounds or time and the report is partial; error, interrupted and denied speak for themselves. A partial report is still useful — the right move is to take what is done and delegate only what is left, never to re-send the same task. A long report is trimmed to its head and tail with a pointer to the full text on disk, which the agent can read back with read_file.

Concurrency ​

agents.max_concurrent (3 by default) bounds how many children one parent runs at once; a project's .snowpea/settings.json can lower or raise it, and session.create(maxConcurrent) overrides both for one session. Children beyond the limit queue rather than fail.

/ultrawork <task> splits a task into parallel subtasks. The splitter is asked to give each subtask a disjoint set of files, and the split is then checked: subtasks that claim the same file are merged into one brief before anything runs, and the merge is reported in the output.

bash
snowpea agents --json

lists the children that are queued or running right now.

Child context diet ​

Delegated children (delegate_task) start with an empty history and a brief explaining the task. Handing a child the parent's full prompt — the memory recall block, the full skills index, and every nested AGENTS.md — wastes hundreds of thousands of input tokens across its rounds.

Setting agents.childContext controls the context diet:

settingdefaultvalueswhat it does
agents.childContext"lean""lean", "full""lean" strips the memory recall block, the skills index, and nested instruction files from delegated children, and narrows read-only child tools. "full" restores the parent's prompt for children. An agent definition can decide for its own delegated runs with frontmatter childContext: full (or lean), which wins over the setting.

Prompt shape ​

Three frontmatter fields let a definition trim the system prompt it runs with. Each choice is made when the session starts and kept until its next compaction, so the prompt prefix a server has cached never changes mid-session.

frontmattervalueswhat it does
identityownThe definition's prompt replaces the core coding identity (base.md, the execution, plan-continuity and memory-guidance fragments). Only the core essentials stay: honest blockers, no invented output, reply length, trust and language. Applies only with agents.ownIdentity: true or env SNOWPEA_AGENT_IDENTITY=1.
deferredToolsnames or prefix_* patternsThese tools are named in the prompt and loaded with tool_search, even when the tool list or a host attached them (grep and glob included). Calling one by name still works. Applies only with tools.agentDeferred: true or env SNOWPEA_AGENT_DEFERRED=1, and only on a local-style provider, whose tool list stays fixed for the session. On a hosted provider a loaded tool would join the list and rewrite the cached prefix, so there the field is ignored. A host can mark a tool the same way with deferred: true in tool.register (protocol 1.21.0).
defaultChildan agent nameWhere a delegate_task with no agent goes from a session running this definition. Without it, a plugin agent delegates to the agent its plugin defines for the preferred role, else to itself, so a browser child keeps the browser agent's page-safety rules.
skillsIndexpluginThe skills index lists only this plugin's skills and the built-ins, under a header that does not insist on loading a skill for every task.

identity and deferredTools stay off by default until an A/B run shows no task does worse with them.

In "lean" mode:

  • No memory block or guidance: the child has no memory recall block or guidance line (though memory tools still work if permitted).
  • No skills index: installed skills are not enumerated in the prompt, but the child can still view any skill by name with skill_view.
  • Root instructions only: only the root AGENTS.md or CLAUDE.md is loaded up front; nested instruction files attach on demand when a tool touches that directory.
  • Smaller eager tool set: read-only children (explore, reviewer) start with read_file, grep, glob, and tool_search. Other tools are deferred and loaded on demand.
  • Preserved: the child's definition prompt, role, and the tool round budget line (BUDGET_LINE) are always preserved.

MIT licensed. The manual is generated from the product repositories — see the banner on each page.