How-to · Authoring

How to Write an Agent Skill

A practical guide to authoring a skill that actually fires: choosing a triggerable scope, writing the description as a trigger rather than a summary, keeping the body short with the depth in reference files, and testing whether it changed the output.

By Michał Jaskólski Updated 9 min read
  1. 01 Clean Code clean-code Writing readable, maintainable code
  2. 02 Clean Architecture clean-architecture Building maintainable, testable software architectures
  3. 03 Refactoring refactoring-patterns Improving code design through systematic refactoring

Anyone who works with a coding agent for a month notices the same thing: it is competent at everything and disciplined at nothing. Ask it to review a pull request and you get plausible remarks; ask it to price a product and you get a reasonable-sounding range. Nothing is wrong, exactly — but a practitioner can tell no method was applied, because none was. A skill fixes that: a folder with a SKILL.md the agent loads when it recognises the situation, telling it what to do.

Writing one is easy. Writing one that fires when it should, and changes the output when it does, comes down to the handful of decisions below. For the anatomy of the file read what goes in a SKILL.md; for portability, the agent skills standard; to run someone else’s skills, how to install Claude Code skills.

What makes a skill narrow enough to actually fire?

Start with a moment, not a topic. An agent picks skills by matching the situation it is in, so the first question is not “what do I know worth writing down” but “what moment do I want to change behaviour in, and would I recognise it in a transcript?”

Topics fail this test. A skill called “software engineering best practices” competes with every request that touches code; it will either lose to more specific skills or win constantly and drown out the ones that should have fired. Moments pass it: I’m reviewing a pull request for readability. We need to decide whether business logic can import the ORM.

That is why our library has three code-quality skills where a lazier design would have one. Clean Code fires at the level of names, function size and error handling; Refactoring when you have a named smell and need a named transformation; Clean Architecture when the question is which way a dependency points. Merged, they would be one skill worse at all three jobs.

The cheap test, worth running before you write a word of the body: three sentences a real user might type that should load your skill, in their words, and three that plausibly might but should not. If you cannot fill either list the scope is wrong. Keep both; they become your test suite. Then check there is something to apply — the rule we use when turning a book into a skill is that the source must contain a procedure someone else could follow.

How do you write a skill description that actually triggers?

Here is the mechanic that determines everything: when the agent decides which skills are relevant, it sees the name and description of each installed skill and nothing else. The body becomes visible only after the description has won. So the description is not documentation — it is the matching surface, and where most skills quietly fail. The failure looks like this:

Clean Code principles for writing better, more maintainable software.

A fine sentence that matches almost nothing, because it describes the skill’s subject instead of the user’s situation. Nobody types “I would like clean code principles.” They type “this function is too long.” Compare the description that actually ships with our clean-code skill:

Write readable, maintainable code through disciplined naming, small functions, and clean error handling. Use when the user mentions “clean up this code”, “this function is too long”, “code smells”, “naming conventions”, “boy scout rule”, “single responsibility”, or “unit test quality”. Also trigger when reviewing a pull request for readability, untangling a messy function, debating comment styles, or improving error-handling patterns. Covers SRP, comment discipline, formatting, and unit testing. For refactoring techniques, see refactoring-patterns. For architecture and dependency rules, see clean-architecture.

Five parts, each doing a job. A capability, stated as an action. Quoted trigger phrases in the user’s register — the words a person actually types, informal ones included, not conference-talk vocabulary. Situations without vocabulary: “reviewing a pull request for readability” catches someone who describes a task and uses none of your keywords. A scope claim. And routing — hand-offs to neighbours, which stops three overlapping skills firing on one request.

The description is not a summary of your skill. It is the only thing the agent reads before deciding whether your skill exists.

Write it before the body, because naming the trigger moments forces the scope decision you may still be avoiding. Keep it third-person and inside the format’s 1024-character limit — a description that hits the ceiling is usually one skill pretending to be two.

What should a skill say — instructions, not a summary

The second most common failure is a body that summarises. A summary tells the agent what a topic is about — and the model has read more about clean code than you have.

So interrogate every paragraph with one question: what will the agent do differently having read this? If the honest answer is “be slightly better informed,” cut it. What survives looks like this:

  • Decision rules with a threshold. “A function that takes a boolean flag is really two functions — split it” is actionable. “Functions should be focused” is not.
  • An order of operations. Our legacy-code skill fixes a sequence: find the change points, find the test points, break dependencies, write characterization tests, then change the code. The value is in the ordering, which a summary flattens.
  • A rubric that forces a verdict. Every book skill in our library scores the work 0–10 against a diagnostic table, turning “here are some thoughts” into a number, the failed rows, and a fix for each.
  • A mistakes table — the mistake, why it fails, the fix. The highest-density format we know for behaviour change, because it pre-empts the wrong thing the model would do.

What goes: history, biography, case studies, throat-clearing. That is the book’s job.

Prompt

Use the clean-code skill to score our user-management module 0-10, flagging every name that hides intent, every function doing more than one thing, and every function that both mutates state and returns a value, then list the top ten fixes in priority order

Clean Code

How long should a SKILL.md be, and where does the rest go?

Short. Every word of a loaded skill competes with the user’s actual problem in the context window, and a skill that costs more attention than it returns is a net loss even when its advice is good. A useful target is a couple of hundred lines — our clean-code skill is about 220 — with the depth in reference files the agent reads only when it needs them. That skill has six of them, each 1,500 to 3,000 words. Most sessions load none.

The part people get wrong is the pointer. A list of reference files at the bottom is a table of contents, and the agent treats it accordingly: it ignores the list or reads everything. What works is an inline pointer at the point of need with a when clause — “See references/error-handling.md when the code swallows exceptions in bare catch blocks or returns null on failure.” That is an instruction with a condition attached, and it fires the same way the skill does. The folder is allowed to be large; the file loaded every time is not.

What do examples and counter-examples do that rules cannot?

Rules are unambiguous in the middle and vague at the edges, which is exactly where the agent operates. Examples fix the edges: a before-and-after pair, or a two-column table — instead of this, write this. Two lines of real code settle an argument that three paragraphs of principle leave open.

The counter-example is the half most authors skip, and the more important one. The failure you are writing against is never gibberish; it is the plausible, competent-looking output the model produces by default. “Do not write vague code review comments” is unenforceable, because the model does not believe its comments are vague. Showing the exact comment you do not want, beside the one you do, is enforceable.

Then ship example prompts. They double as the test cases in the next section.

Where should a skill say it does not apply?

In three places. In the description, as routing — the “for X, see Y” clauses are not politeness, they are how a library stays coherent instead of becoming a bidding war where every skill claims every request. In the body, as an explicit boundary: a sentence naming the adjacent situation and handing it off saves the agent from applying a framework to a problem it was not built for.

And wherever the method is genuinely contested. Clean Code and A Philosophy of Software Design disagree, in print, about how small a function should be. A skill that flattens that into house doctrine makes the agent confidently wrong in front of someone who knows the literature. Naming the disagreement and when each side applies costs nothing, and is the difference between a framework and a sales pitch.

How do you test whether a skill is working?

Two questions, and conflating them is why authors end up tinkering with a description that was never the problem.

Does it fire? Open a fresh session and type the sentence a real user would type — not “use the pricing skill,” which proves only that it is installed. Your agent will usually name the skill it picked; for certainty, drop a tracer into it (“begin your reply with the word ANCHOR”). Run the three positive sentences, then the three negatives — a skill that fires on everything is a worse neighbour than one that never fires, and only the negatives reveal it.

Did it change the output? Run the same task twice — once with the skill renamed so it cannot load, once with it installed — and diff. If the answers say substantially the same thing, the skill is decoration, and the fix is in the body rather than the description: you wrote a summary. Use a fresh subagent for each run; a context that has already seen your skill is not a control. The Superpowers project publishes a good write-up of testing skills with subagents worth reading whichever library you write for. Then keep testing after you ship: every time your agent does the wrong thing in a real session, the rule that would have prevented it is the next line of your skill.

Frequently asked questions

How long should a skill description be?

Two to four sentences: the capability, the quoted phrases, the situations that carry no keywords, and the hand-offs. The format allows 1024 characters and a good one rarely needs them all — pressed against the ceiling usually means you are describing two skills.

Can one skill reference or invoke another?

It can point at one, and it should: a routing clause in the description plus a hand-off in the body. What a plain skill does not do is orchestrate several others — for that, write a skill whose entire content is the sequence, which is what our twelve guided journeys are. If you need isolated context or separate tool permissions, you are describing a subagent; see skills vs subagents vs prompts.

Should I write a skill, or just a better prompt?

Write the prompt first. If a paragraph pasted into a conversation gets the output you want, a skill is premature. The case begins when you have pasted it a fourth time, when you want it applied without remembering to invoke it, or when teammates need the behaviour without knowing the incantation. A one-off instruction is a prompt; a rule that applies whenever a recognisable situation appears is a skill.

Two of my skills keep firing on the same request. How do I fix it?

Almost always a description problem with a scope problem underneath. Write out the request that triggered both, decide which skill you wanted, then add the distinguishing situation to that one’s description and a hand-off in both. If you cannot decide, the two cover one moment and should be merged. Overlap in subject matter is fine; overlap in trigger situation is not.

My skill never fires. What is wrong?

Check the description first, against real sentences rather than your intentions. The usual causes: it summarises the topic instead of naming the situation, it uses your vocabulary rather than the user’s, or the scope is so broad a specific skill wins every time. Also confirm the frontmatter parses — a malformed name or description silently excludes the skill. If it loads when you name it explicitly but never on its own, the body is fine and the description is not.

Start with the description

Take the order, if nothing else: name the moment, write the description as a trigger, write a body that changes behaviour, move the depth out of the way, then test whether it fires and whether it mattered. Authors who work that way ship something that works on the first or second attempt; authors who write the body first produce a very good document no agent ever loads.

Everything in our library is readable on GitHub, so the fastest calibration is to open a skill whose subject you know well and ask whether its description would have caught your last three requests about it. And if your team would rather have this built than build it, that is what we do.

Work with us

We build the skills you already use. Now we’ll build yours.

Custom skills · Subagents · MCP integrations — shipped to production, not demoed.

Sprints from $3K · shipped to production, or you don’t pay the final milestone.