Triggers That Actually Fire
At decision time the model has read your skill's description and nothing else — so the proactive-invocation contract, and the rationalization counters that hold it back, both live or die in that one field.
The model sees one field
Everything in the previous two lessons converges here. A skill can have a perfect body — a host-check, a hard verification gate, a complete rollback runbook — and still be worthless, because at the moment the model decides whether to fire the skill, it has read your description and nothing else.
That is not a limitation to work around. It is the contract. The body loads after the skill fires. The supporting files load on demand. At decision time, the model is scanning a list of skill descriptions against the current situation, and the only skills that can fire are the ones whose descriptions match. If your trigger isn't in the description, the skill does not fire — full stop.
This lesson is about writing the one field that decides everything: the proactive-invocation contract, and the rationalization counters that hold it back from the wrong cases.
What firing actually looks like
Follow the flow. A user says "ok the PR merged, push this to production." The model doesn't read your skill bodies to decide — it can't, they're not loaded. It scans descriptions. Three skills are candidates:
deploy-prod, whose description says "…after a PR merges. Triggers: push to production, redeploy backend." — a clear match.run-tests, whose triggers are about tests — no match.deploy-helper, whose description is just "Helps with deploys." — too vague to fire, even though it's about deploying.
That last one is the heartbreaker. deploy-helper is genuinely a deploy skill. Its body might be excellent. But "Helps with deploys" gives the model no concrete surface to match "push this to production" against, so it stays dormant and the model improvises a generic deploy instead. The skill might as well not exist.
The branch at the bottom is the whole game. If the description carried the contract, the skill fires, the body loads, and your host-check and gate do their job. If the description was vague, none of that machinery ever runs.
Writing triggers that match reality
A trigger phrase is not documentation — it's a target for pattern-matching against how a real user phrases a real situation. That changes how you write them.
Weak triggers restate the capability in the author's vocabulary:
description: Deploys backend changes to production.
True, but it describes what the skill is, not when a user invokes it. A user rarely says "I would like to deploy backend changes to production." They say "ship this," "push it live," "the PR's merged, send it."
Strong triggers carry a WHEN clause plus the natural-language phrasings:
description: >-
Deploy a backend or cron fix to the production runtime, end-to-end.
Use when shipping a backend change after a PR merges to main.
Triggers: deploy to prod, ship this to production, redeploy the backend,
push the merge live.
The WHEN clause ("after a PR merges to main") gives the model situational context. The trigger phrases give it concrete surface in the user's own language. Together they let the model recognize the live situation and fire — which is the entire definition of proactive invocation.
A practical rule: write triggers by imagining three different people describing the same situation in their own words, then put all three phrasings in. The model is matching against natural language, so feed it natural language.
The other half: rationalization counters
A phenomenal trigger contract is two-sided. Firing for the right case is half of it. Refusing the wrong case is the other half — and it's the half most authors skip.
The problem is that the model will rationalize. Given a heavyweight audit skill and a single-file question, it can talk itself into "well, a one-file review is still an audit." Given a deploy skill and a tiny change, "it's so small, I can deploy from here." These are reasonable-sounding rationalizations, and without a counter, the skill fires on the wrong case and does damage.
Each row is a real misfire prevented by one line. Read the middle column as the model's internal monologue and the right column as the sentence in the skill that shuts it down:
/audit-swarmwould fire a multi-agent swarm for a trivial question — unless "NOT for single-file reviews; use /code-review" is there to stop it./deploy-prodwould let the model deploy from a local shadow stack on a "small" change — unless "NOT from a local stack; host-check FIRST" is there./retrowould file a noise retro for a no-code conversation — unless "NOT for Q&A sessions that produced no code changes" is there./incidentwould spin up a P0 process for a failing unit test — unless "NOT for failing CI; use /debug-investigate" is there.
The pattern: name the specific rationalization, then redirect to the right tool. A counter that just says "don't misuse this" does nothing — the model doesn't think it's misusing anything. A counter that names the exact adjacent case ("a one-file review is still an audit") meets the rationalization head-on.
The best place for the most important counters is the description itself or the top of the body — the WHEN clause and the WHEN-NOT-TO-USE together form the firing contract. Author the misuse, not just the use.
Build it: write the firing contract both ways
You'll write the complete proactive-invocation contract for a skill that opens a production incident — the description with trigger phrases and a WHEN clause so it fires on a real outage, plus a rationalization counter that stops it from firing on a failing local test. Both halves. A skill that fires for the right thing but not against the wrong thing is only half a contract.
What's next
You've now built the firing contract — the field the model reads to decide, and the counters that hold it back. That completes the foundation of skill quality: the authority bar (661), the anatomy and disclosure model (662), and the triggers that make a skill fire at all (663). From here, every skill you author should be tested the right way — not "does it run when I name it," but "does it fire when the situation appears, and stand down when it shouldn't."
The next two lessons shift from the firing contract to enforcement: the hooks pair. PreToolUse (664) is the gate that can stop a bad action before it happens, and PostToolUse (665) is the verifier that inspects the aftermath and feeds failures back. Descriptions and counters persuade the model; hooks don't have to — they are mechanical, and that difference is the whole point of the pair.