Delegate the noisy work, keep your context clean.
Most Claude Code sessions get slow and cluttered for the same reason: every exploratory grep, every log dump, and every “let me check one more file” stays in the main conversation forever.
Subagents exist to fix exactly that problem. They are one of the agent primitives built into Claude Code for handling noisy, parallelizable work — a way to push the mess into an isolated window and bring back only the summary that matters.
A subagent is not a smarter Claude, and it is not the same thing as a Skill. It is a separate reasoning agent with its own context window, its own tool allowlist, and no memory of your current conversation unless you explicitly fork it. Understanding that distinction is the difference between a subagent setup that quietly saves you context budget and one that just adds latency for no benefit.
Subagents vs Skills vs MCP #
Claude Code gives you three extension points that solve different problems, and they get conflated constantly because all three can technically “help with a task.”
| Layer | What it is | When to reach for it |
|---|---|---|
| Skill | Instructions loaded into the main agent’s context on demand | |
| Reusable procedures, checklists, playbooks — see | ||
outof the main sessionA useful rule of thumb: a hook enforces a hard constraint deterministically, a Skill gives the main agent a capability inline, and a subagent is for work you want to delegate and keep out of the main context entirely. If a Skill’s job is to orchestrate a tool that doesn’t exist yet, that is usually a sign you need an MCP server, not a subagent. Claude Code isn’t alone in this shape — OpenCode’s ecosystem has a comparable idea in its specialised agents, which split planning, research, and review across dedicated roles in a similar way.
What a subagent actually is #
Three properties define a Claude Code subagent, and all three matter for how you use it:
Isolated context. A subagent starts with a fresh window. It does not see your conversation history unless you explicitly fork it, which keeps its output from being polluted by whatever you discussed three turns ago.A restricted tool allowlist. Subagents can only use a subset of what the parent session already has — they cannot grant themselves new capabilities, and a well-designed subagent should get only the tools its job requires (read-only tools for a research agent, for example).No cross-subagent visibility. Subagents cannot see each other’s work in progress. If task B genuinely needs task A’s output, that is a sequential dependency, not something you can parallelize across two subagents.
The trigger for reaching for one is not “this task is hard.” It is “this task is noisy” — the kind of work that generates a lot of intermediate output (dozens of file reads, a long log, an exploratory grep across the whole repo) where none of that intermediate material needs to survive into your next conversation turn.
When to use a subagent (and when not to) #
Good fits: codebase exploration before a big change, automated test runs where you only care about pass/fail and failure summaries, security or style reviews, and any multi-step research task whose raw output would otherwise flood your main session.
Bad fits: two-second lookups (“what does this function return”), anything requiring tight back-and-forth refinement, and dependent tasks you’re tempted to “parallelize” even though the second one needs the first one’s answer. Using a subagent for a trivial lookup just adds the overhead of spinning up a fresh context window for no real isolation benefit.
Measuring the payoff: context and cost math #
The pitch for subagents is abstract until you put numbers on a real task. Take a common one: grep a ~500-file service for every place a deprecated config key is still read, then report the exact file:line matches.
| Approach | Main-session context consumed | What survives into your next turn |
|---|---|---|
| Direct exploration, no subagent | ~35-45K tokens — every grep hit, every file you opened to double-check, every dead end | All of it, including the wrong turns |
| Delegated to an Explore subagent | ~1.5-3K tokens — one summarized report | Only the findings that mattered |
That’s roughly a 15-20x reduction in what your main session has to carry for that step, which is the actual mechanism behind “subagents keep sessions faster” — it is not magic, it is context that never gets loaded in the first place.
The cost side compounds the same way. Using the pricing from the Claude Code pricing breakdown, running that same exploration pass on Opus ($5/MTok input, $25/MTok output) costs roughly $0.20-0.25 for the ~40K input tokens alone. Routing it to Haiku ($1/MTok input, $5/MTok output) drops that to $0.04-0.05 — and the main session’s Opus budget is never touched by the exploration tokens at all, since it only ever sees the ~2K-token summary.
Defining a custom subagent #
Custom subagents live as Markdown files with YAML frontmatter, either project-scoped in .claude/agents/
(committed to the repo, shared by the whole team) or user-scoped in ~/.claude/agents/
(personal tools you bring to every project).
---
name: code-reviewer
description: >
Reviews staged changes for bugs, security issues, and style violations
before commit. Use when the user asks to review, audit, or check
changes prior to committing or opening a PR.
tools: Read, Grep, Glob
model: sonnet
skills:
- security-checklist
---
You are a careful code reviewer. Read the staged diff, flag concrete
issues with file:line references, and end with a short pass/fail summary.
Do not modify any files.
The description
field is the most important line in the file. It is what the parent session’s routing logic reads to decide whether this subagent fits the current task. Write it like a job posting — name the trigger condition explicitly, not a vague “helps with code.” Vague descriptions get skipped or misapplied by automatic dispatch.
The tools
field is your isolation boundary. Give a research subagent Read
, Grep
, and Glob
and nothing else; giving it every tool available defeats the entire point of running it in a restricted sandbox. The optional skills
field preloads the full content of named Skills into the subagent’s startup context — useful when a subagent needs domain knowledge without spending a turn discovering and it mid-task.
Model routing: cheap models for grunt work #
Subagents are also where cost control gets real. Route file discovery, log scanning, and other cheap-to-verify work to Haiku, and reserve Sonnet or Opus for the reasoning-heavy steps — architecture decisions, ambiguous debugging, anything where getting it wrong is expensive. Haiku is roughly 15x cheaper per token than Opus, and on the kind of noisy exploration subagents are built for, that gap adds up fast across a real working session.
The Explore, Plan, Execute pattern #
For complex, multi-step work, the pattern that holds up in practice is Explore, Plan, Execute — using cheap subagents for the parts that generate noise, and keeping the human review gate in the one place it actually matters.
The key detail people get backwards is where the review gate belongs. Exploration is cheap, so let a subagent read freely without asking permission first. Planning is analytical, so let the agent design the approach on its own. But before any agent modifies files, you want to see the plan and approve it — that is what Claude Code’s plan mode (permissionMode: plan
) is for, and it is the same principle discussed in the broader vibe coding best practices around reviewing every diff before it lands.
Common mistakes #
A handful of mistakes show up repeatedly once teams start writing custom subagents:
Vague descriptions.“Helps with code” will never route correctly. Name the exact trigger condition.** Over-broad tool access.**Giving a read-only research subagent write and bash access removes the isolation guarantee that made it worth creating in the first place.Parallelizing dependent tasks. If task B needs task A’s finished output, run them sequentially — subagents cannot coordinate mid-task the way a shared orchestrator can. For workflows that genuinely need agents talking to each other mid-task, that’s a different shape of problem; seemulti-agent orchestration patternsif you’re building a production system rather than a single-repo workflow.Using a subagent for trivial work.“Format this JSON” or “run this one command” doesn’t need a fresh context window; just do it directly.
Worked example: a code-review subagent end to end #
Say you want every non-trivial commit reviewed before it lands. Drop the code-reviewer
definition shown earlier into .claude/agents/code-reviewer.md
, commit it so the whole team shares the same reviewer, and invoke it with a natural request like “review my staged changes before I commit.” Claude Code matches your request against the subagent’s description
, spins it up with only Read
, Grep
, and Glob
access, and it comes back with file:line-referenced findings and a pass/fail summary — none of the file-by-file noise from getting there ever touches your main session.
What that looks like in the main transcript, annotated:
You: review my staged changes before I commit
Main: [dispatches code-reviewer subagent — 6 files read, 1 grep pass,
zero of it shown here]
Main: code-reviewer findings:
- auth/session.go:142 — token refresh path doesn't handle expired
refresh token; falls through to nil dereference
- auth/session.go:203 — style: error wrapped without %w
PASS/FAIL: FAIL (1 blocking issue)
Six file reads and a grep pass happened, and your main session paid for exactly four lines of it. That gap — everything the subagent did versus the three-line summary you actually see — is the entire value proposition in one transcript.
If your team also uses Spec-Driven Development scaffolds, a review subagent slots naturally into the validation step; see GitHub Spec Kit vs Kiro vs Claude Code SDD Workflows for how that review gate compares across portable and IDE-integrated SDD setups.
Is it worth setting up custom subagents? #
Not on day one. The built-in general-purpose subagent already covers most exploration and research delegation without you writing a single YAML file, and a single Explore-Plan-Execute pass is enough for most day-to-day work. Write a custom .claude/agents/*.md
file only once you’ve delegated the same task by hand three times — a code reviewer, a test-runner triager, a docs-lookup agent for one specific internal library. Teams that write five subagents in their first week usually end up with five stale description
fields nobody updates when the actual trigger condition drifts, which quietly breaks automatic routing months later. Start with zero custom subagents, add one at a time, and only when repetition — not theoretical usefulness — demands it.
Known limitations #
A few rough edges are worth knowing before you build around subagents:
No recursive delegation. A subagent cannot spawn its own subagents. If a task genuinely needs a second layer of delegation, that is a sign you want a different orchestration shape — seemulti-agent orchestration patternsfor what that looks like outside a single Claude Code session.No memory across invocations. Every dispatch starts from zero, even if you called the same subagent five minutes ago on a related task. There is no built-in mechanism for a subagent to remember its last run.Isolation is a tool allowlist, not a sandbox. A subagent withBash
access can still touch the filesystem and network like any other tool call. Restrictingtools
reduces blast radius; it does not create a hard security boundary.
Troubleshooting #
Subagent never triggers. The description is almost always the problem. Rewrite it around the specific trigger condition instead of a general capability statement, and double-check the file lives in .claude/agents/
(project) or ~/.claude/agents/
(personal) with the right extension.
Subagent burns too much context anyway. Check the tools
allowlist — an overly broad toolset invites overly broad exploration. Also check whether the task should have been split into two subagents instead of one doing everything.
A listed skill doesn’t load inside the subagent. Claude Code skips a missing or disabled skill named in the skills
field rather than failing the run, and logs a line to that effect in the debug output (/debug
from the main session, then reproduce the dispatch) — something like skill "security-checklist" not found, skipping
. Run /doctor
afterward to confirm the rest of your setup is healthy.
Results feel inconsistent between runs. This is often a model-routing issue, not a subagent-design issue — reasoning-heavy work assigned to a cheap model will vary more. Move it to Sonnet or Opus and keep Haiku for the deterministic, low-ambiguity steps.
Subagents are one piece of a much larger toolbox; if you’re comparing Claude Code against the rest of the AI developer tools ecosystem before committing to this workflow, that overview is a good next stop.
Useful links #
Claude Code install and config for Ollama, llama.cpp, pricingClaude Skills and SKILL.md for DevelopersGitHub Spec Kit vs Kiro vs Claude Code SDD WorkflowsWhat is Vibe Coding?Multi-Agent Orchestration Patterns: A Practical GuideOh My Opencode Specialised Agents Deep DiveAI Developer Tools: The Complete Guide