Original URL: https://getagenttools.com/blog/claude-code-subagents/

# Claude Code subagents: two files, 125 dispatches, and the work that never touched my context

7 Sep 2026Marek.

- claude-code
- agent-ops
- context-engineering

Claude Code subagents are separate Claude instances that take one task from your main session, run it in their own context window with their own system prompt, tools and permissions, and hand back a result. The searches, logs and file dumps they produce stay in their transcript, not yours. I run two of them from two markdown files, and a grep over my session transcripts on 4 September counted 125 dispatches across 44 sessions. This post is what the docs promise, what those runs taught me, and one leaked secrets file.

 

- **What it is.** Per the [docs](https://code.claude.com/docs/en/sub-agents), "specialized AI assistants that handle specific types of tasks", and each one "runs in its own context window with a custom system prompt, specific tool access, and independent permissions". A markdown file with YAML frontmatter defines one.
- **What comes back.** Only the final result. Conversation history does not flow in, except for forks, and tool output does not flow out.
- **What decides delegation.** The `description` field. Claude reads it to match tasks, so it is the most important line in the file.
- **What mine look like.** `deep-reasoner` on `opus` for the hard thinking, `fast-worker` on `haiku` for mechanical jobs with a spec. Twenty lines each.
- **The rule I learned the hard way.** A subagent on a file with secrets gets `grep -n` for one line, never `cat`. It will run the literal command and paste the result into your transcript.

 

Everything here runs inside the [Claude Code](https://getagenttools.com/tools/claude-code/) install I already reviewed.

  

## Can Claude Code have multiple agents?

 

Yes. Claude Code ships with built-in subagents and lets you define your own, and a session can run many of them at once. The [subagents documentation](https://code.claude.com/docs/en/sub-agents) puts the default ceiling at 20 concurrent subagents and three levels of nesting below the main conversation. Each one is a fresh instance, not a continuation of an earlier one.

 

The docs name six. Three do the general work. `Explore` is a fast, read-only agent for searching and analyzing a codebase, invoked with a thoroughness level of `quick`, `medium` or `very thorough`. `Plan` is the read-only research agent used in plan mode. `general-purpose` gets the full tool set for multi-step work. The other three sit in the docs' "Other" tab: `claude`, the catch-all with every tool available to subagents, for a task that fits no specialized agent; `statusline-setup` behind `/statusline`; and `claude-code-guide` for questions about Claude Code itself. Explore and Plan skip CLAUDE.md files and the parent session's git status, in the docs' words "to keep research fast and inexpensive".

 

Where a definition can live, in the docs' priority order: managed settings, a JSON blob passed with the `--agents` CLI flag for one session, `.claude/agents/` in the project, `~/.claude/agents/` for every project on the machine, and a plugin's `agents/` directory. Project definitions are found by walking up from the working directory; the closest wins.

 

## What a subagent gets, and what it never sees

 

The isolation is the point, and the docs list both sides. A subagent receives:

 

- its own system prompt rather than Claude Code's;
- the task message Claude wrote for it;
- the CLAUDE.md hierarchy, except for Explore and Plan;
- a git status snapshot, with the same exception;
- any skills listed in its `skills` field;
- a roster of sibling agents, if it has `SendMessage` in its tools and at least one other agent in the session carries a name.

 

It does not receive the conversation history, the session's output style, the session's auto memory, or skills the main session invoked earlier, which it has to rediscover through the Skill tool. The docs name one exception: a fork "inherits the entire conversation so far instead of starting fresh" and "sees the same system prompt, tools, model, and message history as the main session". Even then, "the fork's own tool calls still stay out of your conversation and only its final result comes back".

 

Two consequences follow. "Fix the bug we discussed" delegates nothing, because the message and the files are all it has. And the return path is a summary, so a finding that did not make it into the final report might as well not exist. The transcript survives on disk under `~/.claude/projects/{project}/{sessionId}/subagents/agent-{agentId}.jsonl` for 30 days by default (`cleanupPeriodDays`), but nothing reads it back for you.

 

## Does Claude Code automatically use subagents?

 

Yes, when a task matches a subagent's `description`. Claude reads that field to decide whether to delegate, so the wording matters most. The docs also let you force or block delegation: `@agent-<name>` in a prompt guarantees a run, `claude --agent <name>` makes one agent the whole session, and a `permissions.deny` entry such as `Agent(Explore)` blocks a type.

 

The automatic path has a cost the docs quantify. Subagent descriptions load into context at startup. When your own subagents' combined descriptions, built-in ones excluded, pass 15,000 tokens, Claude Code shows a warning at startup with the total. Keep the description short and move the detail into the body, which only loads when the subagent runs. The docs also list the tools a subagent never gets, whatever the file says, forks excepted: `AskUserQuestion`, `EnterPlanMode` and `ExitPlanMode` (the latter stays when the subagent's `permissionMode` is `plan`), `ScheduleWakeup`, `TaskOutput`, `Workflow`, `EndConversation`, `WaitForMcpServers`, and `Agent` itself once the depth limit is reached. So a subagent cannot stop to ask you a question; whether it guesses or reports back depends on what you wrote in its file.

 

To turn the automatic behavior off entirely, deny the `Agent` tool in `permissions.deny`. To drop only Explore and Plan, set `CLAUDE_CODE_DISABLE_EXPLORE_PLAN_AGENTS=1` (v2.1.198 and later).

 

## The two subagent files on my disk

 

My `~/.claude/agents/` holds two files. Both are 20 lines.

 

| Field | `deep-reasoner.md` | `fast-worker.md` |
| --- | --- | --- |
| `model` | `opus` | `haiku` |
| Used for | Architecture, hard debugging, data analysis with hypotheses, reviewing a plan before a build | Mass file edits, boilerplate, parsing logs and CSV, simple scripts, pulling data from an API to a written spec |
| The rule that matters | Missing data: say exactly what is missing and where to find it, instead of guessing | Spec unclear or contradictory: stop and return the question, do not guess |
| Numbers and state | Only from a source: file, query, log. No "will probably work" | No design decisions: names, architecture, thresholds belong to the orchestrator |
| Secrets | Credentials only from the panel file, never pasted into the answer | Same, plus no destructive operation (delete, overwrite, push) without an explicit line in the brief |
| Report format | Recommendation in one or two sentences, three to five points of evidence, risks and what would overturn the conclusion, what was missing | What was done, which files or results, what did not work or was skipped |

 

Matching the model to the job that way is my rule, not the docs'. What the docs fix is the resolution order: a `model` value on the invocation wins, then the frontmatter, then the `CLAUDE_CODE_SUBAGENT_MODEL` environment variable, then the main conversation's model. Set `CLAUDE_CODE_SUBAGENT_MODEL_FORCE=1` alongside `CLAUDE_CODE_SUBAGENT_MODEL` (v2.1.257 and later) and every subagent runs on the environment variable regardless of its file; set the force flag alone and subagents run on the main conversation's model.

 

My frontmatter is three lines: `name`, `description`, `model`; the docs require only the first two. Three optional fields are on my list to try. `isolation: worktree` runs the subagent in a temporary git worktree with an isolated copy of the repository, branched by default from your default branch rather than the parent session's `HEAD`, and cleaned up automatically if the subagent makes no changes. `memory: user` gives the agent its own persistent notes under `~/.claude/agent-memory/<name>/`, with its `MEMORY.md` preloaded up to 200 lines or 25 KB. `hooks` in the frontmatter take any hook event, most often `PreToolUse`, `PostToolUse` or `Stop` (`Stop` becomes `SubagentStop` at runtime), and fire only while that subagent is active, the same mechanism as the [production hook](https://getagenttools.com/blog/pretooluse-hook/) I run at the session level.

 

Three details matter before you write an agent file. A file with no `name`, or whose opening `---` is not the first line, is read as documentation and skipped without a word. A `name` that starts with `-` or contains a colon is skipped too, but that one lands in the debug log. And `claude plugin validate ~/.claude/agents` (v2.1.233 and later) checks the YAML before the session does.

 

## How many subagents can Claude Code spawn?

 

By default, 20 at the same time and three layers deep. Both numbers are settings: the docs name `CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS` for the concurrent limit and `CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH` for nesting, where a value of 1 means no nesting. The count is layers below your main conversation, so a value of 2 lets your subagent delegate once and stops the layer under it.

 

Foreground or background is the other axis. In an interactive session with fork mode on, the default, a subagent runs in the background and its result arrives as a completion notification; Ctrl+B sends a foreground one to the background; and `background: true` in the frontmatter forces it. Permission prompts from a background subagent surface in the main session with the subagent's name attached. Under `claude -p` and in the Agent SDK fork mode is off unless you turn it on. With fork mode off Claude still runs a subagent in the background by default, and moves it to the foreground only when it needs the result before continuing.

 

## Are Claude Code subagents worth it?

 

For work that produces more text than you will read, yes; for a task you want to steer mid-way, no. The dispatch that pays for the design is independent review of another agent's draft, because a subagent has no memory of how the draft came to be.

 

That is the worker and judge pattern this blog runs on. The writer is a fork, so it knows every source, rule and prior finding. The judge is `deep-reasoner` on a clean context with the draft and the brief. On 4 September the first judge pass on a post about an ad platform returned three blockers, two of them one false claim stated twice: that everyone who pays for a plan is outside the ad audience, when the vendor's help center says one paid tier sees ads.

 

The cost side is real: every run is a full model call with its own context, which is why the docs put cost control on the list of what subagents are for, and point at faster, cheaper models like Haiku. `/tasks` lists what is running; the transcripts under `subagents/` are what you open when a result looks too clean.

 

## Subagents vs skills, hooks and agent teams

 

Four mechanisms get confused in the same sentence. A skill is instructions that load into your context when invoked; a subagent is a separate context that runs and returns. "Do it this way" is a skill, "do it over there and tell me the result" is a subagent, and the `skills` field lets a subagent preload the former.

 

A hook is a shell command at a fixed lifecycle event. Subagent frontmatter can carry hooks scoped to that agent, and settings can carry `SubagentStart` and `SubagentStop` hooks around every run. Frontmatter hooks on a project-level agent in `.claude/agents/` run only after you accept the workspace trust dialog for the folder holding the file; until then the subagent still runs and Claude Code skips its hooks and logs an error (v2.1.218 and later). Hooks on user-level agents in `~/.claude/agents/`, and on definitions passed with `--agents`, run without that step.

 

Agent teams are peers that write to each other by design, experimental and off until you set `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1`. A subagent can reach a sibling too: the roster from the list above names `main` and every other named agent, each a valid recipient (v2.1.206 and later), and it is a snapshot taken when the subagent starts, so agents named later are not on it. The difference is who holds the plan: subagents report to the caller. `SendMessage` to a named subagent also resumes it with its context intact instead of starting a new one.

 

Since v2.1.210 Claude Code scans a subagent's report before Claude reads it, inserting backslashes into text that imitates Claude Code's own output and prepending a marker when a report imitates those tags or mentions permission settings. It removes nothing; it guards against a subagent, or a file it read, smuggling instructions back up the tree.

 

## The trap: a haiku worker and cat .env

 

On 3 June a subagent on `haiku` had one job: set one variable in a profile's `.env` file on a server, with "minus secrets" in its brief. It ran `cat` on the file, 476 lines, and pasted all of them into its report, an API key and a bot token included. The report landed in my session transcript, which outlives the session on disk.

 

The subagent did nothing wrong by its own rules: "minus secrets" is not an instruction a literal worker can execute. The fix went into the brief template, not the agent file. On any file that may hold credentials the worker gets three shapes: `grep -n '^KEY=' file` for the one line it needs, `grep -q '^KEY=' file && echo PRESENT || echo ABSENT` to check existence without printing, and an append that never reads the file. The cheaper the model, the narrower the instruction has to be, because it will do exactly what the words say.

 

## Subagents in Codex and Cursor

 

Codex documents subagents at [learn.chatgpt.com/docs/agent-configuration/subagents](https://learn.chatgpt.com/docs/agent-configuration/subagents): "ChatGPT Work and Codex can run subagent workflows by spawning specialized agents in parallel and then collecting their results in one response." A custom Codex subagent is a TOML file under `~/.codex/agents/` or `.codex/agents/` carrying a name, a description and developer instructions. It inherits the parent's model and reasoning effort, plus sandbox mode, MCP servers and skills, when its own file leaves them out.

 

Cursor documents its own at [cursor.com/docs/subagents](https://cursor.com/docs/subagents): "Subagents are specialized AI assistants that Cursor's agent can delegate tasks to. Each subagent operates in its own context window, handles specific types of work, and returns its result to the parent agent." Its file is markdown with frontmatter under `.cursor/agents/` or `~/.cursor/agents/`, closer to Claude Code's shape than Codex's TOML, and `Explore`, `Bash` and `Browser` are built in. Every path, field and limit in the sections above is Claude Code's.

 

## Best practices I actually follow

 

1. One agent file per job shape, not per project; the task message carries the specifics.
2. Write the `description` as the one-sentence condition for delegation; the rest goes below the frontmatter, where it costs nothing until the run.
3. Pick the model by the job: `haiku` with a written spec, `opus` for anything that needs a hypothesis.
4. Put every fact the subagent needs in the message or in a file path; it cannot ask.
5. Ask for a fixed report shape; the parent reads only that.
6. Never let a subagent `cat` a file that may hold a secret. One line by `grep`, or nothing.
7. Use a fresh-context subagent, not a fork, to judge anything a fork wrote, and start it after the writer's completion notification.
8. Run `claude plugin validate ~/.claude/agents` after editing an agent file.

 

Public catalogs of agent files exist, `awesome-claude-code-subagents` on GitHub among them; a reading list, not an install.

 

For tasks that change files in parallel, [isolate parallel edits with Claude Code worktrees](https://getagenttools.com/blog/claude-code-worktrees/). Review each branch before combining the changes.

 

The pattern underneath all eight is the one from [production-ready agents](https://getagenttools.com/blog/production-ready-ai-agents/): the model that did the work is not the model that grades it, and the [context window](https://getagenttools.com/blog/what-is-an-ai-context-window/) that matters is the one you keep the noise out of. A subagent is the simplest [agent](https://getagenttools.com/blog/what-is-an-ai-agent/) you will define.

 

Sources, read on 4 September 2026: Claude Code's [Create custom subagents](https://code.claude.com/docs/en/sub-agents) page and its [CLI reference](https://code.claude.com/docs/en/cli-reference); every path, limit, version number and quotation above comes from those two. Codex: [subagents](https://learn.chatgpt.com/docs/agent-configuration/subagents). Cursor: [subagents](https://cursor.com/docs/subagents). The agent files, the dispatch count and the June incident are from my own machine.

Put this into practice

[See the tool list](https://getagenttools.com/tools/)[Train your team](https://getagenttools.com/#training)
