Claude Code Mastery — Direct Track
CC6 — Delegation Module 7 of 16
50 minIntermediate
← CC5: Skills & Slash Commands 🏠 Home CC7: Hooks →

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-name mention, --agent whole-session.
  • Configure persistent memory: so a subagent learns across sessions.
  • Use foreground / background / fork modes appropriately.

Why Subagents

Everyday Analogy

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.

Technical Definition

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.

SubagentModelToolsWhen Claude uses it
ExploreHaikuRead-onlyCodebase search at quick, medium, or very thorough
PlaninheritRead-onlyResearch during plan mode — prevents nesting
general-purposeinheritAllMulti-step work needing both exploration AND modification
statusline-setupSonnetRead, EditWhen you run /statusline
Claude Code GuideHaikuWebFetch, WebSearchWhen 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:

PriorityScopePath
1ManagedOrganization-wide via managed settings
2--agents CLIJSON passed at launch — session-only, never saved
3Project.claude/agents/ — checked into git, team-shared
4User~/.claude/agents/ — personal, all your projects
5Plugin<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.

FieldPurpose
nameLowercase-hyphen identifier; unique within scope
descriptionWhen Claude should delegate — include "use proactively" to encourage it
toolsAllowlist (e.g. Read, Grep, Bash); inherits all if omitted
disallowedToolsDenylist applied first; tools resolves against the remainder
modelsonnet, opus, haiku, full ID, or inherit (default)
permissionModedefault, acceptEdits, auto, dontAsk, bypassPermissions, plan
maxTurnsHard cap on agentic turns — safety circuit breaker
skillsSkills preloaded at startup — full body injected (vs description-only in main session)
mcpServersInline server defs (scoped) or string refs to existing servers
hooksLifecycle hooks scoped to this subagent only — cleaned up on finish
memoryuser / project / local — persistent MEMORY.md across sessions
backgroundtrue → always run concurrently with permission pre-approval
effortlow / medium / high / xhigh / max — thinking budget
isolationworktree → runs in temp git worktree — auto-cleaned if no changes
colorred blue green yellow purple orange pink cyan — UI badge
initialPromptAuto-submitted first user turn when run as main session via --agent
Plugin subagents drop three fields silently

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.

ScopePathBest 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:

PropertyForegroundBackgroundFork (/fork)
Blocks main sessionyesnono
Starting contextfresh + Task promptfresh + Task promptfull conversation
Permissionsinteractive promptspre-approved at spawninteractive prompts
Prompt cacheseparateseparateshared with parent
Triggerdefault behaviorbackground: 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 /fork command).
What just happened?

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

How it works

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 delegate
  • tools — 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 task
  • memory: 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/agents

Create the subagent file:

Markdown Subagent
.claude/agents/pii-auditor.md
---
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:

Java Test Violation
src/main/java/com/publicrecords/api/filing/DebugLog.java
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.

Lab complete — what you should have

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?

A
user
B
project
C
local
D
global
Correct. project stores at .claude/agent-memory/<name>/, which goes into git. user is personal-only; local is project but gitignored.
Look again. 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?

A
Subagent uses default — frontmatter wins.
B
Subagent inherits bypassPermissions from parent — cannot be overridden.
C
Error — modes conflict.
D
The stricter of the two wins.
Correct. If the parent uses bypassPermissions or acceptEdits, that takes precedence and cannot be overridden by the subagent. auto-mode parents force auto-mode children too.
Look again. Parent permission context wins for 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?

A
Plugin needs to be enabled.
B
Plugin subagents silently drop hooks, mcpServers, and permissionMode for security.
C
Hooks need to be in settings.json.
D
Hooks only work in foreground subagents.
Correct. Plugin subagents drop those three fields silently. Copy the agent file to .claude/agents/ if you need them.
Look again. Plugin-shipped subagents silently strip 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?

A
permissionMode: plan
B
isolation: worktree
C
background: true
D
tools: Read
Correct. isolation: 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.
Look again. 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?

A
Main conversation — you need to see the work.
B
Skill running inline — reusable.
C
Subagent (or skill with context: fork) — verbose work in isolation, summary returns.
D
Plan mode in main — describe the work first.
Correct. The classic subagent use case: heavy verbose work in isolation, just the summary returns. Either dedicated subagent or a skill with context: fork — both achieve isolation.
Look again. Subagent (or fork-style skill) is the right tool when output is verbose but the take-away is small. Main conversation gets clean summaries; verbose stuff stays out.

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>.md with 16 frontmatter fields. Only name and description required.
  • 5-tier scope: Managed > --agents CLI > Project > User > Plugin.
  • Three invocation patterns: natural language, @agent-name, --agent for whole-session.
  • Persistent memory: memory: user / project / local. Project recommended; auto-loads MEMORY.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/auto force the subagent to inherit them — frontmatter ignored.