1. What a sub-agent is and isn't 22 min
Lesson notes
You keep hitting a context-length ceiling. The parent agent has accumulated forty thousand tokens of file reads, intermediate reasoning, and tool results, and now the task it is holding is simply too large to finish cleanly. The instinct is to prompt more carefully, or to ask for a longer context window. The correct move is to dispatch a sub-agent.
But first: understand what you are dispatching.
What a sub-agent actually is
A sub-agent is a separate Claude instance with its own context, its own tool permissions, and a strict one-way data channel: you send it a brief, it runs, it returns a result. When it exits, everything it held — file contents, intermediate reasoning, the entire conversation — is gone. Nothing leaks back to the parent.
The isolation is total and intentional. It is not a bug you work around. It is the feature you design for.
Here is what the dispatch looks like in Claude Code's Agent tool:
Task: "Read /src/auth/session.ts. Find every place a token is written to localStorage or sessionStorage. Return a markdown list: path, line number, variable name, storage key."
Tools allowed: Read, Bash
Output format: markdown list only, no preamble
That brief is self-contained. The agent can execute it without asking a clarifying question. The output format is specified so the parent can use the result without parsing. The tools are constrained so the agent cannot, say, delete files while it is reading them.
What a sub-agent is not
It is not a tool call. A tool call is synchronous — the model emits a structured block, your runtime executes a function, control returns in the same turn with the result. A sub-agent is asynchronous and isolated. The parent does not hold the file open while the child reads it.
It is not a long conversation. Appending messages to a conversation expands context. Dispatching a sub-agent does not touch the parent's context at all. You do not get a "longer session" — you get a separate session.
It is not a function. Functions have shared scope. Sub-agents do not. A sub-agent cannot read a variable the parent set, cannot call back into the parent's scope, and cannot modify shared state unless you explicitly design a handoff through a file or structured return value.
The boundary rule
If a task requires shared mutable state between steps — a file locked for writing, a database transaction open across calls, a variable one step sets and the next reads — it cannot be fully delegated to a sub-agent. The sub-agent's isolation is the feature, but isolation requires each step to be independently completable.
The test: can you write a brief that contains everything the agent needs to execute from a cold start? If you find yourself writing "and you will need to know what the previous agent returned," you have violated the boundary. Either sequence the tasks explicitly — parent reads agent 1's output, embeds it in agent 2's brief, then dispatches agent 2 — or combine them into one agent.
Notice that sequencing is a valid pattern. It is not a failure to use sub-agents. It is the correct design when steps genuinely depend on each other.
If you get stuck
The most common mistake at this stage: dispatching an agent with an underspecified output format, then discovering the parent cannot parse what came back. The agent did exactly what you asked. You asked for prose. Fix the brief, not the agent. Add an explicit output format to every brief before you dispatch.
Second: confusing "the agent has write access" with "the agent will be careful." Tool permissions are a whitelist, not a safety net. If you allow the Bash tool, the agent can run rm -rf. Constrain the tool list to Read and Bash with a specific path scope when the task is read-only. The brief's tools field is the place to enforce this — not the task description.
Third: assuming the sub-agent knows your project layout. It does not. Its context starts with your brief and nothing else. If it needs to know that /src/auth/ is the authentication module, say so in the brief. If it needs to know that the project uses TypeScript, say so. Every piece of context the agent needs that is not in the brief is a gap that will produce a question or a wrong assumption.
Cross-reference
l2 shows parallel dispatch — multiple agents running simultaneous briefs, which is where the "no shared state" constraint becomes structurally important. l3 shows how to isolate file writes when agents need to modify code, not just read it. If you are unsure whether a task belongs in an agent or a tool call, l4 draws that line precisely.
Deliverable
Write a sub-agent brief for one task you have open right now. It must contain: (1) the exact task statement, (2) the tools allowed, (3) the output format the parent will consume, and (4) the one question the agent is answering. Read it back and ask: could the agent execute this from a cold start without a follow-up message? If the answer is no, find the missing dependency and embed it in the brief before you continue to l2.
Further reading
- "Personas Are Channels. Something Else Has to Decide When to Call Them." — names the dispatch problem this lesson is implicitly solving: a sub-agent is a channel, not a PM, and the parent owns the decision to call it.
Try these prompts
- Draft a sub-agent brief to audit all files in /src/auth/ for localStorage token writes. Include: task statement, tools allowed, output format, and the one question the agent is answering.
- Explain in two sentences why a sub-agent cannot read a variable the parent set, and how the parent must pass that value instead.
- Write the output format field for a sub-agent that finds hardcoded API keys. The parent will parse the result programmatically.