Defining a subagent
In the Agent SDK a subagent is an AgentDefinition: a description that tells the coordinator when to use it, a prompt that becomes its system prompt, and optionally tools to restrict what it can do and model to override the model. The description matters more than it looks — the coordinator chooses subagents by matching the task against descriptions.
options = ClaudeAgentOptions(
allowed_tools=["Read", "Grep", "Glob", "Agent"], # the coordinator can spawn
agents={
"doc-analyst": AgentDefinition(
description="Analyses supplied documents and extracts cited findings.",
prompt="Extract claims with their source file and page. Never speculate.",
tools=["Read", "Grep", "Glob"], # read-only
),
"synthesiser": AgentDefinition(
description="Combines findings from other agents into one report.",
prompt="Merge findings. Preserve every source attribution you are given.",
tools=["Read"],
),
},
)Only description and prompt are required. Current documentation lists further optional fields — among them disallowedTools, skills, mcpServers, maxTurns, effort and permissionMode — but the exam's focus is the four above. If you leave tools out, the subagent inherits every tool available to subagents, so restricting it is a deliberate least-privilege choice, not a formality. Subagents can also be written as Markdown files in .claude/agents/; programmatic definitions win when the names clash.
What a subagent can see
A subagent's context starts fresh. It receives its own system prompt and the prompt string it was spawned with — not the coordinator's conversation history, not earlier tool results, not the coordinator's system prompt. If the synthesis agent needs the web search results and the document analysis, the coordinator has to put them in its prompt.
The spawn prompt is the only bridge
Reaches the subagent
- Its own
prompt(its system prompt) - The prompt string it was spawned with
- Its tool definitions (all, or the
toolssubset) - Project CLAUDE.md, when settings load it
Never reaches it
- The coordinator's conversation history
- Tool results the coordinator already saw
- The coordinator's system prompt
- Anything a sibling subagent found
- Its own earlier runs, unless resumed
The return path is just as narrow. When a subagent finishes, the coordinator receives the subagent's final message as the result of the spawning tool call — not the files it read or the searches it ran. That is the point of a subagent: it can explore widely while the coordinator's context grows only by the summary. It also means a subagent should be told what its final message must contain, because that message is all anyone will see.
Passing context well
Pass complete findings, not a pointer to them. And keep content separate from metadata: when handing results to a synthesis agent, use a structured format that carries source URLs, document names and page numbers alongside each claim. Flattening everything into prose is how attribution gets lost between agents.
[
{ "claim": "Cooling accounts for roughly 40% of facility energy",
"source": "https://example.org/report-2025.pdf", "page": 12 },
{ "claim": "Water use rose year on year",
"source": "internal/esg-summary.docx", "page": 3 }
]Rewriting a spawn prompt
Weak — refers to invisible contexttext
Write the final report from
the research so far.Strong — self-contained brieftext
Goal: a 2-page briefing on data-
centre water use for the ESG board.
Findings (JSON, with sources):
[ ...12 claims from 3 agents... ]
Rules:
- Use only these findings.
- Keep every source and page.
- Flag claims that conflict.
Return: markdown report, then a
list of gaps you noticed.Running subagents in parallel
To run subagents concurrently, the coordinator emits several spawn calls in a single response rather than one per turn. Independent subtasks then finish in roughly the time of the slowest, not the sum of all of them.
Parallel spawn, message by message
Coordinator prompts should state research goals and quality criteria rather than step-by-step procedures. A subagent told what good looks like can adapt to what it finds; one given a rigid script cannot.
The guide also mentions fork-based sessions for exploring divergent approaches from a shared analysis baseline. That is covered in 1.7.
Traps the wrong answers are built from
| Tempting but wrong | Do this instead |
|---|---|
| Assuming a subagent knows what the coordinator knows | Pass every finding and constraint it needs in its prompt. |
| Spawning subagents one per turn when the work is independent | Emit several spawn calls in one coordinator response. |
| Flattening findings into prose between agents | Pass structured claims with source, document and page. |
| Procedural step lists in coordinator prompts | State goals and quality criteria so subagents can adapt. |
| Leaving the spawning tool out of the coordinator's allowed tools | Include it ("Task" in the guide; "Agent" in current SDK code). |
You should now be able to
- Define subagents with descriptions, prompts and restricted tool sets.
- Include the spawning tool in the coordinator's allowed tools.
- Put complete prior findings directly in a subagent's prompt.
- Pass context in a structured format that preserves attribution.
- Spawn parallel subagents from a single coordinator response.