CC6: Subagents
Specialist agents that run in their own context window with their own tools and (optionally) their own memory. Use them when a task would otherwise flood your conversation with noise — or when you want to lock down what one specific worker can do.
Learning Objectives
- Decide between subagent / fork / skill / main-conversation for a given task.
- Know the 5 built-in subagents (Explore, Plan, general-purpose, statusline-setup, Claude Code Guide) and when each fires.
- Drop a custom subagent into
.claude/agents/using the 16 frontmatter fields correctly. - Invoke subagents three ways: natural language,
@agent-namemention,--agentwhole-session. - Configure persistent
memory:so a subagent learns across sessions. - Use foreground / background / fork modes appropriately.
Why Subagents
Imagine you're the lead architect on a project and someone asks "is the database schema consistent with the API contracts?" You could read every migration file and every controller yourself, but the answer is going to be 30 lines and the work is 3 hours of squinting. Better: hand it to a junior who specializes in schema review, let them read everything in their own corner, and have them come back with the verdict.
You stay focused on the architecture conversation. The junior's "I read 47 files" doesn't show up in your office. You only see "yes, consistent — except orders.status drifts from OrderStatus in the OpenAPI spec." That's the deal.
Subagents are that junior. Each runs in its own context window, gets a focused prompt, optionally has its own narrow tool allowlist, and returns just the summary. Your main conversation stays clean and high-level.
A subagent is a Markdown file with YAML frontmatter at .claude/agents/<name>.md (or ~/.claude/agents/). When Claude detects a task matching a subagent's description, it spawns the subagent in a new context window, hands it a focused prompt, and waits for the result. The subagent's tool calls don't appear in your main transcript.
Use a subagent when: the task produces verbose output you don't need, you want to enforce specific tool restrictions, or the work is self-contained and can return just a summary.
Don't use one when: the task needs frequent back-and-forth, multiple phases share significant context, or you're making a quick targeted change. Latency matters — subagents start fresh and need time to gather context.
5 Built-in Subagents — Already Available
Claude Code ships with these. Don't re-invent.
| Subagent | Model | Tools | When Claude uses it |
|---|---|---|---|
Explore | Haiku | Read-only | Codebase search at quick, medium, or very thorough |
Plan | inherit | Read-only | Research during plan mode — prevents nesting |
general-purpose | inherit | All | Multi-step work needing both exploration AND modification |
statusline-setup | Sonnet | Read, Edit | When you run /statusline |
Claude Code Guide | Haiku | WebFetch, WebSearch | When you ask "how do I … in Claude Code?" |
You can disable any of these with "deny": ["Agent(Explore)"] in permissions. You can override their behavior by creating a same-named custom agent at higher priority.
The 5-Tier Scope Hierarchy
When name conflicts happen, the highest-priority definition wins:
| Priority | Scope | Path |
|---|---|---|
| 1 | Managed | Organization-wide via managed settings |
| 2 | --agents CLI | JSON passed at launch — session-only, never saved |
| 3 | Project | .claude/agents/ — checked into git, team-shared |
| 4 | User | ~/.claude/agents/ — personal, all your projects |
| 5 | Plugin | <plugin>/agents/ — namespaced as plugin:agent |
Browse them with /agents (interactive UI for create/edit/inspect) or claude agents (CLI list grouped by source).
Your First Custom Subagent
The classic example: a code-reviewer with read-only tools and a focused prompt. Drop this at .claude/agents/code-reviewer.md:
---
name: code-reviewer
description: Expert code review specialist. Proactively reviews code for quality, security, and maintainability. Use immediately after writing or modifying code.
tools: Read, Grep, Glob, Bash(git diff*), Bash(git log*)
model: sonnet
color: orange
---
You are a senior code reviewer ensuring high standards.
When invoked:
1. Run git diff to see recent changes
2. Focus on modified files only
3. Begin review immediately
Review checklist:
- Code is clear and readable
- No exposed secrets or API keys
- Proper error handling
- No duplicated code
- Tests cover the new behavior
Provide feedback organized by priority:
- CRITICAL (must fix before merge)
- WARNING (should fix)
- SUGGESTION (consider)
Include specific examples of how to fix each issue.
Now in any session: "have the code-reviewer subagent look at my recent changes." Claude spawns it, the reviewer runs git diff in its own context, reads the modified files, and returns a structured report — without those file reads polluting your main transcript.
Subagent Frontmatter — All 16 Fields
Only name and description are required. Everything else lets you tighten tool access, lock the model, scope MCP, attach hooks, or carve out an isolated workspace.
| Field | Purpose |
|---|---|
name | Lowercase-hyphen identifier; unique within scope |
description | When Claude should delegate — include "use proactively" to encourage it |
tools | Allowlist (e.g. Read, Grep, Bash); inherits all if omitted |
disallowedTools | Denylist applied first; tools resolves against the remainder |
model | sonnet, opus, haiku, full ID, or inherit (default) |
permissionMode | default, acceptEdits, auto, dontAsk, bypassPermissions, plan |
maxTurns | Hard cap on agentic turns — safety circuit breaker |
skills | Skills preloaded at startup — full body injected (vs description-only in main session) |
mcpServers | Inline server defs (scoped) or string refs to existing servers |
hooks | Lifecycle hooks scoped to this subagent only — cleaned up on finish |
memory | user / project / local — persistent MEMORY.md across sessions |
background | true → always run concurrently with permission pre-approval |
effort | low / medium / high / xhigh / max — thinking budget |
isolation | worktree → runs in temp git worktree — auto-cleaned if no changes |
color | red blue green yellow purple orange pink cyan — UI badge |
initialPrompt | Auto-submitted first user turn when run as main session via --agent |
For security, plugin-distributed subagents silently ignore hooks, mcpServers, and permissionMode. If you need them, copy the agent file into .claude/agents/ or ~/.claude/agents/. Plugin subagents appear in @-typeahead as @agent-<plugin>:<name>.
Three Ways to Invoke a Subagent
Beyond auto-delegation based on description, three explicit invocation patterns escalate from one-off to session-wide:
# 1. Natural language — Claude usually delegates
> "Use the test-runner subagent to fix failing tests"
# 2. @-mention — guarantees this specific subagent runs once
> @agent-code-reviewer look at the auth changes
> @agent-acme-plugin:linter check src/api/
# 3. Whole-session agent — replaces the default system prompt for the entire session
$ claude --agent code-reviewer
# Pin it for every session in this project (.claude/settings.json):
{ "agent": "code-reviewer" }
# Bonus: list configured subagents
$ claude agents
# Bonus: define ad-hoc subagents for one session via JSON
$ claude --agents '{"reviewer":{"description":"Reviews code","prompt":"You are a senior reviewer.","tools":["Read","Grep"],"model":"sonnet"}}'
The full message you type still goes to Claude; @agent-X only controls which subagent Claude invokes, not the prompt body.
Persistent Memory — Subagents That Learn
Set memory: project (recommended default) and Claude Code creates a directory the subagent reads from and writes to across conversations. The first 200 lines (or 25 KB) of MEMORY.md are auto-injected into the subagent's system prompt; Read/Write/Edit are auto-enabled regardless of tools.
| Scope | Path | Best for |
|---|---|---|
user | ~/.claude/agent-memory/<name>/ | Cross-project learnings (universal review patterns) |
project | .claude/agent-memory/<name>/ | Codebase-specific knowledge, shareable via git (recommended) |
local | .claude/agent-memory-local/<name>/ | Project-specific but private — not committed |
Pattern: ask the subagent to consult and update its memory
Add this to the system prompt body:
Before reviewing, check your MEMORY.md for patterns and recurring issues
you've seen in this codebase. After completing a review, append new
patterns and useful insights to MEMORY.md so you're sharper next time.
Over a few weeks, the subagent builds up institutional knowledge about your codebase — the parts of the auth module that always come back broken, the conventions teammates keep violating, the gotchas. That's your knowledge graph living next to the code.
Foreground / Background / Fork — Three Execution Modes
Subagents run one of three ways:
| Property | Foreground | Background | Fork (/fork) |
|---|---|---|---|
| Blocks main session | yes | no | no |
| Starting context | fresh + Task prompt | fresh + Task prompt | full conversation |
| Permissions | interactive prompts | pre-approved at spawn | interactive prompts |
| Prompt cache | separate | separate | shared with parent |
| Trigger | default behavior | background: true or Ctrl+B | /fork <task> when fork mode on |
Foreground: blocks until done, surfaces permission prompts. Background: concurrent, permissions pre-approved at spawn (auto-denies anything else), can ask clarifying questions but won't — that tool call fails and it continues. Fork: experimental (CLAUDE_CODE_FORK_SUBAGENT=1, v2.1.117+), inherits the entire conversation history, shares prompt cache with parent — cheaper for related side tasks.
Useful env vars
CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1— turn off background mode entirely.CLAUDE_CODE_SUBAGENT_MODEL=haiku— override model for every subagent invocation in a session.CLAUDE_AUTOCOMPACT_PCT_OVERRIDE=50— trigger auto-compaction earlier (default 95%).CLAUDE_CODE_FORK_SUBAGENT=1— enable fork mode (changes behavior of general-purpose subagent and/forkcommand).
You now have the full subagent toolkit: built-in agents covered for common tasks, frontmatter to author your own, three invocation patterns, persistent memory for learning, and three execution modes. The next module wires policies on top of all this with hooks.
Hands-On Lab — Build a pii-auditor Subagent for the API
Working in the PublicRecords API. You'll create a tightly tool-scoped subagent that scans Java sources, YAML configs, and SQL files for unmasked SSNs / EINs / DOBs, then returns a markdown table of findings. Read-only by design — can't fix, just audit. About 10 minutes.
Step 1 — Author the subagent
Subagents live in .claude/agents/ as Markdown files with frontmatter. Critical fields:
name— how you invoke it (Use the pii-auditor subagent)description— lets the parent agent decide when to delegatetools— tightly scoped. Read+Grep+Glob means the subagent literally CANNOT Edit, Write, or Bash. The OS doesn't enforce this; the agent harness does.model: haiku— cheap and fast for a focused taskmemory: project— findings persist across sessions and ship with the repo
From the project root, make the agents directory:
cd /path/to/PublicRecordsAPI && mkdir -p .claude/agentsCreate the subagent file:
---
name: pii-auditor
description: Scans the codebase for unmasked PII (SSN, EIN, DOB) in Java
source, application YAML configs, and SQL files. Use proactively before
every commit and as a CI gate.
tools: Read, Grep, Glob
model: haiku
memory: project
---
You are a PII auditor for a US public-records API.
Your task on every invocation:
1. Use Grep to find candidate PII patterns across the working tree
in `src/**/*.{java,yml,yaml,sql,properties}`:
- **SSN**: `\b\d{3}-?\d{2}-?\d{4}\b`
- **EIN**: `\b\d{2}-?\d{7}\b`
- **DOB literals near identifiers**: `\b(19|20)\d{2}-\d{2}-\d{2}\b`
within 5 lines of words like `dob`, `birth`, `birthdate`.
2. For each match, Read 5 lines of context.
3. Skip false positives:
- Matches inside `// TEST`, `// FIXTURE`, or `// MOCK` comments
- Matches under `src/test/`
- Matches in `data.sql` ONLY if the file's first line says
`-- MOCK DATA` (otherwise still flag it).
4. Produce a markdown table:
`| File:Line | Matched | Risk | Suggestion |`
Risk values: HIGH (committed source code logging the value),
MED (fixture or seed data with realistic values),
LOW (matches a pattern but is clearly fake).
5. If no findings, output a single line: **PII audit clean.**
Constraints:
- Be terse — no preamble, no narration of process.
- Never propose code edits. You're a read-only auditor; fixes are someone else's job.
- Never read files outside the working tree.
Step 2 — First run on a clean tree
Restart Claude Code, then:
> Use the pii-auditor subagent to scan this codebase.
Expected output: PII audit clean. The starter repo's seed data uses fake business names, no SSNs.
Step 3 — Plant a deliberate violation
Create a Java file with a clearly bad logging pattern — we'll use it to verify the auditor catches what it should:
package com.publicrecords.api.filing;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class DebugLog {
private static final Logger log = LoggerFactory.getLogger(DebugLog.class);
public static void logDebtor(String ssn) {
// FIXME pre-launch: replace with Pii.mask()
log.info("Debtor SSN={}, hardcoded test value 123-45-6789", ssn);
}
}
Step 4 — Re-run the audit
> Use the pii-auditor subagent to scan this codebase.
Expected: a one-row markdown table flagging DebugLog.java:11 with the SSN, risk HIGH, suggestion to use Pii.mask(). The audit should run in under 10 seconds because Haiku is fast and the toolset is minimal.
Step 5 — Verify the tool restriction is real
Try to make the subagent fix the violation:
> Have the pii-auditor fix the issue it just found.
Expected: the subagent refuses, citing that it has only Read/Grep/Glob and cannot edit files. This is a feature, not a bug. Auditors that can fix things become enforcers, and enforcers create false confidence. Keep audit and fix in separate roles.
Step 6 — Clean up
$ rm src/main/java/com/publicrecords/api/filing/DebugLog.java
$ git add .claude/agents/pii-auditor.md
$ git commit -m "chore(claude): pii-auditor subagent (read-only, project memory)"
Stretch — Add a fourth pattern (credit card)
Edit pii-auditor.md to add a fourth Grep pattern:
- Card PAN:
\b(?:\d[ -]*?){13,19}\b, then validate Luhn-checksum candidates inside the subagent's reasoning.
Drop a fake card number into a test file and re-run. Bonus: combine the auditor with the CC7 hook (next module) so commits are blocked when HIGH-risk PII is found.
A read-only pii-auditor subagent that runs in seconds, costs Haiku-tier tokens, ships with the repo, and flags real violations without ever being able to introduce them. The same shape (tight tool scope + specific task + Haiku) is the template for every focused subagent you'll ever write — lint-fixers, dependency-version checkers, schema-drift detectors. CC7 wires this into a hook so the audit runs automatically.
Knowledge Check
1. You want a subagent that learns about your codebase across sessions, with knowledge shareable to your team via git. Which memory: value?
userprojectlocalglobalproject stores at .claude/agent-memory/<name>/, which goes into git. user is personal-only; local is project but gitignored.project is the right scope: project-specific knowledge that gets checked in.2. The parent session runs in bypassPermissions mode. The custom subagent's frontmatter says permissionMode: default. What actually happens?
default — frontmatter wins.bypassPermissions from parent — cannot be overridden.bypassPermissions or acceptEdits, that takes precedence and cannot be overridden by the subagent. auto-mode parents force auto-mode children too.bypassPermissions, acceptEdits, and auto — subagent permissionMode is ignored in those cases.3. You install a plugin that ships a code-fixer subagent with hooks defined in its frontmatter. The hooks don't fire. Why?
hooks, mcpServers, and permissionMode for security.settings.json..claude/agents/ if you need them.hooks, mcpServers, and permissionMode — security tradeoff.4. You want a subagent to make file edits but in an isolated copy of the repo — so its work doesn't touch your working tree until you approve. Which frontmatter field?
permissionMode: planisolation: worktreebackground: truetools: Readisolation: worktree spins up a temp git worktree. The subagent's edits land there; your working copy is untouched. The worktree is auto-cleaned if no changes.isolation: worktree is the field. Plan mode prevents edits entirely; you want isolation, not prevention.5. Subagent vs Skill vs Main — "verbose research that produces a 5-line summary" goes where?
context: fork) — verbose work in isolation, summary returns.context: fork — both achieve isolation.Module Summary
- 5 built-in subagents handle most cases: Explore (search), Plan (research-in-plan-mode), general-purpose (multi-step), statusline-setup, Claude Code Guide.
- Custom subagents at
.claude/agents/<name>.mdwith 16 frontmatter fields. Onlynameanddescriptionrequired. - 5-tier scope: Managed >
--agentsCLI > Project > User > Plugin. - Three invocation patterns: natural language,
@agent-name,--agentfor whole-session. - Persistent memory:
memory: user / project / local. Project recommended; auto-loadsMEMORY.md. - Three execution modes: foreground (default), background (concurrent + pre-approved), fork (shares parent context + cache).
- Plugin subagents silently drop
hooks,mcpServers,permissionMode. - Parent
bypassPermissions/acceptEdits/autoforce the subagent to inherit them — frontmatter ignored.