Subagents & Custom Agents

This content was generated with the assistance of AI and should be verified against the official documentation of each tool and framework before being relied on in production.

This section’s bibliography lists the reference material consulted while preparing these pages.

This page is written against the Claude Code CLI 2.1.283, VS Code 1.139 with the GitHub Copilot Chat extension, and the GitHub Copilot CLI 1.0.88, all re-verified as current as of 2026-09-28; re-check the linked docs before relying on an exact field name, since both products change these surfaces often. The ai-catalog examples are excerpted from this account’s ai-catalog repository, pinned to commit 58fb709 (58fb70954404f9d539031a02ac6d4413f03745be).

A subagent is a delegated worker that runs a task in its own context window and hands back a result, instead of that work accumulating in the calling conversation. Both Claude Code and GitHub Copilot ship this idea; the sections below cover each tool’s mechanism, then how to choose between a subagent, a context: fork skill, and an agent team.

Claude Code subagents

Built-in subagents

Claude Code ships several built-in subagent types, verified against Claude Code — Subagents:

Type What it is

Explore

A fast, read-only agent for searching and analyzing a codebase. Inherits the main conversation’s model (capped at Opus on the Claude API) and has only read-only tools.

Plan

The research agent Claude Code uses in plan mode to gather context before presenting a plan. Also inherits the main conversation’s model and is read-only.

general-purpose

A capable agent with every tool available to subagents, for complex, multi-step tasks that need both exploration and action. It is the default for a context: fork skill that sets no agent.

claude

A catch-all agent with every available tool, used when a task doesn’t fit a more specialized agent.

statusline-setup

Runs on Sonnet; used when /statusline configures the status line (see Output Styles, Status Line & More).

claude-code-guide

Runs on Haiku; answers questions about Claude Code’s own features.

Explore and Plan are the ones most relevant to everyday delegation; both skip CLAUDE.md and the git status snapshot to keep their context small. general-purpose is the usual target for anything broader. A built-in is used by naming it, either in a prompt or as a forked skill’s agent:

In Claude Code
> Use the Explore agent to find every place DocsController maps a ProblemDetail

To stop Claude from delegating to a particular built-in, deny it in settings:

.claude/settings.json
{
  "permissions": {
    "deny": ["Agent(Explore)"]
  }
}

See Claude Code — Subagents ("Built-in subagents" and "Disable specific subagents").

Custom subagents: .claude/agents/*.md

A custom subagent is a Markdown file with YAML frontmatter, one file per agent, at .claude/agents/<name>.md (project scope, checked into version control), ~/.claude/agents/<name>.md (user scope, across all projects), under a plugin’s agents/ directory, or under a managed-settings directory for an organization-wide agent. Project subagents take precedence over user subagents, which take precedence over plugin agents; see the Subagents reference for the full precedence order, including managed settings and the session-only --agents CLI flag.

The table below covers every frontmatter key currently documented, verified against the same reference:

Key Type Default What it does

name

string

required

The agent’s unique identifier; cannot contain : or start with -. Hooks receive it as agent_type, and it is the name used in @agent-<name> and --agent <name>. The filename doesn’t have to match.

description

string

required

When Claude should delegate to this subagent, matched the same way a skill’s description triggers auto-invocation.

tools

string or list

every available tool

An allowlist of tools the subagent may use, e.g. Read, Grep, Glob, Bash or a YAML list.

disallowedTools

string or list

none

Tools removed from the inherited or specified tools list, applied before tools resolution.

model

string

falls back through a precedence chain

sonnet, opus, haiku, fable, a full model ID, or inherit. Resolved as: a per-invocation parameter, then this field, then the CLAUDE_CODE_SUBAGENT_MODEL environment variable, then the main conversation’s model.

color

string

none

A display color for the agent in the terminal UI: red, blue, green, yellow, purple, orange, pink or cyan.

permissionMode

string

inherits the main session’s mode

default, acceptEdits, auto, dontAsk, bypassPermissions, plan, or manual (an alias for default). Ignored for plugin subagents. See Permissions & Settings for what each mode allows.

skills

list

none

Skill names to preload into the subagent’s context at startup — the full SKILL.md content, not just the description, so the subagent has the pattern in hand without needing to trigger it.

mcpServers

list or map

none

MCP servers available to the subagent: entries name a server already configured elsewhere, or define one inline. Ignored for plugin subagents. See Configuring MCP Servers.

maxTurns

integer

unlimited

Maximum agentic turns before the subagent stops; its output is then marked partial and Claude can resume it.

hooks

map

none

Hooks scoped to this subagent while it is active. Any hook event is accepted; the most common are PreToolUse, PostToolUse and Stop (converted to SubagentStop at run time). A project subagent’s hooks run only after you accept the workspace trust dialog. Ignored for plugin subagents. See Hooks.

memory

string

none

A persistent memory scope for cross-session learning: user (~/.claude/agent-memory/<name>/), project (.claude/agent-memory/<name>/) or local (.claude/agent-memory-local/<name>/). Has no effect while auto memory is turned off.

background

boolean

false

When true, keeps the subagent running in the background even if Claude would otherwise wait for it.

omitClaudeMd

boolean

false

When true, skips loading user, project and local CLAUDE.md files into the subagent (managed policy files still load).

effort

string

inherits the session’s effort

Overrides the reasoning-effort level for this subagent: low, medium, high, xhigh, or max.

isolation

string

none

Set to worktree to run the subagent in a temporary git worktree, branched by default from the default branch rather than the session’s HEAD; removed automatically if the subagent makes no changes.

initialPrompt

string

none

A prompt auto-submitted as the agent’s first turn when it runs as the main session agent (via --agent or the agent setting), not when it runs as a delegated subagent.

experimental

map

none

Experimental options. Its cacheTtl key (5m or 1h) sets the prompt-cache lifetime for this subagent’s requests.

A minimal .claude/agents/code-reviewer.md
---
name: code-reviewer
description: Reviews code for quality and best practices. Use proactively after code changes.
tools: Read, Glob, Grep, Bash
model: sonnet
permissionMode: default
color: cyan
---

You are a senior code reviewer. When invoked, analyze the changed files and provide specific, actionable
feedback on quality, security and best practices. Report findings only -- never edit files yourself.

Context isolation

Every subagent invocation starts with its own context window: its own system prompt (the agent’s Markdown body plus environment details, not Claude Code’s own system prompt), a task message summarizing what the caller wants done, CLAUDE.md at every level (skipped by the built-in Explore and Plan agents, and by any agent that sets omitClaudeMd: true), a git status snapshot, and, if listed, its preloaded skills. What it does not inherit is the calling conversation’s history, output-style settings, or auto memory. When the subagent finishes, it returns a single result to the caller — the parent conversation never sees the subagent’s own tool calls or intermediate reasoning, only the summary it chooses to report back. This is the same isolation mechanism a context: fork skill uses (see Skills) and the reason Optimizing Skills & Agents treats it as a first-class optimization technique: verbose tool output never has to flow back into the orchestrator’s own context.

Invocation is by natural language (Claude decides whether to delegate), by an explicit @agent-<name> mention (which guarantees delegation), or session-wide via claude --agent <name> or an "agent" key in .claude/settings.json:

In Claude Code
> Use the code-reviewer subagent to look at my recent changes
> @agent-code-reviewer look at the auth changes
$ claude --agent code-reviewer

Copilot custom agents

.github/agents/*.agent.md

GitHub Copilot’s custom agents are Markdown files with the .agent.md extension ("agent profiles"), verified against GitHub’s custom-agents-for-CLI docs:

Location Scope

.github/agents/<name>.agent.md

Project scope, checked into the repository

~/.copilot/agents/<name>.agent.md

Personal scope, across all projects — takes precedence over a same-named project agent

Documented frontmatter keys: name (identifies the agent), description (its expertise and when Copilot should reach for it), tools (an allowlist; defaults to every tool when omitted), and include-custom-instructions (when true, the repository’s custom instructions also apply while the agent runs as a subagent; an agent you select yourself already follows them). In the Copilot CLI you invoke a custom agent by choosing it from /agent, by naming it in the prompt, by letting Copilot infer it from its description, or programmatically:

In the GitHub Copilot CLI
$ copilot --agent security-auditor --prompt "Check /src/app/validator.go"

Here security-auditor is the agent file’s name without the .agent.md extension.

VS Code custom agents (formerly chat modes)

VS Code’s custom agents were previously called custom chat modes; the mechanism is unchanged, only the terminology and the file extension moved — an existing .chatmode.md file should be renamed to .agent.md. Verified against VS Code — Custom agents:

Location Scope

.github/agents/*.agent.md

Workspace scope (the same files GitHub Copilot’s own agent surfaces read)

~/.copilot/agents/*.agent.md

User scope

VS Code also reads .claude/agents/.md (workspace) and ~/.claude/agents/.md (user) as custom agents in the Claude format, and treats any .md file in .github/agents/ as a custom agent, so a Claude Code subagent file and a Copilot/VS Code custom agent file can share the same .claude/agents/ directory without duplication — the practical basis for Copilot & Claude Code Equivalents.

VS Code’s frontmatter adds several fields beyond Copilot’s CLI schema: argument-hint, model (a single model name, or a prioritized array), agents (the agents this one may call as subagents, * for all or [] for none; the agent tool must then be in tools), user-invocable (whether it shows in the agent picker dropdown), disable-model-invocation (stops other agents calling it as a subagent), target (vscode or github-copilot), mcp-servers, handoffs, and hooks (local hook commands, marked Preview). The older infer key is deprecated in favour of user-invocable and disable-model-invocation.

Handoffs

A handoff is a workflow button VS Code shows after a custom agent’s response completes, letting the person switch straight into another named agent with a pre-filled prompt — for example, reviewing a plan and then handing off to an implementation agent. Each entry in the handoffs array carries:

Key What it does

label

The button’s display text.

agent

The target agent’s identifier to switch into.

prompt

Text pre-filled into the next conversation with that agent.

send

Optional; when true, submits prompt automatically instead of leaving it for the person to review first (default false).

model

Optional; the model to use when the handoff runs, as a qualified name such as GPT-5 (copilot).

See VS Code — Custom agents ("Handoffs").

A reviewer agent with a handoff, .github/agents/reviewer.agent.md
---
name: reviewer
description: Reviews a proposed change and reports findings without editing files. Use for a second opinion before implementation.
tools: ["search", "read"]
model: GPT-6 Sol
handoffs:
  - label: "Implement the fix"
    agent: implementer
    prompt: "Apply the reviewer's findings above."
    send: false
---

Review the changes in the current diff. Report findings by severity; do not edit any file.

In a VS Code custom agent, model: takes the model’s display name as it appears in the model picker (GPT-6 Sol), not an API id such as gpt-6-sol; a handoff’s model: uses the same name qualified with its vendor (GPT-6 Sol (copilot)). See VS Code — Custom agents ("Header").

Examples from ai-catalog

Example 1. ai-catalog: iru-gate-runner.md (description abridged)

iru-gate-runner is a narrow-purpose subagent restricted to exactly the tools it needs to dispatch to a named skill and read its report, keeping the broader Edit/Write tool set out of reach entirely:

---
name: iru-gate-runner
description: Runs a single verification/quality-gate skill — tests (…), coverage (…), code-quality/lint (…), license-header checks, doc-comment audits (…), security scans (check-security), or a full project build — in an isolated context, optionally diffs the result against a baseline given in the prompt, and reports back only a compact, structured summary. Never dumps the raw generated report (…) into the caller's context. …
tools: Skill, Bash, Read
---

Its body’s "What you report back" section spells out exactly what a caller gets: a pass/fail run states only the failing names and reasons, never the full log of everything that passed; a coverage check reports only the requested percentage, not per-line detail. This is the context-isolation technique in its most concrete form — Optimizing Skills & Agents measures its effect. See Gate Runner for the full, generated page.

Example 2. ai-catalog: iru-isolated-skill-executor.md

iru-isolated-skill-executor runs a single named skill end to end with no memory of the caller’s prior conversation, so an earlier exploration or planning transcript cannot bias the run:

---
name: iru-isolated-skill-executor
description: Runs a single named skill end-to-end in a completely fresh context — no memory of the caller's prior conversation — so an earlier exploration/planning transcript can't bias the run, while the caller keeps executing afterward (e.g. to open a PR once the delegated skill finishes). Reports back only a concise structured outcome (completed/blocked/hard-stop, files touched, and any named gate condition the caller asked about) — never a full step-by-step transcript. Used by `iru-issue` to hand off the entire `iru-code` skill run for a ticket.
tools: "*"
---

Unlike iru-gate-runner’s narrow allowlist, this agent’s `tools: "" grants everything. The "" wildcard isn’t part of the documented tools schema (Claude Code resolves it to every tool today); omitting tools is the documented way to inherit every tool. Everything is granted because its job is to run an arbitrary named skill to completion, not to execute one fixed command — the isolation here is about a fresh context, not a restricted tool set. The broad grant has a cost: whatever skill it is told to run gets every tool the session allows, so it inherits the full risk of that skill’s instructions and is only as safe as the permission rules around it. It reports back a short structured outcome (completed / blocked / hard-stop, files touched, and any named gate condition), never a step-by-step transcript. See Isolated Skill Executor for the full, generated page.

A generalised reviewer agent, in both tools

In Claude Code
---
name: pr-reviewer
description: Reviews the current diff for correctness and style issues and reports findings without editing files. Use before opening a pull request instead of self-reviewing.
tools: Read, Grep, Glob, Bash
model: sonnet
permissionMode: default
color: yellow
---

Review the current diff. Report findings by severity (blocking / suggestion). Never edit a file yourself --
report only.
In GitHub Copilot (VS Code)
---
name: pr-reviewer
description: Reviews the current diff for correctness and style issues. Use before opening a pull request instead of self-reviewing.
tools: ["search", "read"]
model: GPT-6 Sol
user-invocable: true
---

Review the current diff. Report findings by severity (blocking / suggestion). Never edit a file yourself --
report only.

Both versions leave out the edit tools, because the point of a review agent is a report, not a fix. The Claude Code version keeps Bash so it can run git diff, and Bash is not read-only: the "never edit" rule for shell commands is only an instruction. To enforce it, drop Bash and keep Read, Grep and Glob. A deny rule such as Bash(git commit *) in permissions.deny also works, but settings rules apply to the whole session — the main conversation and every subagent — not to this one agent. To block commands only while the reviewer runs, put a PreToolUse hook in its own frontmatter; Claude Code runs frontmatter hooks only while that subagent is active:

Agent-scoped blocking in .claude/agents/pr-reviewer.md (frontmatter excerpt)
tools: Read, Grep, Glob, Bash
hooks:
  PreToolUse:
    - matcher: "Bash"
      hooks:
        - type: command
          command: "./scripts/block-git-writes.sh"

The script reads the hook’s JSON input on stdin and exits with code 2 to block a command such as git commit. See Claude Code — Define hooks for subagents. Writing Effective Skills covers the same discipline for skill descriptions.

Context isolation, visually

flowchart TB subgraph Main["Main conversation context"] P["User request"] --> Del["Delegates: Agent(...) /\n@agent-name / custom agent"] end subgraph Sub["Subagent -- its own context window"] Fresh["Fresh context:\nagent body + CLAUDE.md\n+ task prompt"] --> Work["Tool calls, reasoning,\nintermediate output"] Work --> Result["Compact result summary"] end Del --> Fresh Result -->|only the summary returns| Main

The main context never sees Work — only Result. That gap is the whole point: a subagent can read a thousand-line test log or a raw SARIF report without any of it landing in the conversation the person is reading.

Subagent vs. context: fork skill vs. agent team

All three isolate work in a separate context, but they differ in reusability, lifecycle and cost. Claude Code’s experimental agent teams feature is verified against Claude Code — Agent teams:

Subagent (.claude/agents/*.md) context: fork skill Agent team

Context

Its own context window; result returns to the caller

Its own context window (the skill runs as a forked subagent); result returns to the caller

Its own context window; fully independent, no automatic return

Communication

Returns a result; named subagents can message each other

Returns a result, exactly like a subagent

Teammates message each other and the lead directly, each through its own mailbox

Coordination

The caller decides when to delegate and reads the result

The skill’s own body decides to fork (context: fork in its frontmatter); no team forms

Self-coordination through messages plus a shared task list, for agents with the Task tools

Reusability

A named, reusable role (name/description/tools/…​) invoked from anywhere

Tied to one skill’s own steps; not a standalone reusable role

Ad hoc, spawned by a natural-language request; roles can reuse a subagent definition

Token cost

Lower — one result summarized back

Lower — one result summarized back

Higher — each teammate is a full, separate session

Best for

A focused, reusable worker that reports back (iru-gate-runner)

A single skill that needs isolation for one run (`iru-isolated-skill-executor’s job, but declared inline on a skill rather than as a caller-invoked agent)

Parallel exploration, review or debugging that benefits from teammates challenging each other’s findings

Agent teams are disabled by default and require setting CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1. Turning them on also changes ordinary delegation: a subagent that Claude names while teams are enabled launches as a teammate, so a team can form even when you didn’t ask for one.

.claude/settings.json
{
  "env": {
    "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1"
  }
}

Reach for a subagent when you want a focused worker with a name you can reuse across sessions and skills. Reach for context: fork when the isolation belongs to one skill’s own execution, not to a standalone role. Reach for an agent team only when the work genuinely benefits from several independent perspectives talking to each other — a competing-hypotheses debugging session or a multi-angle review — since it costs meaningfully more tokens than either alternative. See Agents for how ai-catalog’s three agents (iru-gate-runner, iru-isolated-skill-executor, iru-change-summarizer) apply this choice in practice; the general theory of agent architectures — multi-agent topologies, planner/executor patterns and tool-selection strategies beyond what any one tool’s docs describe — belongs to the planned AI Agents sub-section, out of scope here.