Skip to content

Writing Skills That Trigger

The best skill body in the world is worthless if the agent never loads it. Under the Agent Skills standard, only the frontmatter name and description sit in the system prompt full-time (Module 02's layer one), so the description alone decides whether the skill is ever discovered. Under-triggering — a skill that quietly never fires — is the single most common way a skill delivers zero delta despite being well written. Get the description right first; everything else is downstream.

The description is a trigger, not a summary

A description isn't a blurb about the skill; it's the matching rule the agent uses to decide this request needs this skill. That makes its shape specific. Lead with a third-person capability statement, list concrete "Use when" triggers phrased the way a real user actually asks, and fence the skill off with "Don't use for" negatives so it doesn't fight its siblings.

# Weak — a summary. What user phrasing should match this? Unclear.
description: A helpful tool for looking at incidents and system health.
# Strong — a trigger. Note the real-user phrasings and the negative fence.
description: >-
  Triages production incidents: pulls recent alerts, correlates deployments and
  error spikes... Use when investigating an outage, a latency spike, a surge in
  errors... or when asked "what's broken" / "why are bookings failing". Don't
  use for postmortem writing (use the postmortem skill) or filing routine bugs.

The negative fence matters more than it looks. sql_analytics ends its description with "Don't use for building dashboards... or for raw production database access" — that single line is what stops it from triggering on a dashboard request that a vaguer sibling should own. Without it, two skills squabble over the same prompt and the agent picks unpredictably.

Triggering fails in two directions, and both cost you. Under-triggering — the description too vague or too narrow to match how users actually phrase things — means the skill sits unused and its lift is zero no matter how good the body is. Over-triggering — a description so broad it fires on requests it can't actually help — is worse than useless: it burns context and steers the agent wrong on tasks a different skill should own. The capability statement fixes the aim; the "Don't use for" line trims the overreach. Write both, then sanity-check them against real prompts, not the ones you wish users would send.

Signal, not noise

Every line in a skill competes for context with every other line. A sentence that restates what the model already knows doesn't just fail to help — it dilutes the lines that do. Keep the gotchas, the exact commands, the conditional flags, the domain rules the model can't derive. Cut the boilerplate it recites on request.

<!-- Noise: the model already knows what a webhook is -->
Webhooks are HTTP callbacks that notify your service when an event occurs.
Remember to handle errors and validate your inputs.
<!-- Signal: a specific failure mode from partner_api the model can't guess -->
Signatures are HMAC-SHA256 over the raw request body. Frameworks that parse
JSON before your handler (Express body-parser, Flask get_json) re-serialize
with different whitespace, so verification fails intermittently. Verify raw bytes.

The test is mechanical: if deleting a line wouldn't change what the agent does on some task you haven't tried, the line is noise.

The caps-lock smell

Reach for MUST / ALWAYS / NEVER in capitals and you've usually found a place where you couldn't articulate why something matters, so you turned up the volume instead. Models comply better with an understood reason than a shouted rule, because a reason generalizes to the edge cases the rule never names.

- ❌ MUST use --format=proto for large outputs.
- ✅ Use --format=proto for large outputs (JSON silently truncates past 64KB).

The second version teaches the agent when the rule applies — so it makes the right call on a case you never wrote down. Reserve caps for genuine safety and irreversibility — and notice how rarely even those need them. incident_triage carries a real safety rule ("Don't page an owner from this workflow... recommend the page; the human decides") and states it in plain prose, no capitals. If a line about not paging humans at 3am doesn't need shouting, your ordinary rules certainly don't.

Experience before theory

The highest-signal skills are written from scratch by doing the task yourself, without a skill, and recording every failure, wrong turn, and missing fact. Those failures are the skill. Speculating about what an agent might need produces plausible-sounding noise; watching what actually breaks produces the exact gotchas — the UTC/local timestamp mismatch, the sandbox key that expires at 30 days — that no amount of armchair authoring would surface. Write the failure log first, then turn it into instructions.

One caution as you turn failures into rules: generalize, don't overfit. You'll test a skill on a handful of prompts, but it runs on thousands, so after each fix ask whether the change would help on a prompt you haven't seen or just patches the one in front of you.

<!-- Overfit: patches your test case, rots the moment the ID changes -->
For run 12345, pass --run-id=12345.
<!-- Generalized: states the underlying rule, works on every future ID -->
Pass IDs via --run-id; the tool rejects bare numeric arguments.

Encode the reason, not the instance — the same rationale-over-rules discipline as the caps-lock fix, now applied to how wide your rule reaches.

Key takeaways

  • The description is a trigger, not a summary: capability statement + real-user "Use when" + "Don't use for" negatives.
  • Every line must earn its context; delete anything that wouldn't change agent behavior on an untested task.
  • Prefer rationale to capitalized commands — an explained rule generalizes; a shouted one doesn't.
  • Author from lived failures, not speculation. The failure log is the draft.

Drill it

  • ex02_experience_before_theory — do a task cold, log the failures, and turn the log into a draft SKILL.md.
  • ex03_fix_the_trigger — repair a deliberately vague description, using validate_skill.py as your feedback loop.
  • ex04_signal_vs_noise — cut a bloated body down and convert caps-lock directives into rationale.

(Exercises unlock in the Exercises section; direct links are wired as each one lands.)