KaairosGet the kit
Guide · 7 min read

Why your Claude Code subagent isn't being called

Claude delegates to a subagent by reading its description, not its system prompt. If yours never fires, the description is usually written like a bio instead of a routing rule.

If a Claude Code subagent you defined never runs, the cause is almost always the same: Claude decides whether to delegate by reading each subagent's description field, and yours reads like a job title instead of a trigger. Claude never opens the subagent's system prompt until after it has decided to hand off, so the description is the entire routing surface. Fix the description first, then rule out a name collision, a tool or model mismatch, and — when you need certainty — invoke the subagent explicitly with an @-mention.

This guide walks through how auto-delegation actually decides, the before-and-after that makes a description fire, the silent overrides that hide behind /agents, and a six-point checklist to run when a subagent stays stubbornly idle.

How auto-delegation actually decides

When your session starts, Claude Code registers every subagent it can find and loads only their name and description into context — not their bodies. On each turn, Claude matches the task in your request against those descriptions and, when one fits, delegates through the Agent tool. The subagent then works in its own context window and returns only a summary. For how subagents compare with the other primitives, see skills vs subagents vs commands.

Two things follow from this. First, the description does all of the routing work; the careful system prompt you wrote is invisible at decision time. Second, delegation is probabilistic — Claude weighs your wording, the description, and the current context together, so a vague or overlapping description loses to Claude simply doing the work itself in the main thread. Practitioners describe exactly this: Claude frequently handles a task inline even when a relevant subagent exists, because nothing in the description made the match obvious.

It also means some tasks are handled inline by design, and that is not a bug. Claude is told to prefer the main conversation for quick, targeted changes, where spinning up a separate context window would only add latency — so a subagent staying quiet on a one-line edit is expected behaviour. The signal that something is genuinely wrong is a subagent sitting idle on exactly the kind of work its description claims: a review agent that never reviews, a test agent that never runs the tests. That is a routing failure, and the sections below are how you diagnose it.

The description is a routing cue, not a bio

The most common broken description names what the subagent is. Claude cannot match against an identity; it matches against situations. Rewrite the field to say when to use the subagent, in the concrete words a real task would use, and add an explicit nudge to delegate.

# Before: reads like a bio, rarely fires
---
name: code-reviewer
description: A senior engineer who cares about code quality.
---

# After: names the trigger, delegates proactively
---
name: code-reviewer
description: Reviews changed files for security, correctness, and style. Use proactively immediately after writing or editing code, before committing.
---
The load-bearing fieldLead the description with the situation, not the role. Name the file types, the moment in the workflow, and the phrasings a request would use, and add a cue like 'use proactively' when you want Claude to reach for it unprompted. The same rule governs skills: the description is the trigger, not a summary.

Rule out silent overrides in /agents

If the description looks right and the subagent still never runs, check for a collision. Subagent identity comes only from the name field, and names must be unique across the tree. When two files under the same .claude/agents/ directory declare the same name, Claude Code loads only one of them, chosen by filesystem read order, with no error and no warning. A user-level subagent in ~/.claude/agents/ can also be shadowed by a project subagent of the same name, because project scope wins over user scope.

The /agents command is the front door here; recent versions point you to edit .claude/agents/ directly rather than opening a wizard, so inspect that directory and ~/.claude/agents/ by hand to confirm what is registered, and run /doctor to have Claude Code report duplicate names. One more trap: the file watcher only covers directories that existed when the session started, so the very first agent you add to a brand-new .claude/agents/ folder will not appear until you restart Claude Code.

Model and tool mismatches that block a launch

A subagent that gets selected can still fail to launch. The tools field is an allowlist: if nothing in it resolves to a real tool — a typo, or a tool that is not available to subagents — Claude Code refuses to spawn the subagent and returns an error naming the unresolved entries. Leave tools off entirely to inherit the default set, or list only tools you know exist.

The model field accepts sonnet, opus, haiku, a full model ID, or inherit, and defaults to inherit. If your organisation restricts models with an allowlist, a model that resolves to an excluded model is skipped and the subagent quietly runs on the inherited model instead — worth knowing if you set model: haiku to control cost and watch it get ignored. Background subagents also run with a smaller built-in tool set than foreground ones, so the same definition can end up with different tools depending on where it runs.

Force it: name it, @-mention it, or run as the session

When you do not want to leave delegation to chance, three patterns escalate from a hint to a guarantee:

  • Name it in the prompt — 'Use the code-reviewer subagent to look at my changes.' Claude usually delegates, but still decides.
  • @-mention it — type @ and pick the subagent from the typeahead, or type @agent-<name>. This guarantees that subagent runs for the task.
  • Run the whole session as it — launch with claude --agent <name> so the main thread takes on that subagent's prompt, tools, and model.
Use the test-runner subagent to fix the failing tests
@agent-code-reviewer look at the auth changes
claude --agent security-reviewer

If the @-mention typeahead is empty or your mention silently turns into a generic task, that is a known class of regression rather than a description problem — one such bug was reported against Claude Code 2.0.1. Check claude --version, restart the session, and confirm the file really sits in .claude/agents/ before assuming your own configuration is at fault.

The six-point checklist

  1. Does the description name a situation and a trigger, not a role? Add 'use proactively' if you want automatic delegation.
  2. Is the name unique across .claude/agents/ and ~/.claude/agents/? Run /doctor to catch silent duplicates.
  3. Did you add the file to a brand-new agents directory? Restart so the watcher picks it up.
  4. Does every entry in tools resolve to a real tool, or is tools omitted so it inherits the default set?
  5. Is model a value your organisation actually allows, or is it being silently downgraded to the inherited model?
  6. Still not firing? Stop relying on auto-delegation and @-mention the subagent, or run the session with --agent.

Most idle subagents come down to point one. Claude routes on the description, so write it for the router — the moment and the words that should trigger a hand-off — and treat the system prompt as what the subagent does once it has already been chosen. Keeping your .claude/ small helps here too: when you install fifty agents you never call, their descriptions compete with each other and dilute every match. A well-written CLAUDE.md does the same job for your main thread that a tight description does for a subagent.

Sources

Keep reading