Subagents
Subagents are focused, fresh-context helpers the main agent delegates work to. Each one is a markdown file under .claude/agents in your workspace; the file's frontmatter controls which model and tools the child gets, and the body becomes the child's system prompt. This page covers authoring those definitions — how to run background or resumed agents is covered in /guide/background-tasks.
The file contract
Each file in .claude/agents is one agent definition. The body of the file (everything after the frontmatter) is the agent's system prompt — its persona and instructions. The YAML frontmatter controls dispatch behavior.
.claude/
agents/
reviewer.md
debugger.mdDiscovery is scoped to the session's working directory, not the host process cwd — so definitions are visible even when the harness is started from elsewhere. Both a user layer and a project layer are loaded, with the project layer shadowing the user layer.
Frontmatter fields
Only the fields the loader actually consumes:
| Field | What it does |
|---|---|
description | One-line summary of what the agent is for. This is what the Available subagents system-prompt section renders, so it is what drives dispatch — the main model picks an agent by reading these descriptions. |
model | A Claude-Code-style model alias (sonnet, opus, haiku, fable, inherit, …). Resolved through the ccModelRoutes service at spawn time; see /guide/model-routing. |
tools | Restricts the child's tool set (allow/deny). See the tools section below. |
background | Pin the agent to launch as a continuable background agent. See below. |
isolation | isolation: worktree dispatches the child into its own git worktree. See below. |
ephemeral | ephemeral: true forces the foreground one-shot lane for any definition; ephemeral: false overrides the read-only allowlist. See Ephemeral read-only agents below. |
ephemeralTtlMs | TTL (milliseconds) for a running ephemeral child; default 15 minutes. See Ephemeral read-only agents below. |
autoReleaseMs | Override for the settled auto-release window (milliseconds); 0 never auto-releases, a malformed value fails loudly at load. See Settled auto-release below. |
The loader also parses CC frontmatter fields such as permissionMode, memory, and effort, but v1 does not project them onto the child — a definition using them behaves as if the field were absent. (isolation: worktree and background: true are consumed — see below.)
Fields that are omitted fall back sensibly: an omitted model inherits the parent's route; an omitted tools leaves the child with the full parent tool view.
A minimal example
---
description: Fast codebase lookups
model: haiku
---
You are a read-only codebase scout. Return paths and line numbers,
not implementations.The body above is delivered to the child as its system prompt; the task text you pass when delegating becomes the child's first user message.
Dispatch
The main agent delegates with the Task tool, passing the agent's name as subagent_type. Your session's system prompt renders an Available subagents section listing the workspace's file definitions, for example:
## Available subagents
- explore — a fast, read-only codebase scout; returns paths and line numbers, not implementations
- dsh-cc-guide — answers questions about dsh-cc itself: commands, tools, settings, known limits
To delegate to one, pass its name as the `subagent_type` argument of the Task tool.The section lists workspace file definitions plus any agents mounted by plugins, the latter by their scoped plugin:agent ids — backend provider names are never shown as addressable types.
Dispatch follows five cases:
subagent_typeomitted, blank, orgeneral-purpose— a fresh spawn of the caller: your prompt text becomes the child's first user message, no definition participates, and no parent conversation is copied. Write a self-contained prompt.subagent_type: "fork"— a conversation-inheriting fork of the caller: completed parent turns seed the child; no definition participates.forkis a reserved sentinel and wins over a workspace file of the same name, so.claude/agents/fork.mdis unreachable.- A type matching a definition in the workspace — a spawn whose persona is the definition's body, whose model route is the alias-resolved
model:, and whose tools are filtered by the sanitizedtools:value. The child runs with a maximum delegation depth of 3. - A scoped id
plugin:agentmatching a plugin-mounted agent — folded identically to a workspace definition (persona, sanitized tools, alias-resolved model, max depth 3, background pin). Plugin agents are addressable only by their scoped id — a bare plugin agent name is not addressable, matching Claude Code. File definitions and scoped ids occupy disjoint name spaces: a workspace file whoseagentTypecontains:is skipped with a warning at discovery. - Anything else — an error result listing the available types in the workspace (or noting the workspace defines none), with a colon-aware hint when the type contains
:.
Bundled agents
The cc preset bundles two agents in addition to anything your workspace defines:
| Agent | What it is |
|---|---|
explore | A fast, read-only codebase scout. When a Serena MCP server is connected, it additionally carries read-only symbol retrieval (mcp__serena__find_symbol, mcp__serena__find_referencing_symbols, mcp__serena__get_symbols_overview). |
dsh-cc-guide | Answers questions about dsh-cc itself — commands, tools, settings, known limits. |
Behavior controls
model: and alias routing
The model: frontmatter field is resolved through ccModelRoutes on every spawn, so model: haiku lands on whatever your haiku lane maps to at that moment — remapping a lane needs no change to the definition. If the alias service is absent, every child simply inherits its parent's route. Details and examples: /guide/model-routing.
tools: restrictions
A tools: frontmatter value narrows the child's tool set and is sanitized against the tools actually registered at spawn time:
- Names the registry does not know are dropped with a warning — including MCP tools of servers that are not mounted.
mcp__<server>__<tool>entries are kept as written and must be the tool's public name;mcp__<server>andmcp__<server>__*expand to every mounted tool of that server. A baremcp__is dropped as an invalid wildcard.- An allow list is loud about matching nothing: if sanitization leaves zero names, the child runs with zero tools (with a warning), because omitting
allowentirely would instead widen it to every tool. - Explicit
tools:entries that are still deferred are preloaded before the child starts; server-level wildcards are restrict-only and never preloaded.
background: true
By default a Task call is foreground: the tool waits for the child to finish and returns its text output. Setting background: true in the definition pins the agent to launch as a durable, continuable background agent — the call returns promptly with an agentId and the result arrives later as a wake message. The caller can still override the pin: an explicit run_in_background: false forces foreground, and run_in_background: true starts any agent in the background.
Running, resuming, interrupting, and inspecting background agents (send_message / interrupt / list, /tasks, /agents) is covered in /guide/background-tasks.
Ephemeral read-only agents
Allow-listed read-only definitions — the bundled explore and dsh-cc-guide, and the dsh-cc-shunt plugin's shunt-reader — plus any definition with explicit frontmatter ephemeral: true run as a foreground one-shot: a plain spawn with no durable child, no resume pin, no resume. ephemeral: false on the definition overrides the allowlist.
The backgrounding controls above do not carry over. A background: true pin on such a definition is ignored, with an explicit notice saying the pin was ignored because read-only ephemeral agents always run as foreground one-shots; an explicit run_in_background: true argument is fail-fast rejected; isolation: worktree is rejected the same way; Ctrl+B cannot promote an ephemeral wait; and every ephemeral result carries a one-line notice that no durable child was created.
Running ephemeral children are reaped at the definition's ephemeralTtlMs or a 15-minute default; expiry surfaces "ephemeral child hit its TTL; re-spawn it". A running ephemeral child counts toward the 25 live-child capacity guard; release_agent is not supported on a running ephemeral (mode-gated) — it settles or hits its TTL on its own.
Settled auto-release
A settled continuable child is auto-released after an inactivity grace window: 30 minutes for foreground-delivered results, 2 hours for background-delivered results (including Ctrl+B-promoted wake messages).
The per-definition override is the frontmatter autoReleaseMs (in milliseconds): absent uses the tier default, 0 never auto-releases, and a malformed value fails loudly at load. The dsh-cc-agents plugin's write-lane agent pins autoReleaseMs: 7200000 in its definition — equal to the 2-hour background default, pinned explicitly so it survives policy drift.
The settle-time message names the window ("auto-released after … of inactivity") at both delivery sites, and an auto-released child is tagged in /agents exactly like a manually released one. After auto-release the child cannot be continued — send_message is refused, the same rule as manual release_agent, which remains the tool for stuck RUNNING children you can discard.
isolation: worktree
A definition whose frontmatter pins isolation: worktree is dispatched into a per-child git worktree instead of the parent tree:
- Create — a worktree under
<mainRepoRoot>/.claude/worktrees/subagent-<childId>on branchworktree-subagent-<childId>, created through the same hardened path asEnterWorktree(common-dir root pin, local-config scan, filter-driver neutralization; LFS content arrives as pointer files), then locked for the run. Any creation failure refuses the dispatch — the child never silently falls back to the parent tree. - Adopt — on the child's first step, the child's session cwd moves into the worktree; a contract paragraph is appended to the persona and a first-line note is prepended to the prompt.
- Clean up — on
subagent/end, the tree is probed for a dirty status and commits beyond the recorded base HEAD. Clean and no commits → the worktree is unlocked, removed with its branch. Otherwise the tree is left on disk and the child's final text says so.
Honest limits (the feature is partial): the child's header.cwd, the harness sandbox root, and the bash default workdir remain the parent's; a parent cwd under which the worktree convention directory does not fit the sandbox root refuses the dispatch; delegated children cannot answer approval prompts, so a sandbox-denied write hard-fails; and Serena (user-mounted) pins one project root and does not follow the child. File formats: /reference/extension-formats; launcher and in-session worktree lifecycle: /guide/worktrees.
Actor-contract blocks
A definition may wrap part of its body in <!-- actor-contract:start --> … <!-- actor-contract:end --> marker lines. The block reaches the child's system prompt only when the child's resolved model id matches a pattern in the actor-contract settings namespace models — default ['glm-*'], matched case-insensitively. [] disables the contract, ['*'] applies it to every model. A definition whose model: is unset (inherit) is fail-closed: the block is stripped. The marker lines themselves never reach the prompt. Typical use: model-specific evidence or contract sections in plugin-owned agents.
Notes and limits
As of dsh-cc v0.6.0:
/agentsis partial. It is a thin snapshot (list/detail/stop/release) over running agents; groups are residency-only and/agentsattach is reserved but unimplemented.- Process-level discovery cache. Definitions are cached per workspace root for the process lifetime with no filesystem watcher: edits take effect on the next session for an uncached workspace, and on process restart otherwise.
- Cold resume is pinned. A background child's persona, tool filter, model route, and
maxTokensare restored from its resume pin — a pin recording an unset reasoning-effort or token field is honored as absent rather than re-resolved. Other agent options do not survive resume. - No TaskOutput alias or outputFile field. Foreground results come back as text; there is no output file.
- Workspace instructions are stripped from Task children. Unlike Claude Code custom subagents, delegated children do not receive the workspace
CLAUDE.md/AGENTS.mdbaseline in their visible batch (a fork child still inherits what was already in the parent seed).
Large child artifacts: the handoff store
A child can park a long report or plan in the handoff store with handoff_put and return a summary (≤2 KB works well) embedding a handoff://<id> handle; the orchestrator or a follow-up child resolves the handle with handoff_get. Facts worth knowing:
- Handles resolve only for sessions whose cwd hashes to the same projectKey — a different git worktree of the same repo is a different key.
- Retention is a 24 h TTL plus a 500-entry disk-based LRU per project.
- Settings namespace
cc-handoff:enabled(defaulttrue) andthreshold-chars(8192, advisory only, never enforced).
Next
- /guide/worktrees — the launcher flag, in-session tools, and subagent isolation around git worktrees.
- /guide/background-tasks — running, resuming, and interrupting background agents.
- /guide/skills —
SKILL.md-based skills, the other extension surface. - /reference/extension-formats — the file formats dsh-cc reads, including
.claude/agents.