Subagents let Claude delegate work to specialized AI assistants, each with their own context window, tools, and system prompt. They prevent context pollution on long tasks, enable parallel execution, and let you encode domain expertise into reusable agents. This module covers creating, configuring, and using subagents effectively.
Creating Subagents
Subagents are markdown files with YAML frontmatter. You can define them with the --agents CLI flag for one session, put them in .claude/agents/ for project scope (committed to git), or ~/.claude/agents/ for personal scope (all projects). Plugins can bundle agents too. Priority is managed > CLI flag > project > user > plugin. Built-in subagents can be overridden by naming a custom subagent the same name — a user or project subagent named Explore overrides the built-in and keeps its own model field. As of v2.1.198, /agents no longer opens a panel — it prints a notice pointing to the subagent file locations. To create and edit custom subagents, ask Claude or edit the files directly.
The frontmatter defines the agent’s identity. The markdown body is its system prompt — write this like you’re briefing a specialist:
---
name: security-reviewer
description: Security-focused code reviewer. Use proactively after writing authentication, authorization, or data handling code.
tools: Read, Grep, Glob
---
You are a senior security engineer specializing in application security.
Review priorities:
1. Authentication and authorization flaws
2. Injection vulnerabilities (SQL, XSS, command)
3. Data exposure and sensitive information handling
4. Cryptographic weaknesses
5. Insecure direct object references
For each finding, provide: severity (Critical/High/Medium/Low), location (file:line), description, and a concrete fix with code example.
When invoked: run `git diff HEAD` first to focus on changed code.
The tools field restricts which tools the agent can use. A security reviewer only needs Read, Grep, and Glob — no write access. An implementation agent needs the full set. Restricting tools makes the agent safer and its behavior more predictable. If you omit tools, the agent inherits all available tools.
Configuration Options
Beyond basic tool access, the frontmatter supports several powerful options. model sets which model the agent uses — haiku for fast, lightweight tasks, sonnet for balanced work, or opus for complex reasoning. You can also use inherit to inherit the parent’s model. effort controls reasoning depth on supported models, with values low, medium, high, xhigh, and max. maxTurns caps how long the agent can run. permissionMode sets the permission level. Other useful fields include disallowedTools, skills to preload selected skills, mcpServers for agent-scoped MCP access, and initialPrompt to auto-submit the first turn.
memory gives the agent persistent storage across sessions. The first 200 lines of a MEMORY.md file in the agent’s memory directory load into its system prompt automatically — Claude writes to this file as it learns things:
---
name: researcher
memory: user
description: Long-running research assistant with persistent notes
---
You are a research assistant. Check your MEMORY.md at session start to recall previous findings. Update it with new discoveries.
isolation: worktree gives the agent its own git worktree and branch to make changes without touching your main working tree. When the agent finishes, it returns the worktree path and branch name for you to review and merge. If it made no changes, the worktree is cleaned up automatically. While the agent runs, Claude locks the worktree so a concurrent cleanup sweep can’t remove it, releasing the lock once the agent finishes. The worktree branches from your repository’s default branch (origin/HEAD) unless you set worktree.baseRef to head in settings, which makes isolated agents start from your local HEAD and carry along unpushed work.
background: true makes the agent always run as a background task, freeing the main conversation. Press Ctrl+B to background a currently running agent.
Two CLI flags extend what a session can access. --add-dir <path> grants Read/Edit access to additional directories beyond the primary working directory — useful when your code references shared libraries or monorepo packages in sibling folders. Skills in .claude/skills/ within added directories load automatically. Persist these across sessions with permissions.additionalDirectories in settings. --mcp-config <path> loads MCP server definitions from one or more JSON files for the current session only, merged with your user/project MCP sources. Add --strict-mcp-config to ignore user/project sources and use only the provided files:
claude --add-dir ~/projects/shared-types --add-dir ~/projects/design-tokens
claude --mcp-config ./ci-servers.json
To force one model onto every subagent, teammate, and workflow agent — ignoring both per-spawn and agent-definition model overrides — set CLAUDE_CODE_SUBAGENT_MODEL_FORCE=1 (Claude Code v2.1.257+). The chosen model comes from CLAUDE_CODE_SUBAGENT_MODEL or, if that is unset, the main session’s model:
# Pin every subagent to Sonnet for a sensitive refactor
CLAUDE_CODE_SUBAGENT_MODEL=sonnet CLAUDE_CODE_SUBAGENT_MODEL_FORCE=1 claude
Using and Chaining Subagents
Claude invokes agents automatically when the task description matches the agent’s description field. Phrases like “use proactively” can encourage delegation, but explicit invocation is the reliable path when you need a specific agent. Use @"agent-name (agent)" syntax to guarantee a specific agent is used, bypassing the automatic matching.
Explicit invocation via natural language also works:
Use the security-reviewer agent to audit the new auth module.
Have the test-engineer agent write integration tests for the payment service.
Ask the debugger agent to investigate the memory leak in src/workers/queue.ts.
Agents can be chained in sequence, with the output of one feeding the next. Run claude agents from the terminal to open the Agent view — a roster of all Claude Code sessions showing their state (working, waiting, completed, failed, idle, stopped) and last activity. This is useful for monitoring multiple agents running in parallel. Pass --cwd <path> to filter the roster to sessions started under that directory — handy when you juggle several repos and want a view scoped to the one you’re currently working on. Set CLAUDE_CODE_DISABLE_AGENT_VIEW=1 to disable it. You can also run a full session with a specific agent via claude --agent <name>, and restrict which agents a coordinator can spawn with Agent(...) tool allowlists.
# Only show agent sessions started under ~/work/api
claude agents --cwd ~/work/api
For scripts that need to consume the roster — tmux-resurrect-style boot scripts, custom status bars, session pickers — pass --json to claude agents to get the same data as a machine-readable array instead of the interactive view. Each entry includes pid, cwd, kind, and startedAt, plus sessionId, name, and status when set. When status is waiting, waitingFor says exactly what the session is blocked on, such as permission prompt or input needed, so a script can route those two cases to different actions:
# Wake up every session that's blocked on a permission prompt
claude agents --json \
| jq -r '.[] | select(.status == "waiting" and .waitingFor == "permission prompt") | .sessionId' \
| xargs -I {} claude respawn {}
First use the code-analyzer agent to find performance bottlenecks, then use the optimizer agent to fix them.
You can also start a session detached from your terminal from the outset: claude --bg "investigate the flaky test" (also --background) launches it as a background agent and returns immediately, printing the session ID and the commands to manage it. Combine --bg with --exec to run a shell command as a background job instead of a Claude session, or with --agent to background a specific subagent — it cannot be combined with -p/--print. Once a session is backgrounded, manage it from the shell without opening the full Agent view: claude attach <id> brings it into the current terminal, claude logs <id> prints its recent output, claude stop <id> (also claude kill) stops it, claude respawn <id> restarts a running or stopped session with its conversation intact (pass --all to restart every running session, for example to pick up an updated Claude Code binary), and claude rm <id> drops it from the roster while keeping the transcript on your machine so claude --resume can still reopen it.
Claude Code ships with several built-in agents you don’t need to create: general-purpose handles broad multi-step tasks, Explore inherits the main session model (capped at opus) for fast read-only codebase analysis, Plan researches the codebase before presenting implementation plans, and claude-code-guide answers questions about Claude Code features. Note that Explore and Plan skip your CLAUDE.md files and git status to keep research fast and inexpensive — every other built-in and custom subagent loads both. Claude can also continue a previous agent’s conversation instead of starting over — sending a follow-up with SendMessage({to: agentId}) resumes that agent with its context intact, while a fresh Agent call always starts a new conversation.
By default, a subagent can spawn subagents of its own, up to three layers below your main conversation — as of v2.1.219 the default is three (it was one in v2.1.217–v2.1.218). Nesting suits a delegated task that itself splits into parallel subtasks — a reviewer subagent that dispatches a verifier per finding — so the intermediate output never reaches your main conversation and only the top-level subagent’s summary returns to you. At the depth limit, Claude Code withholds the Agent tool from every subagent except a fork, so a subagent at the limit does its delegated work itself. Set CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH (v2.1.217+) to the number of layers you want below the main conversation, or 1 to turn nesting off. Beyond nesting depth, a concurrent cap (CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS, default 20 running at once, v2.1.217+ — ultracode sessions are exempt) limits how many subagents run at the same time. There is no per-session total: the 200-spawn-per-session cap (CLAUDE_CODE_MAX_SUBAGENTS_PER_SESSION, added v2.1.212) was removed in v2.1.224, so long-running sessions no longer refuse new agents over a session-wide spawn count.
When you drive subagents non-interactively with -p, you can inject shared instructions into every subagent’s system prompt — nested subagents included, apart from a forked subagent that reuses the conversation’s own prompt. --append-subagent-system-prompt "Cite file paths in every answer" (v2.1.205+) appends the text to each subagent’s system prompt; for instructions too long to pass on the command line, --append-subagent-system-prompt-file ./subagent-rules.txt (v2.1.261+) loads the same text from a file. The two flags can’t be combined, and both apply only in -p mode. (For the main agent’s own prompt, the equivalents are --append-system-prompt and --append-system-prompt-file.)
By default a conversation records its system prompt on the first request and reuses that recorded snapshot on later requests. While you iterate on --append-system-prompt or --append-subagent-system-prompt wording across --continue runs, that reuse means your edits are ignored — pass --system-prompt-snapshot off (v2.1.257+) to rebuild the prompt on every request instead. Before v2.1.268, this recording applied only in sessions that fetch feature flags, as claude.ai and Console accounts do by default; sessions that don’t — including Bedrock, Google’s Cloud Agent Platform, and Foundry — rebuilt the prompt on every request regardless, and the flag had no effect.
Subagent forking is on by default in interactive sessions as of v2.1.232 — it stays off by default in non-interactive -p mode and the Agent SDK. A forked subagent inherits the full conversation context from the main session instead of starting fresh, so you can hand it a side task without re-explaining the situation, and forked spawns run in the background. Start one with /subtask (v2.1.212+). Use CLAUDE_CODE_FORK_SUBAGENT to override the defaults: 1 also turns forking on in non-interactive mode and the Agent SDK, and 0 turns it off in every kind of session:
CLAUDE_CODE_FORK_SUBAGENT=0 claude # turn forking off everywhere
The experimental Agent Teams feature (requires CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1) coordinates multiple Claude instances working in parallel via a shared task list and mailbox. The --teammate-mode flag controls in-process vs. split-pane display; it does not enable the feature on its own. This is for large multi-file projects where independent agents can work on different parts simultaneously without stepping on each other. SendMessage automatically resumes stopped agents when a message is sent to them, so you no longer need to explicitly resume an agent before communicating with it. As of v2.1.178 the TeamCreate and TeamDelete tools were removed: with the environment variable set, every session already has one implicit team, so you spawn teammates directly through the Agent tool’s name parameter — no setup step — and cleanup happens automatically when the session exits.
Cross-Session Messaging
SendMessage and ListAgents (v2.1.224+) also work between independent Claude Code sessions — the ones you start and steer yourself, not subagents or team teammates. The receiving session reads a delivered message between tool calls during an active turn, so a running tool is never interrupted; when it’s idle, a new turn starts with the message. Messaging is on with nothing to enable on macOS and Linux, runs on the same machine out of the box, and reaches your other machines and Claude Code on the web when the sending session is connected to Remote Control.
Reach for cross-session messaging when one of your sessions has something another session needs mid-task: a breaking change one session discovered that affects the work in another, the answer to a question one session settled that another is blocked on, a status update from a long-running migration, or a hand-off between sessions working the same repository in separate worktrees. For sharing whole conversations or context between terminals, /resume is the right tool instead — a message is plain text, not history.
Each session decides what to do with an incoming message, defaulting by both sides’ permission modes: messages to a session that prompts for permissions are delivered, while messages to a session running with bypassed permissions are held for your approval unless the sender is also bypassing. Override the default with the crossSessionInbound setting — accept auto-delivers, hold queues for your approval, refuse drops. The held-message dialog expires after dialogExpiry (default five minutes); set it to "never" to keep default-held messages until the session ends. From project or local settings, refuse applies over every other source; from user settings, it applies unless managed settings or --settings set a value. To turn messaging off entirely, add SendMessage and ListAgents to your permissions.deny list — denying SendMessage also blocks messages to subagents and agent-team teammates since the same tool serves all three:
{
"permissions": {
"deny": ["SendMessage", "ListAgents"]
},
"crossSessionInbound": "refuse"
}
You don’t need to call the tools yourself: Claude discovers the target with ListAgents and sends with SendMessage when it sees a need, or when you prompt it to. To name a target yourself, type @ followed by the first letters of the session’s name and pick the session from the typeahead (v2.1.232+), the same way you @-mention a subagent. Sessions are addressed by the name you set with /rename or --name; without one, Claude Code derives a name from the working directory.
Cross-session messaging runs on macOS and Linux, requires Claude Code v2.1.224 or later, and depends on the provider and configuration of both sessions. For organizations, administrators can combine the deny rules with crossSessionInbound: "refuse" in managed settings to turn both directions off.