All sections

07Extending

Agents, subagents and forks

A markdown file in .claude/agents/ defines a separate execution context with its own window, prompt, tools and model. The same file can be run three different ways, and the difference between them is placement, not format.

What a subagent is

A markdown file in .claude/agents/ that defines a separate execution context. Unlike memory, rules and skills, which modify your conversation, a subagent gets:

  • its own context window
  • its own system prompt (the file body replaces the default)
  • its own tool allowlist
  • its own model
  • its own permission mode

It does its work in isolation and returns only a summary to your conversation. That isolation is the entire point.

graph TD
    subgraph MAIN["Main conversation your context window"]
        U["Your prompt"] --> C["Claude"]
        C --> D{"Delegate?"}
        D -->|"No"| R1["Direct answer"]
        D -->|"Yes"| SPAWN["Spawn subagent"]
        SUM["Summary returns<br/><i>~200 tokens</i>"] --> C2["Claude continues"]
    end

    subgraph SUB["Subagent separate context window"]
        SPAWN --> SP["Own system prompt"]
        SP --> W["Reads 40 files<br/>runs test suite<br/><i>~80,000 tokens</i>"]
        W --> COND["Condense to findings"]
    end

    COND --> SUM

The 80,000 tokens never enter your conversation. That is why subagents are the right answer for log triage, test-output analysis, and codebase archaeology.

Anatomy

---
name: log-triage
description: Parses large log dumps and reports only the relevant failures. Use when investigating a test failure or a production incident with more than ~200 lines of logs.
tools: Read, Grep, Glob, Bash
model: haiku
---

You triage logs. Read the indicated files, find the first error in causal
order — not downstream noise — and report:

- The failing component and the root error
- Stack frames belonging to our code, not framework frames
- The three log lines immediately preceding the failure

Do not summarise healthy log lines. Do not speculate about fixes.
Output at most 30 lines.

model: haiku is doing real work here: high-volume, low-judgement grep work at a fraction of the cost, and none of it touches your main context.

Tool restriction is a real boundary

The tools: list is enforced outside the model. An agent without Write and Edit cannot modify code, no matter what it concludes it should do. This is the difference between asking for a read-only review and having one.

---
name: security-reviewer
description: Reviews a diff for security defects. Use before merging anything touching auth, input parsing, or outbound requests.
tools: Read, Grep, Glob, Bash(git diff *), Bash(git log *)
model: opus
---

You review diffs for security defects only. You cannot edit files, and you
should not propose a patch as a diff; describe the fix in prose.

Report only findings you can point at with a `file:line`. For each:

- **What** an attacker can do
- **How** they reach the code path from an untrusted input
- **Confidence**: certain / likely / speculative

Rank by exploitability, not by how interesting the bug is. If you find nothing,
say so in one line rather than padding the report with observations.

Note the Bash(git diff *) scoping: the agent can read the diff but cannot run arbitrary shell commands. Giving a subagent broad Bash “just in case” quietly defeats the isolation you set it up for.

More agents worth having

---
name: test-analyst
description: Runs the test suite and reports the failures that share a root cause. Use after a refactor, or when a CI run has more than a handful of failures.
tools: Read, Grep, Glob, Bash
model: sonnet
---

Run the suite, then group the failures by *cause*, not by file.

For each group: the shared root cause, the number of tests it explains, and one
representative failure with its assertion. Order groups by how many tests they
explain. Explicitly list any failure you could not attribute to a group.

Never edit code. Never re-run a single test to "confirm" — one full run is
enough.
---
name: dependency-archaeologist
description: Traces every caller and every implementation of a symbol across the repository. Use before renaming, deleting, or changing the signature of anything shared.
tools: Read, Grep, Glob
model: haiku
---

Given a symbol, produce a complete call map:

- Direct callers, with `file:line`
- Indirect reach: anything that wraps a direct caller and is itself exported
- Test-only callers, listed separately
- Any dynamic reference — reflection, string lookup, generated code, config —
  that a grep for the identifier would find but a compiler would not

State explicitly whether the change is safe to make mechanically. Read only.

Three ways to run an agent definition

The same file can occupy three different positions. This is the distinction between “agent” and “subagent” that trips people up: they are not different artifacts, they are different placements.

graph TD
    DEF["Agent definition<br/>.claude/agents/reviewer.md"]

    DEF --> S["SUBAGENT<br/>Claude delegates via the Agent tool,<br/>or you @-mention it"]
    DEF --> M["MAIN-SESSION AGENT<br/>claude --agent reviewer<br/>or agent: in settings.json"]
    DEF --> F["FORK<br/>/subtask &lt;task&gt;"]

    S --> S1["Fresh context<br/>Own system prompt<br/>Returns a summary"]
    M --> M1["Entire session adopts it<br/>Default Claude Code<br/>system prompt is replaced"]
    F --> F1["Inherits your full conversation<br/>Same prompt, tools, model<br/>Reuses the prompt cache"]
Mode Start it with Context Use when
Subagent Claude delegates, or @reviewer Fresh, empty A side task that would flood your context, or one needing hard tool restrictions
Main-session agent claude --agent reviewer, or "agent": "reviewer" in settings Yours, but with a replaced system prompt You want every turn this session to behave a certain way
Fork /subtask <task> Inherits everything so far The task needs the conversation you’ve already had, but its output shouldn’t clutter your transcript

Concrete guidance:

  • Subagent: “run the full test suite and tell me what failed”, “trace every caller of this function across the repo”, “audit internal/ for direct time.Now() calls”. Also: a reviewer agent whose tools: list omits Write and Edit, so it cannot modify code even if it decides it should.
  • Main-session agent: launching claude --agent security-reviewer for a dedicated review session, or pinning a repository’s default posture in settings.json.
  • Fork: “now write the tests for what we just built” while you keep going on the implementation. Cheaper than a fresh subagent because it reuses the parent’s prompt cache.

Related but distinct: subagents all live inside a single session. For genuinely parallel long-running work you want separate sessions, not subagents.

Choosing between a subagent and a fork

flowchart TD
    Q["A side task needs doing"] --> A{"Does it need the<br/>conversation so far?"}
    A -->|"No"| B{"Will it read a lot,<br/>or need restricted tools?"}
    B -->|"Yes"| SUB["Subagent"]
    B -->|"No"| INLINE["Just do it inline"]
    A -->|"Yes"| C{"Should its output stay<br/>out of the transcript?"}
    C -->|"Yes"| FORK["Fork — /subtask"]
    C -->|"No"| INLINE

The mistake in both directions is common: spawning a subagent for a task that needs the last twenty minutes of conversation (it starts cold and re-derives everything), or doing an 80,000-token log read inline because it felt simpler than delegating.

Where agents live, and their precedence

Priority Location
1, highest Enterprise managed settings
2 --agents CLI flag (session-only JSON)
3 .claude/agents/, project
4 ~/.claude/agents/, user
5, lowest Plugin agents/ directory

This runs opposite to skills. For agents, project beats user. For skills, user beats project. There is no mnemonic; you simply have to know it. See skills vs agents.

Verify with /agents, which lists each available agent and the file it came from.

Built-in subagents

Explore and Plan ship with Claude Code. Both skip your CLAUDE.md files and the parent session’s git status to keep research fast and cheap. Every other built-in and every custom subagent loads both.

Practical consequence: if Explore seems to ignore a project convention, that is by design. Put anything Explore must respect into the prompt you give it, not into CLAUDE.md.