Claude Code subagents: the complete guide (2026)
How Claude Code subagents work: the .claude/agents file format, scope, delegation, tool limits, model choice, and patterns that hold up in real projects.
9 min read
Claude Code subagents are specialized assistants defined as Markdown files in .claude/agents/. Each one has a name, a description that tells Claude when to use it, an optional list of allowed tools, an optional model, and a body that becomes its system prompt. When Claude delegates to a subagent, that agent works in its own context window and hands a result back to your main conversation.
That is the whole mechanism. The rest of this guide is about using it well: the exact file format, where files live, how delegation actually gets triggered, and the limits that shape how you design agents.
What a subagent is, and why you would want one
Your main Claude Code session is one long conversation. Every file it reads, every test log it scrolls through, every dead end it explores stays in that context. On a long task, that gets noisy.
A subagent fixes three things:
- Its own context window. The subagent reads twenty files, runs the tests, and returns a short summary. Your main thread only sees the summary, not the twenty files.
- A focused prompt. A code reviewer with a dedicated system prompt reviews more consistently than a general assistant you remind halfway through a session.
- Tool limits. You can give a reviewer read-only tools so it physically cannot edit code, or keep a researcher away from
Bash.
The tradeoff is that the subagent starts fresh. It does not see your conversation history, only what gets passed to it. More on that below, because it is the source of most "my agent did something dumb" moments.
The subagent file format
A subagent is one Markdown file with YAML frontmatter. The file name does not have to match, but keeping them aligned saves confusion.
| Field | Required | What it does |
|---|---|---|
name | Yes | Unique identifier, lowercase letters and hyphens |
description | Yes | When to use the agent. Claude reads this to decide delegation |
tools | No | Comma-separated tool list. Omit it and the agent inherits all tools |
model | No | sonnet, opus, haiku, or inherit |
Everything after the frontmatter is the system prompt.
A full example: a code reviewer
Here is a realistic .claude/agents/code-reviewer.md:
---
name: code-reviewer
description: Reviews code changes for bugs, security issues, and maintainability. Use proactively after any non-trivial code change, and whenever the user asks for a review.
tools: Read, Grep, Glob, Bash
model: inherit
---
You are a senior code reviewer. You review; you never edit files.
## Process
1. Run `git diff` (and `git diff --staged`) to see what changed. If the caller
named specific files, review those instead.
2. Read enough surrounding code to understand each change. Use Grep to find
callers of any function whose signature or behavior changed.
3. Check, in this order:
- Correctness: logic errors, off-by-one, unhandled null/undefined, wrong
async handling, broken error paths.
- Security: injection, secrets in code, missing auth checks, unsafe input
handling.
- Maintainability: unclear names, duplicated logic, dead code.
4. Do not comment on formatting a linter would catch.
## Output format
Return exactly these sections:
### Blocking
Numbered list. Each item: `file:line`, the problem, and a concrete fix.
Write "None" if empty.
### Should fix
Same format.
### Nits
At most 5 items.
### Verdict
One line: APPROVE or REQUEST CHANGES.A few things worth noticing. The description says both what it does and when to use it. The tools line includes Bash so it can run git diff, but leaves out Edit and Write, so "you never edit files" is enforced, not just requested. And the output format is spelled out, because the main thread has to parse whatever comes back.
Where agent files live: project vs user scope
There are two locations:
.claude/agents/ # project agents, shared via git
~/.claude/agents/ # user agents, available in every project on your machineIf a project agent and a user agent share the same name, the project agent wins. That is useful: keep a generic code-reviewer in your home directory, and override it in a repo that has stricter rules (say, a payments service where every review needs a security pass).
My rule of thumb: anything that encodes how this project works goes in .claude/agents/ and gets committed. Personal helpers you use everywhere go in ~/.claude/agents/.
Creating agents: /agents vs by hand
Run /agents inside Claude Code to open the agent manager. From there you can list, create, edit, and delete agents, and pick tools from a list instead of typing names from memory.
Writing the file by hand is just as valid:
mkdir -p .claude/agents
$EDITOR .claude/agents/test-writer.mdEither way, the result is the same Markdown file. If a hand-written agent does not show up, /agents is the quickest way to confirm what Claude Code actually sees.
How delegation works
There are two ways a subagent gets used.
Automatic delegation. Claude reads the description of every available agent and decides on its own when a task matches one. Ask "can you add a retry to the webhook handler" and, if your code-reviewer description says to use it after non-trivial changes, Claude may hand the diff to the reviewer when it is done.
Explicit request. You name the agent:
Use the code-reviewer agent to review the changes in src/billing/.Explicit requests are reliable. Automatic delegation depends almost entirely on how well the description is written.
Writing descriptions that actually trigger
Weak descriptions are the most common reason an agent never gets used. Compare:
description: Code reviewer.description: Reviews code changes for bugs, security issues, and maintainability. Use proactively after any non-trivial code change, and whenever the user asks for a review.The second one works better because it:
- States the trigger condition ("after any non-trivial code change").
- Uses words the user will actually say ("review").
- Includes "use proactively", which encourages Claude to delegate without being asked.
Keep descriptions specific enough that two agents never compete for the same task. If you have both a code-reviewer and a security-auditor, make the boundary explicit in each description, or Claude will pick somewhat arbitrarily.
Restricting tools
Omitting tools means the agent inherits every tool the main session has, including MCP tools. That is convenient and usually too generous.
Some sensible sets:
| Agent role | Tools |
|---|---|
| Reviewer, auditor | Read, Grep, Glob, Bash |
| Researcher, explainer | Read, Grep, Glob |
| Test writer | Read, Grep, Glob, Edit, Write, Bash |
| Planner | Read, Grep, Glob |
Narrow tools do two jobs. They prevent accidents (a planner that cannot edit will not "just quickly fix" something mid-plan), and they make the agent's role obvious to anyone reading the file.
Bash deserves a second thought. It lets an agent run tests and git commands, but it also lets it do almost anything. Give it to agents that need to execute things, and keep it off pure readers.
Choosing a model, and why inherit is a good default
The model field accepts sonnet, opus, haiku, or inherit. inherit uses whatever model the main conversation is running.
I default to inherit for most agents. You already chose a model for the session, and inherit respects that choice. Switch the main session to a stronger model for a hard problem and your agents follow. A hard-coded model: opus in some agent you downloaded quietly ignores that choice.
Hard-code a model only when you have a reason. A haiku agent for cheap, mechanical work like summarizing logs or checking file naming makes sense. Pinning a reviewer to a specific model because a template did it does not.
This matters most with agents you copy from public collections, many of which pin models. When I went through the public MIT collections for SlashKits, 76 of the 211 pieces I picked had hard-coded models and got switched to inherit. If you are evaluating collections yourself, this rundown of free agent collections covers what else to check.
Limits to design around
Subagents cannot spawn subagents
A subagent cannot delegate to another subagent. Only the main thread can. A "manager" agent that calls "frontend" and "backend" agents will not work.
Orchestration has to happen in the main conversation. You can do it by hand ("use the planner, then give step 2 to the backend agent"), or write a slash command that runs in the main thread and walks the steps for you. The slash command guide shows how to pass arguments into one.
Context goes in, a summary comes out
The subagent sees the task Claude writes for it, not your conversation. If you spent ten messages agreeing that the API must stay backwards compatible, the subagent does not know that unless it is in the hand-off.
Two fixes:
- Put durable rules in
CLAUDE.md, the project memory loaded each session, or in the agent's own system prompt. - When delegating explicitly, include the constraints: "Use the test-writer agent for
src/billing/retry.ts. Use vitest, no network calls, and match the existing fixtures intest/fixtures/."
On the way back, the main thread only gets what the agent returns. That is why the output format in the agent prompt matters. "Return a verdict line and a numbered list of blocking issues with file:line" gives the main thread something it can act on. "Summarize your findings" gives you a paragraph.
Best practices
- One job per agent. A
code-reviewerand atest-writerbeat onequality-agentthat does both badly. Small agents also have sharper descriptions, which helps delegation. - Narrow tools. Start with read-only and add tools when the agent actually needs them.
- Explicit output format. Headings, verdict lines,
file:linereferences. Treat the output as an API the main thread consumes. - Say what not to do. "Never edit files", "do not refactor unrelated code", "do not comment on formatting" save a lot of noise.
- Check agents into git.
.claude/agents/is part of the project. Review changes to agent prompts like code, because they change how code gets written. - Prune. Thirty overlapping agents make automatic delegation worse. Keep the ones you use.
The lead and specialist pattern
Since subagents cannot call each other, the pattern that works is: one agent plans, the main thread dispatches.
- A lead agent (read-only tools) reads the request and the codebase and returns a plan. Each step names the specialist that should do it and lists the files involved.
- The main thread takes the plan and delegates each step to the named specialist, passing the relevant context along.
- A final gate agent runs tests, typecheck, lint, and build, then returns a clear ship or block verdict.
The lead's output format is what makes this work. Something like:
## Plan
1. [backend-developer] Add `retryCount` column. Files: db/schema.ts, db/migrations/
2. [backend-developer] Retry logic in webhook handler. Files: src/webhooks/handler.ts
3. [test-writer] Tests for retry and max-attempts. Files: test/webhooks/
4. [shipper] Release gate.You can drive this by hand, or wrap it in a slash command so one command runs the whole sequence in the main thread. That is the reason SlashKits pairs a tech-lead planner with a /build-feature command instead of trying to make the planner call the specialists itself. The final step is covered in detail in adding a release gate to Claude Code.
If you are unsure whether a given workflow belongs in an agent at all, or would be better as a skill or a slash command, skills vs subagents vs slash commands walks through when to use which.