Agent Engineering
Module 05 · Steering/Lesson 5.4/3 min

Writing a skill

A procedure the agent loads only when it is relevant — the unit of reusable expertise.

A skill is a teachable capability packaged as a unit: instructions, and often scripts or templates, that stay out of context until a pointer activates them. Harnesses implement this differently — a skills directory, custom commands, prompt files, reusable rules — but the shape is the same: a named procedure, loaded on demand.

When a procedure should be a skill

  • It is more than three steps.
  • You do it more than occasionally.
  • Getting it wrong is annoying to unpick.
  • It applies to some sessions, not most — that is the test that separates it from a brief line.

Typical candidates: adding a database migration, creating a new API endpoint end to end, the release checklist, adding a feature flag, onboarding a new integration, upgrading a framework major version.

The shape

.agents/skills/add-migration.md
# Add a database migration

Use when: adding, altering, or removing any column, table, or index.

## Rules
- Never edit an applied migration. Always add a new one.
- Two-phase for destructive changes: deploy the code that stops using the
  column, then a later migration drops it. Never in one release.
- Every migration needs a tested down-migration.

## Steps
1. npm run db:new <name>            # creates a timestamped file
2. Write up and down. Both must be idempotent.
3. npm run db:migrate               # apply locally
4. npm run db:rollback && npm run db:migrate   # prove down works
5. Update src/db/schema.ts to match. Do not hand-edit generated types.
6. npm run check

## Done when
Check passes, rollback was exercised, and the diff contains exactly one
new file in db/migrations/ plus the schema.ts update.

Note what makes this work: an explicit use when, imperative steps with real commands, and a definition of done stated as something observable in the diff.

Activate it with a pointer

AGENTS.md
## Skills
Before any schema change, read and follow .agents/skills/add-migration.md.
Before cutting a release, read and follow .agents/skills/release.md.

Two lines always loaded; the procedures themselves only when relevant. That is progressive disclosure applied to know-how rather than to documentation.

Write skills from failures

The best source material is a session that went wrong. When you have just spent forty minutes unpicking a botched migration, that is the moment to write the skill — while you can still remember the specific step that was missed.

Watch out

Skills rot faster than briefs because they encode procedures, and procedures change with tooling. Put a command in every skill that would fail visibly if the skill were stale — a script name, a generated path — so drift surfaces as an error rather than as silently wrong work.

Try it

Write one skill for the most error-prone procedure in your project. Then run it: start a fresh session, give it a task that should trigger the skill, and see whether the agent follows it without being told. If not, your pointer is too vague.

Takeaways

  • A skill is a named, on-demand procedure — for work that applies to some sessions, not most.
  • Give every skill a "use when", real commands, and an observable definition of done.
  • Write skills straight after the session that went wrong.
How do you decide between a brief line and a skill?

Frequency of relevance. If it applies to most sessions it belongs in the always-loaded brief; if it applies to a specific kind of task it belongs in a skill with a pointer, so the other sessions do not pay for it.

A course by Pieter Zandbergen