The Navigator · 12 min mission

Subagents: Delegation Without Context Pollution

Fan work out to specialist agents and keep your main thread clean.

agentsdelegationarchitectureFact-checked 2026-06-13
On this page

Ask Claude to "investigate how authentication works" and watch what happens: it reads a dozen files, greps for a handful of symbols, and dumps every line of all of it into your main conversation. You wanted a three-sentence answer. You got three sentences plus four thousand lines of source you will never look at again — now permanently parked in your context window, crowding out the actual work.

A subagent is the fix. It is a separate Claude instance with its own fresh context window that does the messy work — the reading, the grepping, the log-spelunking — out of sight, and returns only the summary to your main conversation. The exploration happened; the clutter did not follow it home.

That fresh window is the whole point: a subagent does not see your conversation history, the skills you already invoked, or the files Claude already read. Claude writes a short delegation message describing the task, the subagent works from there, and when it finishes only its final result comes back — the dozens of files it read along the way stay in its window, not yours.

Why subagents exist

Two distinct problems, one tool. The first is context isolation. The official docs are direct about the use case: reach for a subagent when a side task would flood your main conversation with search results, logs, or file contents you won't reference again. The subagent does that work in its own context and hands back the relevant summary. Your main window stays lean for the thing you are actually building.

The second is specialization. A subagent has its own system prompt, its own restricted set of tools, and its own model. That lets you carve out a focused worker — a security reviewer, a test-runner, a database analyst — that behaves differently from your general session. You can hand it a sharp, narrow brief and a sharp, narrow toolbelt, and it will not wander.

Per the docs, subagents help you preserve context, enforce constraints by limiting which tools a subagent can use, reuse configurations across projects, specialize behavior with focused prompts, and control costs by routing work to faster, cheaper models like Haiku.

Built-in agents you already use

You have been using subagents without defining any. Claude Code ships with built-in subagents it delegates to automatically. Explore is a fast, read-only agent (running on Haiku) for searching and analyzing a codebase — Claude sends it off when it needs to understand code without changing anything, so the search output never lands in your main window. Plan gathers context during plan mode. general-purpose is the capable all-rounder for multi-step tasks that need both exploration and action.

Custom subagents are how you go further: your own prompts, your own tool restrictions, your own model, saved as files and shared with your team. The rest of this guide is about building those.

Where subagents live

A subagent is just a Markdown file with a YAML frontmatter block. Where you put the file decides its scope. Project subagents live in .claude/agents/ and ship to your team through version control — check them in so everyone benefits. User subagents live in ~/.claude/agents/ and follow you across every project on your machine. Claude Code scans both directories recursively, so you can organize definitions into subfolders like agents/review/ without changing how an agent is named — identity comes only from the name field, not the path.

When two subagents share a name, the higher-priority location wins. Managed (organization-deployed) definitions outrank a per-session --agents CLI flag, which outranks project files, which outrank your user files, which outrank plugin-provided agents.

LocationScopeBest for
Managed settingsOrganization-wideStandards IT or DevOps deploys to every machine
--agents CLI flagCurrent session onlyQuick testing and automation scripts (not saved to disk)
.claude/agents/Current projectAgents specific to a codebase; check into git
~/.claude/agents/All your projectsPersonal agents you want everywhere
Plugin's agents/Where the plugin is enabledAgents distributed through a plugin
Where subagent definitions can live, highest priority first. When names collide, the higher-priority scope wins.

Anatomy of a definition

The frontmatter configures the agent; the Markdown body becomes its system prompt. Only two fields are required: name (a unique lowercase-and-hyphens identifier) and description (when Claude should delegate to it). Everything else is optional and has a sensible default.

The four fields you will reach for most:

  • name — the identifier Claude and you use to invoke it. The filename does not have to match.
  • description — the single most important field, because Claude reads it to decide when to delegate. Write it like a job posting, not a label.
  • tools — an allowlist of tools the agent may use. Omit it and the agent inherits every tool the main conversation has.
  • modelsonnet, opus, haiku, fable, a full model ID like claude-opus-4-8, or inherit. If you omit it, the default is inherit — the agent uses whatever model your main session is on.

The body below the frontmatter is plain prose that tells the agent who it is and how to work. Subagents receive only this prompt plus basic environment details — not the full Claude Code system prompt — so write it to stand on its own.

.claude/agents/security-reviewer.md
markdown
---
name: security-reviewer
description: Reviews code for security vulnerabilities. Use proactively after writing or modifying code that handles input, auth, or secrets.
tools: Read, Grep, Glob, Bash
model: opus
---
 
You are a senior security engineer. Review code for:
- Injection vulnerabilities (SQL, XSS, command injection)
- Authentication and authorization flaws
- Secrets or credentials committed in code
- Insecure data handling
 
Provide specific line references and suggested fixes. You cannot
edit files — report findings only.

Description-driven delegation

Here is the part that surprises people: you usually do not invoke a subagent by name at all. Claude automatically delegates based on three things — the task description in your request, the description field in each subagent's configuration, and the current context. When the task matches a description, Claude hands it off on its own.

This makes the description field load-bearing. "Reviews code" is weak; Claude has little to match against. "Expert code review specialist. Proactively reviews code for quality, security, and maintainability. Use immediately after writing or modifying code" is strong — it tells Claude both what the agent does and when to reach for it. The docs note that adding phrases like "use proactively" to the description encourages Claude to delegate without being asked.

When automatic delegation is not enough, you escalate. There are three explicit patterns, from gentle nudge to session-wide default:

  • Natural language — name the agent in your prompt ("use the test-runner subagent to fix failing tests") and Claude almost always delegates, though the choice is still its own.
  • @-mention — type @ and pick the agent from the typeahead. This guarantees that specific agent runs for the task rather than leaving it to Claude.
  • Session-wide — launch with claude --agent code-reviewer and the whole session takes on that agent's system prompt, tools, and model.
automatic delegation in action
… scroll to run this session
Notice the give-away: the verbose research happens inside the subagent and only the summary returns. Your main context stays clean.

Parallel dispatch

Because each subagent runs in its own window, you can run several at once. For independent investigations, ask Claude to spawn multiple subagents to work simultaneously — research the authentication, database, and API modules in parallel, each in a separate agent, then let Claude synthesize the findings. This works best when the research paths do not depend on each other; if step two needs step one's answer, parallelism buys you nothing.

There is a real cost to watch. When subagents finish, their results return to your main conversation — and running many agents that each return detailed results can itself consume significant context. The summary is small; ten verbose summaries are not. The official guidance for sustained parallelism that would overflow your window is to graduate to agent teams, where each worker keeps its own independent context. For most day-to-day work, a handful of parallel research agents returning tight summaries is exactly the right tool.

Scoping tools: the principle of least privilege

The tools field is where subagents earn their keep as a safety mechanism. A reviewer that only needs to read should never be handed Write or Edit. Restrict it with an allowlist — tools: Read, Grep, Glob, Bash — and the agent physically cannot edit files, no matter how its prompt drifts. The inverse field, disallowedTools, starts from "inherit everything" and subtracts: disallowedTools: Write, Edit keeps Bash and MCP tools but removes the ability to change files. If you set both, the denylist is applied first, then the allowlist resolves against what remains.

The official best practices put it plainly: grant only the necessary permissions, for security and for focus. A tightly scoped agent is not just safer — it is better at its job, because it cannot be distracted into doing something off-task.

The model field is the matching cost lever. A read-only search or a log-summarizing agent does not need a frontier model — set model: haiku and it runs fast and cheap while your main session stays on Opus or Sonnet for the reasoning that matters. Reserve model: opus for agents doing genuinely hard analysis, like deep security review. Matching both the toolbelt and the model to the task is one of the simplest wins subagents offer.

When NOT to use a subagent

Subagents are a context tool, not a default. The docs are explicit about when the main conversation is the better choice: when the task needs frequent back-and-forth or iterative refinement; when multiple phases share significant context (planning, then implementation, then testing all leaning on the same understanding); when you are making a quick, targeted change; and when latency matters, because a subagent starts fresh and may need time to gather context before it can act.

Reach for a subagent instead when the task produces verbose output you do not need in your main context, when you want to enforce specific tool restrictions, or when the work is self-contained and can return a clean summary. And there is a sibling tool to keep in mind: when you want a reusable prompt or workflow that runs in your main conversation rather than in an isolated window, a Skill is the right call, not a subagent.

The trap to avoid is reflexively delegating everything. A subagent that has to be re-briefed because it cannot see your conversation, for a task that needed your context anyway, is slower and worse than just doing the work inline. Isolation is the feature — and the cost.

Orchestrate a fleet of subagents

Watch delegation happen

The orchestrator hands a slice of work to each subagent. Every subagent runs in its own context window, does the noisy part — searching, reviewing, running tests — and returns only a short summary. Dispatch them and watch the work fan out, then the results pulse home.

orchestrator · main thread
ready
exploreridlerevieweridletesteridleimplementeridleorchestrator

The roster

exploreridle

Searches and maps the codebase without editing.

model · Haiku 4.5

revieweridle

Read-only pass for bugs, style, and risk.

model · Sonnet 4.6

testeridle

Runs the suite and reports failures.

model · Haiku 4.5

implementeridle

Writes the focused change end to end.

model · Opus 4.8

Idle. Four subagents waiting for the orchestrator to dispatch work.

Dispatch specialized agents — explorer, reviewer, test-runner — and watch how parallel work in isolated windows returns only summaries to the conductor. This is the delegation pattern made visible.

Subagent vs. main conversation

Delegate to a subagent

Running the full test suite to surface just the failures. Reading 40 files to answer one question. A security pass that must never edit code.

Verbose, self-contained, returns a summary — the clutter stays in the agent's window.

Keep it in the main session

A tight edit-run-fix loop on one file. A planning phase whose context the implementation phase will reuse. A one-line typo fix.

Shared context and fast iteration matter more than isolation — delegating would just add latency and re-briefing.

Knowledge check

You are about to ask Claude to read your entire test suite output and migration logs to find why one integration test is flaky. What is the cleanest way to keep your main session usable?

Give it an isolated checkout: isolation: worktree

By default a subagent starts in your main conversation's working directory and edits the same files you have open. [V] A cd inside the subagent does not persist between its Bash calls and does not move the main session's directory — but it is still writing to your checkout. For a delegated task that should not touch your working tree until you have reviewed it, set isolation: worktree in the frontmatter. [V]

That single field hands the subagent a temporary git worktree — its own isolated copy of the repository. [V] One detail worth internalizing: the worktree is branched by default from your default branch, not from the parent session's HEAD. [V] So a worktree subagent does not inherit your uncommitted local work; it starts from a clean baseline. And if the subagent makes no changes, Claude Code cleans the worktree up automatically — no stray branches to garbage-collect. [V] This is the move when you want a reviewer or a refactor agent to propose changes in a sandbox you can diff, rather than mutate the files under your cursor.

Persistent memory: memory: project | user | local

Every subagent starts with a fresh, empty context — that is the whole design. But "fresh every time" also means a reviewer that learned your codebase's quirks last week relearns them from scratch today. The memory field is the escape hatch: it gives the subagent a persistent directory that survives across conversations, so it can accumulate codebase patterns, conventions, and recurring issues over time. [V]

The value picks the scope, and the scope decides where the directory lives and who sees it: [V]

  • project.claude/agent-memory/<name>/. Project-specific and shareable via version control. The docs call this the recommended default. [V]
  • user~/.claude/agent-memory/<name>/. Follows the agent across every project, for knowledge that is broadly applicable. [V]
  • local.claude/agent-memory-local/<name>/. Project-specific but deliberately not checked into version control. [V]

There is a consequence worth flagging up front: turning on memory automatically enables the Read, Write, and Edit tools so the agent can manage its own memory files. [V] A reviewer you scoped to tools: Read, Grep, Glob precisely so it could not write will suddenly hold Write and Edit the moment you add memory: project. The subagent's system prompt also gets instructions for using the directory, plus the first 200 lines (or 25KB, whichever comes first) of its MEMORY.md. [V] Add memory deliberately, not reflexively — and re-check your tool scoping when you do.

`memory` valueDirectoryChecked into git?Use when
project.claude/agent-memory/<name>/YesKnowledge is project-specific and worth sharing (recommended default)
user~/.claude/agent-memory/<name>/No (your home dir)Knowledge applies across all your projects
local.claude/agent-memory-local/<name>/No (gitignored)Project-specific knowledge you do not want committed
Persistent-memory scopes for the `memory` field. Enabling any of them auto-enables Read, Write, and Edit.

Subagents that spawn subagents

For a long time a subagent was a leaf: it could not delegate further. As of Claude Code v2.1.172, a subagent can spawn its own subagents. [V] The use case is recursive fan-out — a reviewer subagent that dispatches a verifier per finding, for instance — so the intermediate output never reaches your main conversation and only the top-level subagent's summary returns to you. [V] A nested subagent is configured exactly like a top-level one and resolves from the same scopes. [V]

What makes a subagent able to nest is the Agent tool (renamed from Task in v2.1.63; old Task(...) references still work as aliases). [V] If Agent is in a subagent's tools list, it can spawn children; omit it, or add it to disallowedTools, and that subagent is a leaf again. [V] One subtlety: inside a subagent definition, listing Agent(worker, researcher) with a type list does not restrict anything — the parentheses are ignored, and the Agent(agent_type) allowlist only constrains an agent running as the main thread via claude --agent. [V]

Depth has a hard ceiling, and it differs by run mode. Foreground subagents can nest at any depth — each level blocks its parent, so the chain is self-limiting because the main conversation waits on the whole thing. Background subagents are capped: a background subagent at depth five does not receive the Agent tool and cannot spawn further. [V] That limit is fixed, not configurable, and exists to stop runaway concurrent trees. [V] A fork (next section) still cannot spawn another fork, though it can spawn named subagents, and those count toward the depth limit. [V]

Forking: a subagent that inherits your whole conversation

Every subagent so far starts fresh — no conversation history, no files you already read. A fork is the deliberate exception. It is a subagent that inherits the entire conversation so far: the same system prompt, tools, model, and full message history as your main session. [V] You drop the input isolation on purpose, so you can hand off a side task without re-explaining the situation — but the fork's own tool calls still stay out of your conversation and only its final result returns, so your main window stays clean. [V]

Two ways to reach for it. The /fork command takes a directive inline — /fork draft unit tests for the parser changes so far — and Claude Code names the fork from its first words, then runs it in a panel below your prompt while you keep working. [V] As of v2.1.161 the /fork command is enabled by default (it requires v2.1.117+); on earlier builds you switch it on with the CLAUDE_CODE_FORK_SUBAGENT environment variable. [V] Set CLAUDE_CODE_FORK_SUBAGENT=1 to force fork mode on, or =0 to force it off — the variable is honored in interactive mode, headless mode, and the Agent SDK. [V]

Enabling fork mode changes two behaviors: Claude spawns a fork wherever it would otherwise use the general-purpose subagent (named agents like Explore still spawn as before), and every subagent spawn runs in the background. [V] Because a fork's system prompt and tools are byte-identical to the parent, its first request reuses the parent's prompt cache — which makes forking cheaper than spawning a fresh subagent for tasks that need the same context. [V] A fork cannot spawn another fork, but Claude can pass isolation: "worktree" when it forks so the fork's edits land in a separate worktree rather than your checkout. [V]

Fork vs. named subagent

Fork (`/fork` or `CLAUDE_CODE_FORK_SUBAGENT=1`)

Inherits the full conversation history, system prompt, tools, and model from your main session. [V] Permission prompts surface in your terminal. Its first request reuses the parent prompt cache, so it is cheaper for same-context side tasks.

Use when a named subagent would need too much background to be useful, or to try several approaches from the same starting point. Cannot spawn another fork.

Named subagent (the Agent tool)

Starts from a fresh, isolated context with only the prompt Claude writes. System prompt, tools, and model come from its definition file; cache is separate. [V]

Use when isolation is the point — verbose research, strict tool scoping, a self-contained task that returns a clean summary. Can spawn nested subagents if it holds the Agent tool.

Case study: restrict a delegation subagent to one CLI

A clean way to see tool scoping, plugins, and the Bash() allowlist syntax converge is the official codex-rescue subagent, distributed in the openai/codex-plugin-cc plugin as the file agents/codex-rescue.md. [V] Its job is narrow: forward a stuck or substantial task to the Codex CLI through a shared runtime and do nothing else. Once the plugin is enabled you invoke it like any plugin agent — @agent-codex:codex-rescue from the typeahead, or session-wide with claude --agent codex:codex-rescue. [V]

A forwarding wrapper like this is the textbook case for the tightest possible toolbelt: it should be able to shell out to one command and nothing else. The canonical way to express "Bash, but only the codex CLI" is the prefix-match allowlist Bash(codex:*). [V] The :* suffix is the documented trailing-wildcard form — Bash(codex:*) matches the same commands as Bash(codex *), anchoring the rule to the codex command prefix. [V] Scoped this way, the agent physically cannot run rm, git push, or any other binary, no matter how its prompt is steered.

One sharp edge specific to plugin subagents: for security, plugin-provided agents silently ignore the hooks, mcpServers, and permissionMode frontmatter fields. [V] They are dropped at load time with no error. So you cannot harden a plugin subagent by adding a PreToolUse hook or a permissionMode inside its file — those lines are inert. If you need them, copy the agent file into .claude/agents/ or ~/.claude/agents/ where the fields take effect, or add the rules to permissions.allow in settings.json (noting that those rules then apply to the whole session, not just the one agent). [V]

.claude/agents/codex-delegator.md — a Bash-to-one-CLI wrapper
markdown
---
name: codex-delegator
description: Forwards a stuck or substantial coding task to the Codex CLI. Use proactively when the main thread should hand off a deep investigation or implementation pass.
tools: Bash(codex:*)
model: sonnet
---
 
You are a thin forwarding wrapper around the Codex CLI. Your only job is
to shape the user's request into a clear Codex prompt and forward it with
a single `codex` invocation. Do not read files, grep, or do independent
work — the `Bash(codex:*)` allowlist means `codex` is the only command
you can run.

Reach the end and this star joins your charted sky.