Back to writing

Subagents in Claude Code: when delegating is worth it

How subagents work, when they pay off and when they're over-engineering. A pragmatic guide with a couple of ready-to-paste examples.

There’s a moment, working with Claude Code, when the main conversation fills up with things you don’t need to read: test output, the contents of a file you only wanted to skim, logs from a script. The original plan is still there, but it’s buried under the noise. That’s what subagents are for.

A subagent is an isolated instance of Claude launched with its own context, its own system prompt and, optionally, a restricted set of tools. It does its isolated task and returns only the summary to the main conversation. The intuition is the same as with any function: the main session makes the call, the subagent returns the value.

what it actually solves

The official docs sell them for five things, but in the end they all reduce to three real problems:

  1. Context gets dirty fast. Searching a large repo, running a linter, reading a two-thousand-line file — all of that burns tokens you won’t reuse. In the subagent that information stays where it belongs: outside.
  2. You want to guarantee constraints. An agent with only Read, Grep, Glob can’t touch anything by accident, no matter what you ask of it. You don’t get that guarantee with good intentions.
  3. You repeat the same prompt over and over. “You’re a code reviewer, look for…” — that paragraph becomes a file and you invoke it with @code-reviewer for the rest of your life.

If you don’t have any of these three problems, you don’t need a subagent. The main conversation is faster, keeps context between steps and doesn’t have the latency of starting from scratch.

how they’re defined

A subagent is a Markdown file with YAML frontmatter. Where you store it determines its scope:

LocationScope
.claude/agents/This project. Versioned, shared with the team.
~/.claude/agents/All your projects. Personal.
--agents (CLI flag)This session only. Useful for automation.

The two required fields are name (identifier) and description (when Claude should delegate to it). The body of the file is the system prompt:

---
name: code-reviewer
description: Reviews recent changes for quality and security issues. Use proactively after editing code.
tools: Read, Grep, Glob, Bash
model: sonnet
---

You are a senior code reviewer. When invoked:
1. Run git diff to see the recent changes
2. Focus only on the modified files
3. Report critical issues first, then warnings, then suggestions

Three things to note:

  • description isn’t decorative. It’s what Claude reads to decide whether to delegate. Adding “use proactively” changes the behavior — it starts invoking the subagent without you asking.
  • tools is an allowlist. If you omit it, it inherits everything. If you want the opposite (everything but a couple of things), use disallowedTools.
  • model can lower the cost. A researcher that only reads files doesn’t need Opus. haiku or sonnet are perfectly capable and return results faster.

when it’s worth it (and when it isn’t)

The trap with subagents is the same as with any abstraction: overusing them. Each subagent adds latency — it starts from scratch, without your context — and its final result takes up context again in the main conversation. It isn’t free.

Use a subagent when:

  • The output is noisy and you only care about the summary. Tests, broad searches, fetching external docs.
  • You want to restrict tools. A read-only researcher that can’t write by mistake.
  • The same prompt repeats across sessions. Turning it into a file is cheaper than rewriting it.
  • You want to run several independent tasks in parallel. One subagent per module to investigate.

Stay in the main conversation when:

  • The task needs iteration. “Try this, now change that, now try again” — the spawn latency makes this miserable.
  • You need the same context across several phases. Plan → implement → test works better without restarting.
  • It’s a quick, targeted change. To fix one line you don’t need to delegate.

There’s a pattern that’s sometimes better than any subagent: a skill. If what you want is to reuse a prompt or a workflow that doesn’t need context isolation, a skill loads into the main conversation and shares everything you already have. Subagents to isolate; skills to reuse.

a real example: read-only researcher

This is the pattern I use most. A subagent that searches, reads and reports — but touches nothing.

---
name: explorer
description: Investigates the code to answer structural questions. Reads, searches, reports. Doesn't modify files. Use proactively when the question is "where is X" or "how does Y connect to Z".
tools: Read, Grep, Glob, Bash
model: haiku
---

You are a code researcher. Your job is to answer questions
about the structure of the repo without modifying anything.

When asked:
1. Search broadly first (Grep, Glob) and then focus (Read).
2. If the repo is large, prioritize files by their path before reading them.
3. Report only what's relevant. Don't paste whole files.

Always return paths with line numbers (`src/foo.ts:42`)
so the main conversation can navigate directly.

You save it in .claude/agents/explorer.md, restart the session, and from then on Claude invokes it on its own when the question matches the description. The trick that really makes it useful is the last two lines: asking for paths with line numbers turns the summary into something actionable — the main conversation can jump straight to the file without re-searching.

details that matter

Restart the session after editing the file by hand. Subagents load at startup. If you create them with the /agents command they load immediately; if you edit them in your text editor, they don’t.

It inherits permissions from the parent. If your main session is in bypassPermissions, acceptEdits or auto, the subagent inherits it and can’t lower the level. The reverse does work: the parent can be in normal mode and the subagent run in plan.

Subagents can’t invoke other subagents. If you need to chain tasks, do it from the main conversation: “use the code-reviewer, then the optimizer on what it finds”. Claude handles passing the relevant context to the next one.

Logs live in their own place. Each invocation leaves a transcript in ~/.claude/projects/<project>/<session>/subagents/agent-<id>.jsonl. Useful when something went weird and you want to know what happened inside.

the summary, in one sentence

A subagent is a way of telling Claude “do this somewhere else and come back with the summary”. It’s worth it when what it does is noisy, restricted or repeated. It’s not worth it when what you need is to keep talking.

· ·