Skip to content

Building Great Agent Skills: An Engineering Checklist

02/07/20268 min read

A practical four-pillar framework for writing agent skills that load cleanly, steer reliably, and stay out of the agent's way.

Open
Hand-drawn line illustration: the little black creature holds up a tiny SKILL.md index card; one thin reference page slides out of a giant binder-clipped book while crumpled no-op pages pile in a waste bin

Last month I shipped a skill that read like a textbook. The description was clear, the procedure was step-by-step, and the examples were there. I ran it, the agent loaded the file, summarized the first paragraph back at me, and went off to do its own thing.

Nothing was wrong with the model. Everything was wrong with the skill.

After watching this pattern repeat across half a dozen skills I’ve written and reviewed, I’ve landed on a four-pillar checklist. It’s the distillation of what works in skills I’ve shipped to production and what keeps going wrong in the ones I keep rewriting. Treat it as an engineering checklist, not gospel.

If you haven’t read the post on what skills actually are, start there. This one assumes you already know the basics and want to write good ones.


The mental model you need

A skill is code, not documentation. A SKILL.md is an entry point, not a deliverable. The agent loads it, decides whether to walk the procedure, and pulls in supporting reference files only when a specific branch fires. That progressive-disclosure behavior is the single most important thing to internalize. Design for it, and your skills stay small. Ignore it, and you end up with a 600-line Markdown file the model will inevitably skim past.

The four pillars below are all consequences of that one idea.

1. The trigger: user-invoked beats model-invoked, most of the time

The first design decision is how the skill wakes up. Two ways:

  • Model-invoked: the skill’s description sits in the agent’s system prompt or context. The agent reads it and decides on its own: “ah, I should use this skill now.”
  • User-invoked: the skill is invisible to the agent until you, the developer or operator, call it explicitly.

Model-invoked sounds more powerful. It usually isn’t. Every model-invoked skill you add costs you tokens on every single request, and it gives the agent one more thing to be distracted by. I’ve watched agents ignore perfectly good skills because the description was too generic, or fire a skill at the wrong moment because a phrase in the user’s prompt loosely matched its trigger.

User-invoked skills put the cognitive load on you to know when to use the tool. That cognitive load is the feature, not a cost. You pick the moment, the agent stays focused, and your token bill drops.

My rule of thumb: default to user-invoked. Switch to model-invoked only when the trigger is genuinely hard for a human to predict but easy for the agent to recognize from context. If you can articulate the trigger in a sentence, you can articulate it to the model too.

2. Structure: keep SKILL.md tiny

A skill has two kinds of content. Steps are the procedure the agent follows. Reference is the supporting templates, examples, or domain notes it might need along the way. Most SKILL.md files I’ve seen dump both into one document. Don’t.

Your only goal at the structure layer is to make SKILL.md as small as you can without losing clarity. Smaller skills load faster, audit better, and the agent follows them more reliably because there’s less to ignore.

The trick is to look at the branches in your skill. If a skill updates a glossary or generates an architecture document, the agent doesn’t need both templates at once. Push the templates out into a references/ folder and point at them from SKILL.md. The agent loads the right reference file only if it actually walks that branch.

<!-- SKILL.md -->

# Update a doc

1. Identify the doc type.
2. Follow the matching procedure:
   - Glossary: see @references/glossary.md
   - Architecture: see @references/architecture.md
3. Run the validation script in @scripts/check.sh.
<!-- references/glossary.md -->

# Glossary update procedure

(only loaded when the agent walks the glossary branch)

The @references/ pointer is a progressive-disclosure trigger. The model treats it as a hint to fetch the file when it needs to, not eagerly. If your skill runner doesn’t support that syntax, name the file plainly; the effect is the same as long as the file isn’t preloaded.

3. Steering: leading words, and hide the future

You’ve had this moment. You write a clear instruction, the agent reads it, and then does the opposite. Nine times out of ten, the fix is just better instructions, written denser.

Leading words are opinionated phrases that pack intent into a few tokens. If you want the agent to avoid coding layer by layer, you don’t write a paragraph begging it not to. You use the phrase “vertical slice” everywhere, and you make it the only phrase the agent hears when it’s about to make a structural choice. The model starts echoing “vertical slice” in its reasoning traces, and its behavior aligns with yours because it’s narrating itself toward your term.

I learned this from watching a colleague rewrite a refactor skill. The original was three paragraphs telling the agent not to do top-down rewrites. The rewrite was one line: “Implement vertical slices only.” Same outcome, a tenth of the tokens, and the model actually listened.

Hide the future is the second trick, and it’s about laziness. Agents are lazy the same way junior engineers are lazy: they want to ship something, anything, before they’ve earned the right to. If you ask an agent to “ask clarifying questions, then create a plan,” it will ask you two surface-level questions, declare the requirements clear, and rush into a mediocre plan.

The fix is to split the task into two distinct skills with no shared state. Run a grill-me-style skill first so the agent focuses entirely on interrogation. Only when that’s done do you invoke the planning skill. The agent can’t skip the leg work because the leg work lives in a different procedure that the planning skill doesn’t have access to.

This is the pattern I lean on in my own workflow. The grill-me skill sitting in my agents folder is literally an implementation of “hide the future”: it forces a planning step to do the work that another skill would otherwise skip.

4. Pruning: kill the no-ops, kill the sediment

The last pillar is editing. Skills rot the same way any shared document rots, but faster, because you pay for bloat on every single request.

Two patterns to watch for.

Sediment. This is what happens when multiple people edit a shared SKILL.md and nobody deletes anyone else’s rules. You end up with five paragraphs of contradictory guidance, half of it contradicting the other half. The author who would have deleted the bad paragraph was worried about stepping on toes. The result is a skill that reads like a committee wrote it, which means the agent will pick the easiest instruction to follow and ignore the rest. Sediment is a people problem disguised as a documentation problem.

No-ops. These are paragraphs that look important but don’t change the agent’s output. The test is mechanical: delete the paragraph and rerun the skill. If the output is identical, the paragraph was a no-op. Delete it. A common example is a paragraph telling the agent to “write a detailed commit message.” Modern models write detailed commit messages anyway. The paragraph costs you tokens and confuses the agent about which instruction to prioritize.

I keep a personal rule: if a paragraph in a skill doesn’t survive a deletion test, it doesn’t ship. Period.

The four-question audit

Before I merge any skill, I run it through this. Four questions, asymmetric on purpose, because not every skill needs the same depth of every pillar.

  1. Is the trigger right? Would I, the operator, be able to predict when to invoke it, or does it genuinely need the model’s judgment?
  2. Is SKILL.md small? Say, under a hundred lines. If not, what can I move to references/?
  3. Does the procedure have at least one leading word the agent will echo back at me?
  4. Does every paragraph in SKILL.md survive a deletion test?

If any answer is no, the skill isn’t ready.

The honest truth is that most “skill hell” is the slow accumulation of small design mistakes. Bloated SKILL.md files from past authors. No-ops no one wanted to remove. A skill that solves the same problem with half the tokens and a clearer trigger will outperform a “comprehensive” one every time, because the model has less to ignore.

Engineer your skills the way you’d engineer a small library: a tight surface, lazy internals, and the discipline to actually delete. That’s the whole job.


What’s the worst skill you’ve had to rewrite? Mine involved a 700-line SKILL.md and an agent that summarized the first paragraph and wandered off. Reach me on Twitter/X, I want to hear the worst one.

Did this resonate?