TL;DR — Claude Code's
descriptionfield is not a human-readable summary. It's the routing signal the dispatcher reads to decide whether to invoke your subagent. Write it like documentation and your agent never fires. Write it in trigger phrases and it runs when it should.
The agent that sat there doing nothing
I wrote a subagent I was proud of. Solid instructions, tight scope, the works. Dropped it in ~/.claude/agents/, opened a project, did exactly the kind of task it was built for — and nothing happened. Claude just did the work itself, inline, ignoring the agent entirely.
I assumed I'd misconfigured something. I hadn't. The agent was fine. The problem was the one field I'd treated as an afterthought: the description. I'd written it the way you'd write a README line:
description: An expert code reviewer that analyzes your code for quality and bugs.
That sentence is for a human browsing a list. It is almost useless to the thing that actually decides whether to call my agent.
The description is a routing signal, not a summary
Here's the part the docs don't emphasize enough: Claude Code has a dispatcher that, on each turn, looks at what you asked for and decides whether any subagent should handle it. The only thing it has to make that decision — before reading the agent's body at all — is the description field.
So the description isn't documentation. It's a classifier input. Its entire job is to help the dispatcher answer one question: "Does this user's request match this agent?"
"An expert code reviewer that analyzes your code for quality and bugs" answers that badly. It describes an identity ("an expert reviewer"), not a trigger. The dispatcher is trying to match your request — "can you check this before I push?" — against the description, and "expert code reviewer" gives it very little surface to match on.
What a triggering description looks like
Compare. Here's the same agent, rewritten so the dispatcher can actually route to it:
description: Use when the user is about to commit, push, or open a PR and
wants a final check on their changes. Triggers on "review my changes",
"is this ready", "check before I push", "anything I missed". Reviews the
current diff for bugs and risk — not style or naming.
Look at what changed:
- It leads with *when to use it* — "Use when the user is about to commit, push, or open a PR." The dispatcher is matching situations, so describe the situation.
- It lists literal trigger phrases — "review my changes", "is this ready", "check before I push". These are the actual words a user types. Giving the dispatcher real phrasings to match against is the single biggest improvement you can make.
- It states an anti-trigger — "not style or naming." This stops the agent from grabbing requests that belong to a different agent (or to Claude itself). Scoping out is as valuable as scoping in.
That's the whole trick. The body of the agent can stay exactly the same. Just the description determines whether it ever gets a chance to run.
The anatomy of a description that fires
A reliable pattern, in order:
description: Use [PROACTIVELY] when [situation]. Triggers on [literal user
phrases]. [What it does in one clause]. [Anti-trigger: when NOT to use it].
-
Use PROACTIVELY when...— the wordPROACTIVELYis a real signal. It nudges the dispatcher to offer the agent without the user explicitly asking, for situations where that's wanted (a pre-commit check, say). Use it deliberately; don't sprinkle it on everything or every agent becomes pushy. -
Triggers on "..."— the highest-leverage part. Put 3–5 real phrasings a user would actually type. Think about how you would ask for this thing on a tired Friday, not how you'd formally describe it. - One clause on what it does — enough for the dispatcher to disambiguate between two similar agents.
- An anti-trigger — "not X", "does not handle Y". Prevents overlap and false fires.
How to test whether it routes
Don't guess. After writing the description, open Claude Code and say the trigger phrase you put in the description. If the agent fires, the routing works. If it doesn't, your description and your real phrasing have drifted apart — fix the description to match how you actually talk.
A good loop: use the agent for a week, notice the times you wanted it and it didn't fire, and add those exact phrasings to the Triggers on list. The description is a living classifier; tune it against reality.
See it in a real agent
If you want a working reference, my free, MIT-licensed Claude Code agent has a description written exactly this way — situation, trigger phrases, anti-triggers, and a deliberate PROACTIVELY:
üëâ github.com/allcanprophesy-ops/claude-code-shipping-coach
cp shipping-coach.md ~/.claude/agents/
Open the file and read the frontmatter — the description is doing real routing work, and it's the part worth copying before anything else. A few more agents built the same way (pr-surgeon, regression-sentinel, test-gap-hunter) are linked from the README, but start by reading one description closely. It's the most important line in the file.
Have you written a Claude Code agent that just never fires? Paste its description in the comments and I'll suggest how to make it trigger.
Top comments (0)