Claude Code subagents tutorial: build and restrict one

Claude Code subagents tutorial: create a custom subagent, choose project or user scope, restrict its tools, and invoke it by name, @-mention or --agent.

A subagent is a specialized assistant that Claude Code delegates to, with its own context window, system prompt and tool access. This Claude Code subagents tutorial builds one from the official quickstart, then covers scope, frontmatter, tool restriction and invocation. Everything below was checked against the Create custom subagents page on 2026-10-10; fields and defaults change between releases, so confirm against the current page.

What a subagent is and when it beats the main conversation

Per the subagents docs, each subagent works in its own context window with a custom system prompt and its own tool access and permissions, and returns only a summary to the main conversation. Use one when a side task would flood your main conversation with output you will not reference again.

Stay in the main conversation when:

  • you need frequent back-and-forth;
  • several phases share a lot of context;
  • the change is small and targeted;
  • latency matters.

If you want a reusable workflow that runs in the main context, the docs point to a Claude Code skill instead (see Extend Claude with skills). Anthropic’s guide How and when to use subagents in Claude Code covers the delegate-or-not decision in more depth.

Built-in subagents you already have

Claude Code ships built-in subagents, including Explore (read-only, for searching and analyzing code), Plan and general-purpose, per the docs. Explore and Plan skip CLAUDE.md and the git status snapshot; the other built-ins load them. Check the docs for the full list before relying on a specific built-in.

Step 1: create your first subagent

The quickstart asks Claude to create a personal subagent in ~/.claude/agents/. The resulting file looks like this (copied from the docs):

---
name: code-improver
description: Scans files and suggests improvements for readability, performance, and best practices. Use after writing or modifying code.
tools: Read, Grep, Glob
model: sonnet
---

You are a code improvement specialist. For each issue you find, explain
the problem, show the current code, and provide an improved version.

Test it with a plain request:

Use the code-improver agent to suggest improvements in this project

The delegation shows up as code-improver(Suggest code improvements). The docs say the /agents view reminds you that you can also edit the agent folders directly. If a new subagent is not found, restart the session, but the docs say this applies only when ~/.claude/agents/ did not exist before the session started. Added or edited files are otherwise picked up within seconds, with an exception for directories added through --add-dir.

Where subagent files live

Location Scope Commit it?
.claude/agents/ Current project Yes, to share with the team
~/.claude/agents/ All your projects No, personal

Per the docs, when two subagents share a name, the higher-priority location wins; the project folder ranks above the user folder. Managed settings and the --agents flag also define subagents, so check the full priority table in the docs before relying on an override. Subagent folders are scanned recursively, identity comes only from the name field, and names must be unique. Subagents shipped by plugins ignore the hooks, mcpServers and permissionMode fields.

Frontmatter fields that matter

Only name and description are required. Claude decides when to delegate mostly from description, so write it as a trigger: what the agent does and when to use it. Adding “use proactively” encourages delegation.

Field What it does
name Unique identifier.
description When Claude should delegate to this subagent.
tools Allowlist, as a list or comma-separated string. Omitted means all tools are inherited.
disallowedTools Denylist of tools to remove.
model sonnet, opus, haiku, fable, a full model ID, or inherit.
permissionMode default, acceptEdits, auto, dontAsk, bypassPermissions, plan; manual is an alias for default.

The docs list further fields (maxTurns, skills, mcpServers, hooks, memory, effort, background, omitClaudeMd, isolation). Unknown fields are ignored without an error, so a typo in a camelCase name fails silently. The Markdown body is the system prompt. The subagent receives that prompt plus environment details such as the working directory, not the full Claude Code system prompt. For the hooks field and subagent lifecycle events, see the hooks reference and our Claude Code hooks examples.

Restrict what a subagent can do

Two documented approaches, both from the subagents docs:

tools: Read, Grep, Glob, Bash
disallowedTools: Write, Edit

The first is an allowlist: the subagent gets only those tools. The second removes specific tools from what it would otherwise inherit. To limit which subagents a main agent can launch, the docs use the form tools: Agent(worker, researcher), Read, Bash.

Here is a read-only reviewer modeled on the docs’ code-reviewer example, which uses tools: Read, Grep, Glob, Bash and model: inherit. The prompt body is our own shortened version, not the official one:

---
name: code-reviewer
description: Reviews code for bugs and maintainability. Use proactively after writing or modifying code.
tools: Read, Grep, Glob, Bash
model: inherit
---

You are a code reviewer. Run `git diff` to see recent changes, review only
those files, and report issues grouped by severity with the file and line.
Do not edit files.

Note that Bash is still a way to change files, so a reviewer that must never write should drop it, or you should enforce limits with permissions rather than prompt wording. That last point is our inference, not a documented guarantee.

Invoke a subagent

The docs describe three ways:

  1. Natural language: “Use the test-runner subagent to fix failing tests”. Claude may or may not delegate.
  2. @-mention: @"code-reviewer (agent)" look at the auth changes guarantees that agent runs.
  3. Whole session: claude --agent code-reviewer runs the session as that agent.

Common patterns

  • Isolate high-volume output. “Use a subagent to run the test suite and report only the failing tests with their error messages” keeps logs out of your main context.
  • Parallel research. Ask for independent investigations at once and receive summaries.
  • Chaining. Feed one subagent’s summary into the next step.

Pitfalls

  • Description budget. Past 15,000 cumulative tokens of descriptions (built-ins excluded), Claude Code warns at startup, though everything is still loaded. Keep descriptions short.
  • Plugin limits. Plugin subagents ignore hooks, mcpServers and permissionMode.
  • New agents directory. Restart only if ~/.claude/agents/ did not exist when the session began.
  • Context and token use. The docs warn that many subagents returning results consume main context, and each one spends its own tokens.
  • Silent typos. Unknown frontmatter fields are ignored, so check names such as disallowedTools exactly.

What to change in your setup

Items 1 to 4 follow the docs; item 5 is our inference.

  1. Move recurring noisy tasks (test runs, log digging, codebase search) into a subagent with a narrow description.
  2. Commit shared subagents to .claude/agents/ and keep personal ones in ~/.claude/agents/.
  3. Set tools explicitly on every subagent instead of inheriting everything.
  4. Add @"name (agent)" to your workflow when you need a specific agent, not a guess.
  5. Audit your combined descriptions and drop the ones you never trigger, since each one is loaded at startup.

FAQ

Where do Claude Code subagents live?
In Markdown files with YAML frontmatter. `.claude/agents/` holds project subagents you can commit, and `~/.claude/agents/` holds your personal ones. Higher-priority locations exist, so check the scope table in the [subagents docs](https://code.claude.com/docs/en/sub-agents).
Which frontmatter fields are required for a Claude Code subagent?
Only `name` and `description`. Everything else, such as `tools`, `model` or `permissionMode`, is optional, and an omitted `tools` field means the subagent inherits all tools ([docs](https://code.claude.com/docs/en/sub-agents)).
How do I make a Claude Code subagent read-only?
Use an allowlist such as `tools: Read, Grep, Glob`, or a denylist such as `disallowedTools: Write, Edit`. Both are documented in the [subagents docs](https://code.claude.com/docs/en/sub-agents).
How do I force Claude Code to use a specific subagent?
@-mention it, for example `@"code-reviewer (agent)" look at the auth changes`, or start the whole session with `claude --agent code-reviewer` ([docs](https://code.claude.com/docs/en/sub-agents)).