Claude Code Subagents, Explained

A subagent is a helper Claude Code spawns in its own context window. It does the work, returns a summary, and throws away everything else. Here's what that costs you, when it's the right call, and when a separate session beats it.

A subagent is a helper that Claude Code spawns in a fresh context window with its own system prompt and its own tool access. It does a job, returns one final message to the main conversation, and everything else it saw is discarded.

That last clause is the whole feature. A subagent reads fifty files and your conversation gains a paragraph. It is a context filter with a model attached.

Anthropic’s own docs cover the file format well, and they should be your reference for exact field behavior. This page covers what they can’t: what the trade actually costs, why a subagent’s reasoning is invisible in the place it matters, and the cases where reaching for one makes your day worse.

The mechanics, briefly

Subagents are markdown files with YAML frontmatter. Two locations:

PathScope
.claude/agents/this project (check it into git, the team gets it)
~/.claude/agents/every project on your machine

Both are scanned recursively, so subfolders like agents/review/ are fine. Identity comes from the name field, not the filename or the folder.

A minimal definition:

---
name: dep-auditor
description: Audits third-party dependencies for unmaintained or risky packages. Use when reviewing package.json changes.
tools: Read, Grep, Glob, Bash
model: haiku
---

You audit dependencies. For each package added or bumped, check the last
publish date, open issue count, and whether it pulls transitive deps with
known advisories. Report only packages that warrant a decision, with the
reason in one line each. Do not edit files.

Only name and description are required. The body becomes the system prompt.

The optional fields worth knowing:

  • tools takes an allowlist. Omit it and the subagent inherits every tool available to subagents, including your MCP tools. disallowedTools is a denylist applied on top.
  • model takes haiku, sonnet, opus, a full model ID, or inherit. It defaults to inherit, so a subagent silently runs on your main model unless you say otherwise. Set haiku on a grep-and-summarize worker and the scan costs a fraction of what it would on Opus, for identical output.
  • permissionMode sets how the subagent handles approvals. It cannot loosen a stricter parent: if your main session is in acceptEdits or bypassPermissions, the parent mode wins.
  • isolation: worktree runs the subagent in a temporary git worktree so it gets its own copy of the repo. The worktree is cleaned up if the subagent changed nothing.
  • maxTurns caps how long it can churn before it has to stop and report.

One exception to know about if you install subagents from a plugin: plugin subagents ignore hooks, mcpServers, and permissionMode for security reasons. The fields are dropped at load time rather than rejected, so a plugin subagent you assumed was running in a restricted permission mode is running in yours. Copy the file into .claude/agents/ if you need those fields honored.

description is not documentation. It is the routing signal Claude uses to decide whether to delegate at all. “Reviews code” gets picked at random. “Use after any change to functions/api/ to check auth and input validation before commit” gets picked when it should be.

The /agents command has changed. Through Claude Code v2.1.197 it opened an interactive wizard for creating, editing, and deleting subagents. From v2.1.198 it prints a reminder pointing at those two directories instead. Run it and see which you have. Either way the practical path is to ask Claude to write the file, then read it before you trust it. Files are picked up within a few seconds of being written, no restart needed, unless the agents directory itself didn’t exist when the session started.

What the parent actually sees

When a subagent finishes, the main conversation receives its final message. Not its tool calls. Not the files it read. Not the reasoning that got it there. If it searched forty files and concluded “the token refresh happens in middleware.ts”, your session holds that sentence and nothing behind it.

You can open the transcript yourself. Subagent transcripts live in ~/.claude/projects/{project}/{sessionId}/subagents/, one agent-{agentId}.jsonl per subagent plus an agent-{agentId}.meta.json sidecar, and the subagent panel lets you open a running or finished one and even type follow-ups into it. So the record exists.

But the parent model still can’t see it, at least not in an interactive session. (Scripted runs are the exception: --forward-subagent-text forwards subagent text and thinking blocks, and only works alongside --print and --output-format=stream-json.) Ask Claude “why did the subagent say that?” and it is reading the same one paragraph you are. It will reconstruct a plausible reason, because that is what a model does with a missing premise. That reconstruction can be confidently wrong.

This matters in one specific way: a subagent that gets something subtly wrong hands you a clean, confident sentence with no visible seams. A mistake made in your main conversation leaves a trail. You scroll up, you see the grep that missed a directory, you catch it. A mistake made in a subagent arrives pre-laundered. The error rate isn’t higher; the detectability is lower.

Two habits that help:

  1. Ask for evidence in the output contract. Put it in the system prompt: file paths and line numbers for every claim, and say plainly when a search came back empty. A subagent that has to cite is a subagent you can spot-check in ten seconds.
  2. Delegate the looking, keep the deciding. Subagents are excellent at finding and summarizing. They are a poor place to put an irreversible judgment call, because the judgment arrives without the reasoning that produced it.

When a subagent is the right tool

The honest test: would the intermediate output be garbage in your main context? If yes, delegate.

  • Broad search across an unfamiliar codebase. “Where is rate limiting implemented” costs thirty file reads to answer in one sentence. Those reads are pure noise afterwards.
  • Parallel research on independent questions. Three subagents on auth, database, and API, running at once, each returning a summary. They don’t need each other’s findings, so isolation costs nothing.
  • Audits with a narrow output. Dependency risk, dead code, missing test coverage. Verbose input, short answer.
  • Work that should be constrained. A reviewer that only gets Read, Grep, and Glob cannot edit anything, no matter what it decides. That’s a real guarantee, not a request in a prompt.
  • Work that should be cheap. Routing a mechanical scan to Haiku while your main session stays on a larger model.

If you keep spawning the same shape of worker with the same instructions, that’s the signal to write a definition file instead of describing it every time.

When a subagent is the wrong tool

This is the part the reference docs skip, and it’s most of the disappointment people have with the feature.

Work you need to watch. You cannot steer a subagent turn by turn the way you steer your main session. You wrote a prompt, it ran, it came back. If the task involves taste, or a direction you’ll want to adjust after the first look, run it in a conversation you’re actually in.

Work with approvals in the middle. Recent versions surface a background subagent’s permission prompt in your main session, naming which subagent is asking, and Esc denies that single tool call without killing the subagent. That’s a real improvement: older versions auto-denied anything that would have prompted, which meant a background subagent could quietly fail at its first restricted call. But it turns your main session into a queue of interruptions from workers whose context you can’t see. Approving rm -rf ./build is a different decision when you can read the surrounding reasoning. Delegate work that stays inside its permission envelope, not work that will keep knocking.

Work whose tools change depending on where it runs. A background subagent keeps its MCP tools but is cut down to a restricted set of built-in tools, and this happens regardless of what its tools field says. The same definition can resolve to different tools in the foreground and the background, silently, with no error unless the trimming leaves it with no tools at all. If a subagent depends on a specific built-in tool, don’t assume the frontmatter guarantees it.

Long-running work. A subagent lives inside one session. Close Claude Code and it’s gone. Subagent transcripts persist within their session and can be resumed by resuming that session, but this is not a durable background job system. For anything measured in hours, you want a session that survives.

Anything you’d want to interrupt mid-flight. You can stop a subagent from the task list, but stopping is all you get. There’s no “wait, not that directory, look over here” without killing it and starting over.

Chained work where each step needs the last step’s detail. Each subagent starts fresh. A pipeline of them means the detail is thrown away at every boundary, and by step three you’re reasoning from a summary of a summary. Use one subagent with a bigger job, or keep the chain in your main conversation.

Anything where “it said it was done” isn’t good enough. The subagent reports success. You have its word. If verification matters, verify in the main session where you can see the test output yourself.

There are also three ceilings worth knowing before you design a hundred-worker fan-out. In recent versions: 20 subagents running at once, 200 spawned per session in total, and nesting up to three layers below your main conversation. Hit the first and the Agent tool fails with Concurrent subagent limit reached; hit the depth limit and Claude Code simply withholds the Agent tool, so the subagent does the work itself instead of delegating. All three are configurable with environment variables (CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS, CLAUDE_CODE_MAX_SUBAGENTS_PER_SESSION, CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH). The depth default in particular has moved around between releases, so confirm it rather than building a deep pipeline on the number above.

Subagents vs separate sessions

The alternative to a subagent is a whole second session: another Claude Code running in another terminal, on the same repo or a different one. Different tool, different trade.

subagentseparate session
contextfresh, isolatedfresh, isolated
you can watch it workonly by opening its panelyes, it’s right there
you can redirect it mid-tasknoyes, just type
survives closing the appnoyes, if your setup keeps it
approvalssurface in the parent’s queuehandled in that session
result reaches your main agentautomatically, as a summaryonly if you carry it over
best forverbose input, short outputwork you want to steer

The rule that holds up in practice: subagents are for work you want the answer to. Separate sessions are for work you want to be part of.

The reason people default to subagents for both is friction. A subagent is one sentence to spawn. A second session is a new terminal window, cd to the right directory, start the agent, explain the project again, and then remember it exists. That friction is a tooling problem, not a reason the subagent was the right shape.

Worth noting that if two sessions touch the same repo at once, you need git worktrees or they’ll clobber each other. Two agents, same repo covers what actually goes wrong.

The same idea in other agents

This isn’t a Claude Code exclusive, though the vocabulary differs.

Context pollution is a problem every coding agent has, so every coding agent ends up with some answer to it. Delegating a noisy side task to a helper that reports back a summary is the answer most of them reach for, whether or not they call it a subagent. Codex is the other CLI most people run alongside Claude Code, and this shape shows up there too.

What differs is everything specific: the vocabulary, whether definitions live in config files at all, the format if they do, the field names, and whether the main agent routes to a helper on its own or waits for you to ask. None of that transfers. Check the docs for the agent you’re actually running, and check them against the version you have installed, because this area moves fast in every tool.

Expect the pattern to be portable. Don’t expect the config to be.

Where the tools diverge is everything around the subagent: how you watch one, what happens when it needs you, and whether the work outlives the session.

Practical rules

  1. Set model explicitly. It defaults to inherit. A file-scanning worker on your largest model is money on fire.
  2. Write the description as a routing rule, with the trigger condition in it. This is what decides whether the subagent ever gets used.
  3. Restrict tools on anything that shouldn’t write. A read-only reviewer is a guarantee, not a hope.
  4. Demand citations in the system prompt. Paths and line numbers, and an explicit “found nothing” when it found nothing.
  5. Cap the scope with maxTurns on anything exploratory, so a confused subagent stops instead of grinding.
  6. Use isolation: worktree when a subagent will edit files and you want its changes separable from yours.
  7. Read the file Claude writes for you. A subagent definition is a standing instruction that runs when you’re not looking.
  8. Don’t nest deeply. Layer two is already a summary of a summary. Layer three is a rumor.

Where the ceiling is

Every limitation above traces back to the same root: a subagent is a thing that happens inside one session. It shares that session’s lifetime, its permission queue, and its attention. Isolation of context, no isolation of everything else.

Once you’re running enough parallel work that this bites, the answer stops being a better subagent and becomes real sessions you can see, steer, and come back to tomorrow.

That’s the layer crystl works on. It’s a macOS terminal built for running several agents at once, so a second session costs about as little as a subagent does:

  • A new session is a keystroke. Projects are gems, sessions inside them are shards. Spinning up a real, watchable Claude Code session next to your current one takes no window management. See parallel sessions.
  • Parallel work on one repo without collisions. Isolated shards create the git worktree, run the agent in it, and clean up when you close them. The thing isolation: worktree does for a subagent, for a session you can actually watch.
  • Approvals find you. When any session needs permission, it surfaces as a floating panel with the project it came from, rather than a line of text in a stream you’re not reading. Approval modes let you auto-run the safe stuff and keep the rest.
  • Sessions survive. Structured history per shard, searchable across all of them. Yesterday’s session is still there.
  • Agents that coordinate. When work genuinely needs a team rather than one delegate, Fanout and orchestration put one session in charge of workers across projects, and Roundtable puts several agents in a shared chat you can read. The multi-agent development guide walks through it.
  • Subagent files are still files. crystl’s agent file editor manages .claude/agents/ alongside CLAUDE.md, rules, and skills, for Claude Code, Codex, and the rest. See agent instruction files.

Bottom line

Use a subagent when the work produces more output than it produces value, and you want the answer without the trail. Restrict its tools, set its model, and make it cite its sources.

Reach for a real session when you want to watch, redirect, or come back to it. The two aren’t competitors. Most good days use both, and the mistake is only ever picking the one that was easier to start.

More on the surrounding ground: Claude Code agents, the four things people mean sorts out the vocabulary, managing multiple AI sessions covers keeping track of them, and running agents for longer covers keeping them working while you’re away.