Skip to content

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.

text
.claude/
  agents/
    reviewer.md
    debugger.md

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

FieldWhat it does
descriptionOne-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.
modelA Claude-Code-style model alias (sonnet, opus, haiku, fable, inherit, …). Resolved through the ccModelRoutes service at spawn time; see /guide/model-routing.
toolsRestricts the child's tool set (allow/deny). See the tools section below.
backgroundPin the agent to launch as a continuable background agent. See below.
isolationisolation: worktree dispatches the child into its own git worktree. See below.
ephemeralephemeral: true forces the foreground one-shot lane for any definition; ephemeral: false overrides the read-only allowlist. See Ephemeral read-only agents below.
ephemeralTtlMsTTL (milliseconds) for a running ephemeral child; default 15 minutes. See Ephemeral read-only agents below.
autoReleaseMsOverride 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 ​

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

text
## 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:

  1. subagent_type omitted, blank, or general-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.
  2. subagent_type: "fork" — a conversation-inheriting fork of the caller: completed parent turns seed the child; no definition participates. fork is a reserved sentinel and wins over a workspace file of the same name, so .claude/agents/fork.md is unreachable.
  3. 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 sanitized tools: value. The child runs with a maximum delegation depth of 3.
  4. A scoped id plugin:agent matching 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 whose agentType contains : is skipped with a warning at discovery.
  5. 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:

AgentWhat it is
exploreA 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-guideAnswers 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> and mcp__<server>__* expand to every mounted tool of that server. A bare mcp__ 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 allow entirely 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:

  1. Create — a worktree under <mainRepoRoot>/.claude/worktrees/subagent-<childId> on branch worktree-subagent-<childId>, created through the same hardened path as EnterWorktree (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.
  2. 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.
  3. 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:

  • /agents is partial. It is a thin snapshot (list/detail/stop/release) over running agents; groups are residency-only and /agents attach 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 maxTokens are 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.md baseline 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 (default true) and threshold-chars (8192, advisory only, never enforced).

Next ​

dsh-cc is not Claude Code and is not a wrapper around Claude Code. Not affiliated with or endorsed by Anthropic.