Subagents and Context Isolation
In the previous article we covered slash commands — the simplest way to codify a recurring request. A subagent is a different level of abstraction: not a prompt template, but a fully isolated Claude instance with its own context window, its own system prompt, and its own tool permissions. When a task would drown in your main conversation — voluminous logs, git history, test results — a subagent executes it in a separate space and returns only the outcome.
How isolation works
Every subagent starts with a fresh context window. It cannot see your conversation history, files Claude has already read, or skills that have already been invoked. Claude itself composes the delegation message — a concise description of the task — and the subagent works from scratch.
What a subagent receives at startup:
- System prompt — the body of its markdown file plus environment details (working directory, tool versions). Not the full Claude Code system prompt.
- CLAUDE.md and memory — all levels of the memory hierarchy that are loaded in the main session. Exception: the built-in Explore and Plan subagents deliberately skip these to stay fast and cheap.
- Git status — a snapshot of the repository state at the time the parent session started.
- Preloaded skills — if the frontmatter includes a
skillsfield, their contents are injected into the context immediately.
Everything else — conversation history, intermediate files, results of past calls — stays in the main session and does not "leak" into the subagent.
flowchart TD
User(["You"])
Main["Main session\n(context window)"]
Agent1["Subagent A\n(isolated context)"]
Agent2["Subagent B\n(isolated context)"]
User -->|"request"| Main
Main -->|"delegates task + brief context"| Agent1
Main -->|"delegates task + brief context"| Agent2
Agent1 -->|"returns result only"| Main
Agent2 -->|"returns result only"| Main
subgraph SubA ["Subagent A"]
Agent1
T1["Read / Bash / Grep..."]
M1["Own CLAUDE.md\n+ memory"]
Agent1 --- T1
Agent1 --- M1
end
subgraph SubB ["Subagent B"]
Agent2
T2["Read / Bash / Grep..."]
M2["Own CLAUDE.md\n+ memory"]
Agent2 --- T2
Agent2 --- M2
endBuilt-in subagents
Claude Code ships with several pre-configured subagents that Claude selects automatically:
| Subagent | Model | Tools | When used |
|---|---|---|---|
| Explore | Haiku | Read-only | Searching and navigating the codebase |
| Plan | Inherits from session | Read-only | Gathering context in plan mode |
| general-purpose | Inherits from session | All tools | Complex multi-step tasks |
| statusline-setup | Sonnet | Read + Edit | Configuring the status line |
| claude-code-guide | Haiku | — | Questions about Claude Code features |
Explore is the most frequent visitor: when Claude needs to understand a project's structure before implementing something, it launches Explore on Haiku, and the mountains of grep results settle into a separate context without cluttering your conversation.
You can disable a specific subagent via permissions.deny in settings.json:
{
"permissions": {
"deny": ["Agent(Explore)", "Agent(Plan)"]
}
}Creating a custom subagent
A subagent is a markdown file with YAML frontmatter. The structure is the same as for slash commands, but the semantics differ: the file body becomes the subagent's system prompt, not an instruction for the main Claude.
---
name: code-reviewer
description: Reviews code for quality, security, and best practices. Use proactively after significant code changes.
tools: Read, Glob, Grep, Bash
model: sonnet
color: blue
---
You are a senior code reviewer. When invoked, analyze the specified code and provide
specific, actionable feedback organized by severity (critical / warning / suggestion).
For each finding: describe the issue, show the affected code, and propose a fix.The file can be placed in two locations:
| Path | Scope |
|---|---|
.claude/agents/<name>.md | This project only |
~/.claude/agents/<name>.md | All your projects |
Subagents in .claude/agents/ should be committed to the repository — that way the whole team gets them automatically.
Important: files are picked up only when a session starts. If you created a file manually on disk — restart claude. Subagents created via /agents take effect immediately.
All frontmatter fields
Only name and description are required. Everything else is optional:
---
name: db-analyst # unique identifier (lowercase + hyphens)
description: Analyze query performance and suggest indexes. Use when user mentions slow queries.
tools: Read, Bash, Grep # tool allowlist
disallowedTools: Write # denylist (applied first if both are set)
model: haiku # sonnet | opus | haiku | fable | inherit | full model ID
permissionMode: acceptEdits # default | acceptEdits | auto | dontAsk | bypassPermissions | plan
maxTurns: 20 # maximum number of agentic steps
effort: high # low | medium | high | xhigh | max
isolation: worktree # run in an isolated git worktree
memory: project # user | project | local — persistent memory
skills:
- api-conventions # skills preloaded into context
color: green # red | blue | green | yellow | purple | orange | pink | cyan
background: true # always run in the background
---A few details that are easy to miss:
model: haiku — subagents can run on a cheaper model. Routine code review, codebase search, log analysis — all of this works great on Haiku at a fraction of the Sonnet price.
isolation: worktree — creates a temporary git worktree, an isolated copy of the repository. This lets the subagent make changes without touching your working directory. The worktree is removed automatically if the subagent made no changes.
bypassPermissions in permissionMode — disables all permission prompts. Use only in isolated environments (Docker, sandbox). See the Permissions Model, Security, and Trust article for details.
mcpServers — you can give a subagent access to an MCP server that is not in the main session, isolating its tools from the main context:
---
name: browser-tester
description: Test features in a real browser using Playwright
mcpServers:
- playwright:
type: stdio
command: npx
args: ["-y", "@playwright/mcp@latest"]
---
Use Playwright to navigate, screenshot, and interact with web pages.For more on MCP, see the MCP and External Tool Integrations section.
How to invoke a subagent
Three ways, from soft to explicit:
Natural language — Claude decides on its own whether to delegate the task:
Use the code-reviewer subagent to look at my auth changes@-mention — guarantees that this specific subagent will be used for the task:
@"code-reviewer (agent)" look at the changes in auth/Session-wide mode — the --agent flag launches Claude Code so that the main thread itself operates under the subagent's system prompt:
claude --agent code-reviewerUseful when the entire session is dedicated to one type of work — for example, refactoring to a specific style.
The /agents command opens a TUI interface: the Running tab shows live and completed subagents, and Library shows all available ones (built-in, custom, and from plugins). You can also create a subagent there using a wizard, or ask Claude to generate one from a description.
Background or foreground
Every subagent runs either in the foreground (blocking the main conversation until it finishes) or in the background (in parallel, while you continue working).
- Foreground: permission requests are forwarded to your terminal — you see them and respond.
- Background: the subagent runs autonomously; if something requires a permission that was not pre-granted, the request is automatically rejected, but the subagent continues working.
Claude chooses the mode based on the task. You can ask explicitly: "run this in the background" — or press Ctrl+B while the task is already running.
Parallel research is one of the most effective patterns:
Research the authentication, database, and API modules in parallel using separate subagentsClaude will launch three background subagents simultaneously, each exploring its own area, and the results are synthesized in the main conversation. Note: each of the three returns its summary back — the main conversation context grows by the sum of all returns. If the results are large, the main context can also swell.
Nested subagents and chains
Starting with version 2.1.172, a subagent can spawn its own subagents. This is useful when a delegated task itself breaks down into parallel sub-tasks:
Use the code-reviewer subagent to find performance issues,
then use the optimizer subagent to fix themClaude will run the reviewer, collect a list of issues, and hand them off to the optimizer — the intermediate output never appears in your main conversation.
Nesting depth limit: a background subagent at depth level 5 can no longer spawn children. This is a safeguard against uncontrolled growth of parallel trees.
You can also resume a subagent after it has finished:
Use the code-reviewer subagent to review the authentication module
[Subagent completed]
Continue that code review and now analyze the authorization logicClaude will resume the subagent with its full conversation history — it remembers what it already reviewed.
Persistent subagent memory
The memory field gives a subagent a persistent directory that is preserved between sessions. The subagent writes its findings there — codebase patterns, recurring mistakes, architectural decisions — and reads them the next time it starts:
---
name: code-reviewer
description: Reviews code for quality and best practices
memory: project
---
You are a code reviewer. As you review code, update your agent memory with
patterns, conventions, and recurring issues you discover.| Scope | Path | When to use |
|---|---|---|
user | ~/.claude/agent-memory/<name>/ | Knowledge applies to all projects |
project | .claude/agent-memory/<name>/ | Knowledge is project-specific and should be shared with the team |
local | .claude/agent-memory-local/<name>/ | Project-specific, do not commit |
# Example file structure for the "code-reviewer" subagent
~/.claude/
└── agent-memory/
└── code-reviewer/
└── MEMORY.md # user scope: shared across all projects
<project>/
└── .claude/
├── agent-memory/
│ └── code-reviewer/
│ └── MEMORY.md # project scope: committed to the repository
└── agent-memory-local/
└── code-reviewer/
└── MEMORY.md # local scope: in .gitignore, only for youThe subagent automatically receives an instruction to read its MEMORY.md at startup. Recommendation: explicitly ask the subagent to update its memory after completing a task: "now save what you learned to memory." Over time, an institutional knowledge base accumulates.
When a subagent is worth it
Sometimes it's simpler to stay in the main conversation. A subagent is not a cure-all:
Use a subagent if:
- The task produces large output (tests, logs, documentation) that is not needed in the main context
- A specific combination of tools or permissions is required
- The work is self-contained and reduces to a final summary
- You want to run several independent investigations in parallel
Stay in the main conversation if:
- The task requires frequent clarifications and iterations
- Several phases of work are tightly coupled by context (plan → implementation → tests)
- The change is small and targeted
- Latency matters — a subagent starts from scratch and takes time to build up context
Choose a skill instead of a subagent when you want a reusable prompt or procedure executed in the main context — no isolation needed.
For a quick question whose answer doesn't need to be saved to history, there is /btw — it asks the question in a side context without creating a subagent.
Practical example: a code review agent with memory
---
name: pr-reviewer
description: Review pull requests for quality, security, and conventions. Use when user asks to review PR or code changes.
tools: Read, Glob, Grep, Bash
model: sonnet
memory: project
color: purple
---
You are a senior engineer doing code review. Review the specified code or PR.
Before reviewing, check your MEMORY.md for:
- Known patterns and conventions in this codebase
- Recurring issues to watch for
- Architectural decisions already made
Provide feedback organized by severity:
- 🔴 Critical: must fix before merge
- 🟡 Warning: strongly recommended
- 🟢 Suggestion: optional improvement
After reviewing, update MEMORY.md with:
- New patterns you discovered
- Issues you found that may recur
- Anything that helps future reviewsThe first time, this subagent performs a code review "blind," like any other. Over time it builds its own map of the project: it knows that this codebase logs through logger.structured(), that utils/auth.ts is a historically problematic spot, and that tests by convention belong in __tests__/.
For more on organizing a set of subagents, commands, and skills into a reusable bundle, see the Plugins and marketplace article. The decision matrix for all extensibility mechanisms is in What to choose: command, skill, subagent, MCP, or hook.
See also
- Slash commands: built-in and custom — a lighter mechanism for prompt templates without context isolation
- Skills — portable expertise — reusable expertise in the main context, no isolation required
- Hooks — lifecycle events — deterministic shell commands on SubagentStart/SubagentStop events
- What to choose: command, skill, subagent, MCP, or hook — the decision matrix for all extensibility mechanisms
- Permissions model, security, and trust — more on bypassPermissions and permissionMode
- CLAUDE.md and the memory system — how the memory hierarchy loads into subagents
- Managing the context window — why subagent isolation helps keep the main context clean
- Plugins and marketplace — how to package subagents together with commands and hooks into a single bundle
- Dynamic workflows and agent orchestration — scaling up to full agent teams with independent contexts