Subagents and Parallel Work
Fan out research, reviews, and refactors to parallel agents without losing the plot.
Claude Code uses subagents to offload focused work from the main conversation. Each subagent is an agent with its own context window, its own tools and its own system prompt, started by the main agent through a tool call. When Claude starts several subagents, Claude Code runs them at the same time, so research, reviews and refactors can move forward together without flooding the main conversation's token budget.
The idea that makes this work is context isolation with a strict response contract. A single request can send several subagents to check patterns across your codebase, and each one does its reading in its own context. Subagents do not dump raw file contents into the main conversation. They hand back short results that the main agent uses to decide what to do next.
What is a subagent, and how is it different from a skill?
A subagent is a specialized agent defined in a Markdown file inside .claude/agents/ (for one project) or ~/.claude/agents/ (for all your projects). It gets its own system prompt, its own tool access, and optionally its own model. A skill, by contrast, is a set of instructions that runs inside the main conversation and shares its full context, as Part 3 showed.
That difference decides which one to use. A skill suits a multi-step procedure that needs to see the whole conversation. A subagent is better when the work is self-contained, reads a lot, and only needs to return a short result. The analogy: a skill is a function you inline; a subagent is a service you call.
- Share the main conversation's context
- Run inside the main conversation
- Multi-step procedures
- Own, isolated context window
- Several can run at once
- Self-contained tasks
Here is a complete subagent file, saved as .claude/agents/type-refactorer.md:
The frontmatter configures the subagent and the body becomes its system prompt. Only name and description are required, according to the subagents documentation. tools limits what it can use (leave it out and it inherits the tools available to subagents), model picks a model, and maxTurns caps how many agentic turns it runs before it stops and returns what it has. You can write these files yourself, or ask Claude to write one for you. In current versions the /agents command only reminds you of those two routes; it no longer opens a wizard.
Claude Code also ships built-in subagents. Explore is a fast, read-only agent for searching and understanding a codebase. Plan does the research in plan mode, which Part 7 covers. General-purpose can both explore and change things for multi-step tasks. Explore and Plan start without your CLAUDE.md files and the git status snapshot, to keep their research fast and cheap; other subagents load your CLAUDE.md files like the main conversation does.
Claude reads each subagent's description to decide when to delegate. All subagents go through one tool, Agent (called Task before version 2.1.63; the old name still works as an alias). When Claude delegates, it calls that tool with the subagent's name as subagent_type, a short description, and a prompt that carries the task. The subagent runs its own agent loop, reads files, uses its tools, and finishes when it has produced the requested output. The main agent receives only the final result, not the full trace.
How does Claude Code decide when to spawn subagents and coordinate them?
The main agent handles planning. After you ask "Refactor the payment flow to use the new API (application programming interface) client," the main agent works out which parts can be delegated. The available subagents, with their names and descriptions, act as a menu of specialized workers. If you have defined a pattern-finder, a docs-checker, and a type-refactorer, the main agent can start all three in a single turn. You can also ask for one by name, or type @ and pick it to make sure that subagent runs.
This delegation uses the standard tool-calling mechanism. In pseudocode, the model emits something like Agent(subagent_type="type-refactorer", description="Migrate payment types", prompt="Convert the payment module's return types to Result<T, E>. The plan is in plans/result-migration.md."). Claude Code starts the subagent, and when it finishes, its output comes back to the main agent as a tool result, which feeds the next planning step.
The model can request several tool calls in one message, and Claude Code treats subagent launches the same way, so a single "fan out" step can start several subagents at once. Starting a subagent does not itself ask for permission; Claude Code checks each of the subagent's own tool calls against your permission rules as it runs.
How does context isolation work, and how do subagents hand off useful results?
A subagent starts with a fresh, isolated context window. It does not see your conversation history, the skills you have already invoked, or the files Claude has already read. Its context holds its own system prompt, the task message Claude wrote when handing off the work, your CLAUDE.md files (except for Explore and Plan), and a git status snapshot. This isolation keeps the main conversation clean: only the subagent's final, distilled answer enters it.
Because of this, subagents should produce compact outputs. A good subagent prompt demands a specific format: a short summary, a list of file paths and line numbers, or a pass or fail plus a brief explanation. The main agent can then merge these outputs into a conclusion without wading through raw logs or full source dumps. If a subagent ignores the format and returns whole files, the context fills up anyway, so tighten the output contract in its prompt. maxTurns caps how long it works, not how long its answer is; brevity comes from the prompt.
If you ask the main agent to write a brief plan to a file before fanning out, that file becomes a handoff artifact. The main agent passes the file path to each subagent. The subagent reads the relevant sections, does its local work, and returns findings anchored to the plan, not to the entire codebase. This pattern makes subagents dependable even when several run at once.
How does parallel execution work under the hood?
When Claude starts several subagents, Claude Code runs them concurrently. What the main conversation does meanwhile depends on whether they run in the foreground or the background.
In an interactive session, subagents run in the background by default. You can keep talking to Claude while they work, each result arrives as a message when that subagent finishes, and a subagent that needs permission for a tool call asks you in the main session, naming itself. A foreground subagent instead blocks the main conversation until it returns. In a claude -p run, Claude runs subagents in the background by default and in the foreground when it needs the result before continuing.
This mirrors a fan-out and fan-in pattern: map a batch of independent tasks to subagents, collect the results, and reduce them into a single decision. It also has the hazards of any concurrent system. If two subagents edit the same file at the same time in the same checkout, the second write can overwrite the first.
Claude Code has a built-in answer for that: worktrees. Set isolation: worktree in a subagent's frontmatter, or ask Claude to "use worktrees for your agents," and each subagent works in its own temporary git worktree, a separate copy of the repository on its own branch. Its edits cannot collide with anyone else's. A worktree with no changes is removed when the subagent finishes; one with changes stays until you bring the work back.
There are limits, and they are not the ones people expect. By default a subagent can start subagents of its own, up to three layers below the main conversation (CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH changes that, and 1 turns nesting off). And when 20 subagents are already running in a session, starting another fails with "Concurrent subagent limit reached" until one finishes (CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS changes that). There is no limit on the total number of subagents over a session.
How do you design subagents for fan-out refactors and reviews on a real project?
Our side project's payment module needs a migration to a typed result pattern. You define three subagents in .claude/agents/:
type-refactorer.md, which rewrites function signatures in one module to returnResult<T, E>and returns the list of changed files plus any type errors.test-updater.md, which adjusts the tests' assertions to match the new result types and returns a short list of the tests it changed.docs-validator.md, which checks that every function returning aResulthas a doc comment explaining the error case and returns a checklist.
Each subagent's file lists its tools in the frontmatter and its output format in the body. The two that edit files get isolation: worktree, so they never touch the same checkout. You ask the main agent to write a migration plan to a file first, then start all three with the plan path as context, then merge their work and write the commit message.
This fan-out turns what would be a long, sequential chain of edits into one concurrent step. The main agent never sees the raw diffs or every test file. It sees a summary like "5 files updated, 3 tests adjusted, 12 doc comments checked. Two problems: missing error docs in payment.ts line 42 and an unused import in types.ts." That compact report lets it decide the next action without context bloat.
What breaks when you fan out too aggressively, and how do you recover?
The most common failure is cost and rate limits. Each subagent sends its own requests, which count toward the same usage limits as your main conversation, and every result that comes back takes space in the main context. Fanning out to many subagents that each read half the codebase burns tokens fast. Design subagent tasks to be truly independent and narrow, and keep their results short.
Another risk is verbose subagent output defeating the purpose of isolation. If a subagent returns the full content of every file it touched, the main conversation fills up fast. The fix is to refine the subagent's prompt and output contract until it returns only a summary and pointers to the evidence.
Race conditions on shared files are the third risk. Claude Code does not lock files across subagents that share a checkout, so either give writing subagents isolation: worktree, have them write to separate files, or let the main agent apply changes one after another after the parallel read step. If you find inconsistent state after a parallel step, the main agent can run a reconciliation pass: a dedicated subagent that reads all the outputs and resolves conflicts in a fixed order.
When one session is not enough, there are two bigger tools. You can run separate Claude Code sessions in their own worktrees with claude --worktree <name>, and agent teams, an experimental feature that is off by default, let one lead session coordinate several teammate sessions that share a task list and message each other. Both cost more tokens than subagents, so reach for them only when the work really needs it.
Quick Reference
| Property | Value |
|---|---|
| Subagent definition location | .claude/agents/*.md (project), ~/.claude/agents/*.md (you) |
| Required frontmatter | name, description |
| Other useful fields | tools, disallowedTools, model, maxTurns, isolation: worktree, background |
| The tool behind it | Agent (formerly Task), with subagent_type, description, prompt |
| Built-in subagents | Explore, Plan, general-purpose |
| Context isolation | Each subagent has its own context window |
| Foreground or background | Background by default in interactive sessions |
| Nesting | Up to three layers below the main conversation by default |
| Concurrency cap | 20 running subagents per session by default |
| Handoff artifact pattern | A plan file, or the context passed in the prompt |
Frequently Asked Questions
Q: When should I use a subagent instead of a skill? Use a subagent when a task is self-contained, reads a lot, and benefits from a separate context window and a short result. Use a skill when the workflow needs continuous access to the full conversation, like a deploy procedure that builds on earlier outputs.
Q: Can one subagent call another subagent?
Yes, in current versions. By default a subagent can start subagents of its own, up to three layers below the main conversation, and in an interactive session only the top-level subagent's summary comes back to you. To turn nesting off, set CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH to 1; to stop one particular subagent from delegating, leave Agent out of its tools list or add it to disallowedTools.
Q: How many subagents can I run in parallel?
Up to 20 running at once in a session by default; past that, a new launch fails until one finishes. CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS changes the cap. In practice, your usage limits and the size of the results coming back matter sooner than the cap, so a handful of well-scoped subagents usually beats a crowd.
Q: What happens if a parallel subagent times out or fails?
Its result comes back to the main agent with the error, alongside the other subagents' results. The main agent can retry the failing subagent with a different prompt, skip it, or stop the task. A subagent that hits its maxTurns limit returns its output marked as partial, and Claude can resume it to continue.
Q: How do I keep shared state consistent across parallel subagents?
The safest approach is to make subagents read-only, or give each writing subagent its own worktree with isolation: worktree so their edits cannot collide. If they must change the same files in one checkout, have the main agent apply the changes one after another after the parallel step.
Test yourself
Our side project uses a shared types.ts file that defines core interfaces. Three subagents run in parallel in the same checkout: one refactors function signatures, one updates JSDoc types, and one migrates Redux action types. All three write updates to types.ts. Afterwards, types.ts contains a garbled mix of changes from the second and third subagents, and the first one's edits are missing. What happened, and how do you prevent it next time?
Answer: This is a write-after-write race. Claude Code does not lock files across subagents that share a checkout, so overlapping edits to the same file can overwrite each other. To recover, have the main agent start a reconciliation subagent that reads the current file and what each worker meant to change, then rebuilds types.ts in a fixed order; or revert the file and rerun the steps one at a time. To prevent it, change the pattern. Give each writing subagent isolation: worktree, so each edits its own copy on its own branch and the changes are merged afterwards. Or have the subagents return descriptions of their intended changes and let the main agent apply them to types.ts one after another. Better still, split the work so each subagent owns different files.
Next: Plan Mode and the Art of Not Letting the Agent Run Wild. It shows how to make Claude explore and propose a plan before it changes a line of code.
If you want this kind of breakdown every week, how real systems actually work under the hood, subscribe to Internals Decoded at internalsdecoded.com.
Sources
- Create custom subagents
- Tools reference
- Run parallel sessions with worktrees
- Orchestrate teams of Claude Code sessions