DEV Community

Rulestack
Rulestack

Posted on

Claude Code subagents: when to delegate, and when a rule or hook is enough

Your main conversation's context window is the scarcest resource you have. Every search result, every log dump, every file you open "just to check" stays in context and competes with the actual task. By the time you've explored a codebase to answer one side question, the conversation that was supposed to implement a feature is half full of things you'll never reference again.

Subagents are Claude Code's answer to that problem — and to a couple of others that look unrelated until you see the mechanism. But like rules files and hooks, they're a tool with a specific shape, and most of the disappointment I see comes from reaching for them when a rule or a hook was the right layer.

This is the fourth post in a series on the control layers of AI coding agents: how rules files actually load, hooks as enforcement, and pruning the rules that do nothing. Same approach here: what the mechanism actually is, then a decision framework you can apply in ten seconds.

What a subagent actually is

A subagent is a separate agent with its own context window, its own system prompt, and its own tool allowlist. When Claude delegates a task to it, the subagent does the work in its own context and returns a summary. The search results, file contents, and dead ends stay in the subagent's window and get discarded; only the conclusion lands in your conversation.

Concretely, a subagent is a Markdown file with YAML frontmatter. There are five places Claude Code can load one from (managed settings, a CLI flag, project, user, plugins), but two you'll actually use day to day:

  • .claude/agents/ — project-scoped, checked into version control, shared with your team
  • ~/.claude/agents/ — user-scoped, available in every project on your machine

A minimal, genuinely useful one looks like this:

---
name: code-reviewer
description: "Reviews code for correctness, security, and maintainability"
  issues. Use proactively after writing or modifying code.
tools: Read, Grep, Glob
model: sonnet
---

You are a senior code reviewer. For each issue: state the problem,
show the offending code, explain the failure scenario, and suggest
a fix. Rank findings by severity. Do not comment on style that a
formatter would fix.
Enter fullscreen mode Exit fullscreen mode

Only name and description are required. tools inherits everything if omitted — listing Read, Grep, Glob is what makes this reviewer read-only, which matters more than it looks (more below). model defaults to inherit; setting it routes the work to a cheaper or stronger model than your main conversation.

Two things about invocation:

  1. Automatic delegation is driven by the description field. Claude reads it to decide when to hand work over. "Use proactively after writing or modifying code" is a routing instruction, not documentation.
  2. You can invoke explicitly: "use the code-reviewer subagent on this diff." If auto-delegation never triggers, your description is too vague — that's the single most common failure mode.

One currency note, since most tutorials out there predate it: as of v2.1.198 the /agents interactive wizard is gone. You create subagents by asking Claude to write the file, or by writing it yourself. The file format and locations are unchanged.

The three-layer mental model

If you've read the earlier posts, here's where subagents slot in:

Layer What it is When it fires Costs
Rule (CLAUDE.md / .cursorrules) A preference, in prose Always in context Context space, every turn
Hook A deterministic gate On specific tool events A process spawn
Subagent Delegated judgment When a task matches its description A full agent run

A rule asks for behavior. A hook enforces a checkable condition. A subagent does a chunk of work somewhere else and reports back.

The framing I use: rules are preferences, hooks are controls, subagents are staff. You don't hire staff to remember that you prefer named exports (that's a rule), and you don't hire staff to check whether tests ran (that's a hook — it's a yes/no fact). You hire staff for work that requires judgment and would flood your desk if done in front of you.

The four cases where a subagent wins

1. Context isolation — the default reason

Any task whose intermediate output is large but whose conclusion is small: codebase exploration, dependency audits, log analysis, "find every place we handle currency rounding." Done in the main conversation, that's dozens of file reads polluting context for the rest of the session. Done in a subagent, it's one summary paragraph.

Worth knowing before you build a custom one: Claude Code ships a built-in Explore subagent for exactly the read-only-search case. Define your own when you need a specialized lens on exploration — an accessibility auditor, a security-focused reader — not just search.

2. Constraint enforcement — the underrated reason

The tools allowlist is a hard boundary, not a suggestion. A reviewer with tools: Read, Grep, Glob cannot "helpfully fix" the code it reviews — the write tools don't exist in its world. A migration planner without Bash cannot run anything.

This is the same argument as hooks-over-prose from part 2: a rule saying "the reviewer should not modify files" is a preference the model can drift past; a tool allowlist is a control it can't. When someone asks "how do I stop the agent from doing X during Y," the answer is often not a sterner prompt — it's a subagent whose tool list makes X impossible.

3. Clean-room judgment

A subagent starts with no view of your conversation history. It sees its system prompt and the task description Claude passes it. That's a constraint (covered below), but it's also the point: your main conversation is full of your framing, your justifications, the three approaches you already talked yourself out of. A reviewer that can't see any of that judges the diff on its merits. You get something closer to a second opinion than an echo.

4. Cost and latency routing

model: haiku on a subagent that does mechanical scanning (collect TODOs, list untested exports, extract API surfaces) routes bulk work to a fast, cheap model while your main conversation stays on a stronger one. The other direction works too: keep the main session light and route one hard verification task to a stronger model with higher effort.

When a subagent is the wrong tool

  • The task needs your conversation's context. The subagent starts blank. If the delegation prompt would have to include half your session to make sense, the work belongs in the session. Corollary: when you do delegate, the prompt must be self-contained — "fix the bug we discussed" hands the subagent nothing.
  • Quick, interactive edits. A subagent run is a full agent lifecycle. For a rename or a three-line fix, delegation is pure overhead.
  • A yes/no condition. "Did tests pass," "does the commit message match the format," "is this file forbidden" — that's a hook. Spawning an agent to check a boolean is using staff to read a thermometer.
  • A one-off task. Claude Code can spin up a general-purpose task without any custom definition. Write a subagent file when you notice you keep spawning the same worker with the same instructions — that's the signal it deserves a name, a tuned prompt, and version control.

Failure modes that actually happen

The vague description. description: Helps with code will never be auto-delegated to, because it gives the router nothing. Say what it does and when to use it: "Audits SQL for injection and missing indexes. Use before merging schema or query changes."

The kitchen-sink agent. One helper subagent that reviews, fixes, documents, and deploys has no routing signal and no meaningful tool boundary. The value comes from specialization — several small agents with sharp descriptions beat one omnibus.

Assuming shared memory. "Why did the subagent ignore our conventions?" Because your conventions were discussed in a conversation it never saw. Anything it must honor goes in its system prompt (the Markdown body) — or in project rules files, which subagents do load.

Unversioned project agents. A .claude/agents/ directory that lives only on your machine is a convention your teammates don't have. Check it in. Review changes to it like code, because it is code — it runs with tool access.

Routing three real requests

To make the decision framework concrete, here's how three requests that come up constantly route:

  1. "The agent should always run the linter before committing." Checkable, deterministic, event-shaped → hook. A rule gets forgotten; a subagent is overkill.
  2. "We prefer composition over inheritance in new code." Judgment, always-on, cheap to state → rule. There's nothing to delegate and nothing to gate.
  3. "Before every release, check our public API against the changelog for undocumented breaking changes." Judgment + large intermediate reads + recurring with identical instructions → subagent, read-only tools, invoked explicitly in your release checklist.

If you can't decide, ask two questions in order: Is it a checkable fact? → hook. Is the intermediate work bigger than the conclusion? → subagent. Everything else starts as a rule — and per part 3, gets deleted later if it never earns its place.

The uncomfortable conclusion

Same shape as the rules-file conclusion, one layer up: the end state of a good agent setup is boring. A short rules file that survived deletion testing, a handful of thin hooks enforcing checkable facts, and two or three sharply-scoped subagents you actually reuse. If you have eleven subagents and can't remember what half of them do, you've rebuilt the rules-file bloat problem with more moving parts — and each one runs with tool access.

Start with one: the read-only reviewer above. It exercises all four wins at once — isolation, constraint, clean-room judgment, and model routing — and it's the one you'll invoke every day.


I maintain Rulestack — rule packs, hooks, and subagent patterns for Cursor, Claude Code, and Codex, audited against current tool behavior. If this series is useful, I post working notes on Bluesky at @ai-shop.bsky.social.

Top comments (0)