Skip to content
echogeco
Skills, hooks and MCP · Skills and hooks

Skills as packaged procedures

Move a procedure out of the system prompt into a skill, write the description that decides when it loads, and cost the move per call and per day.

Lesson · 8 min · 50 of 77
On this page

On the ladder from five eras, one ladder, this module is the step from rung 1 to rung 2, where procedures leave the system prompt and become files, plus hooks, the first piece of rung 4 most teams adopt. A skill is a procedure the model loads only when a task needs it: a folder holding a short description, a body of instructions, and optionally scripts. The description is paid on every call and the body only on the calls that use it. That split is the whole mechanism, and its arithmetic decides which procedures should move.

Module 6 moves procedures into files and puts the first code at fixed points in the loop. The model still owns the loop.
100%SVG (opens in a new tab)

Pinch to zoom · drag to pan

The prompt that carried every procedure

The mistake first. An internal engineering assistant answers 4,000 calls a day. Its system prompt started as 1,500 tokens of role, rules and output format, and over a quarter six procedures were pasted in, one per request from a different team:

ProcedureTokensShare of calls that need it
Release notes9002%
Incident write-up1,0001%
Dependency upgrade7003%
Migration review8002%
On-call handover5001%
Security checklist6001%

The prompt is now 6,000 tokens, and nine calls in ten need none of the 4,500 tokens of procedure. Weighted by use, the average call needs 0.02 × 900 + 0.01 × 1,000 + 0.03 × 700 + 0.02 × 800 + 0.01 × 500 + 0.01 × 600 = 76 tokens of procedure while carrying 4,500: 18M tokens a day read so that 0.3M get used.

Two other costs come with the tokens. A rule placed after the procedures sits in the middle of the context, where tokens and the context window showed instructions are read worst. And the prompt is a file six teams edit, so an edit to the incident procedure is an edit to every task, and the eval has to cover all of them each time.

What a skill is

Anthropic's "Agent Skills" (opens in a new tab) reference gives the shape this lesson generalises from: a folder with a SKILL.md file, whose frontmatter carries a name and a description and whose body carries the instructions, beside any reference files and scripts the body points to. Loading happens in three levels. The name and description are in context on every call; the page budgets about a hundred tokens per skill for them, and a one-sentence description is often half that. The body enters context only when the model decides the description matches. A bundled script runs without its code entering context; only its output does.

---
name: release-notes
description: Draft release notes for a tagged release from the pull requests merged
  since the previous tag. Use when asked for release notes, a changelog or "what
  shipped in". Not for incident summaries; use incident-writeup.
---
1. Run scripts/merged_prs.py <previous-tag> <tag> to list merged PRs with labels.
2. Group by label: feature, fix. Drop internal and chore.
3. One line per PR, present tense, user-facing wording, PR number at the end.
4. Lead with breaking changes under their own heading, or write "None".

The mechanism is generic: in your own loop it is a system-prompt section of names and descriptions plus a load_skill(name) tool whose result is the body.

The arithmetic, per call and per day

Take release notes alone. Before, 900 tokens are on every call. After, a 50-token description is on every call and the 900-token body on the 2% that load it:

saving per call = 900 − 50 − 0.02 × 900 ≈ 832 tokens
per day         = 832 × 4,000 ≈ 3.3M tokens, 3.3 × P_in

Move all six and the formula covers the whole prompt: the old prompt, minus the prompt that stays with its descriptions, minus each body weighted by how often it loads.

saving per call = 6,000 − (1,500 + 6 × 50) − 76 ≈ 4,120 tokens
per day         = 4,120 × 4,000 ≈ 16.5M tokens, 16.5 × P_in
Nine calls in ten carry 1,800 tokens of instructions instead of 6,000. The tenth pays for one body, not six.
100%SVG (opens in a new tab)

Pinch to zoom · drag to pan

The formula leaves out the term that sets the limit. Loading a body is a tool call, so the next send re-reads the context so far. On the 400 calls a day that load a body, at about 3,000 tokens of prompt and request, that is 1.2M tokens, and the net saving is about 15.3M. Those calls also gain about a second and a half, a second to the first token and half a second to decode the load call, at the course's latency figures (about 1 s and 50 tokens/s, from the four numbers). Since 10% of calls is more than the 5% above p95, the p95 can rise by up to that much; latency budgets and streaming says whether the budget can take it.

The round trip gives the break-even. A procedure of B tokens with a description of d, loaded on a share f of calls at a context of R tokens, saves B − d on every call and costs f × (B + R). It belongs in a skill while

f < (B − d) ÷ (B + R)        release notes: (900 − 50) ÷ (900 + 3,000) ≈ 22%

At these sizes, a procedure needed on more than about a fifth of calls is cheaper left in the prompt.

Then caching. A 6,000-token prompt that never changes should already be a cache hit, priced at C_r × P_in by prompt caching. If it was, the saving above shrinks by that factor. On a cached prompt the case for skills rests on the other two costs: a request no longer buried behind other teams' procedures, and an edit to the incident procedure that cannot regress release notes, because release-notes calls never load it.

The description decides when it loads

A skill fails in two directions. A miss: the description did not match, and the model wrote release notes from general knowledge with the internal PRs left in. A false load: a body and a round trip paid for nothing. Both have rates, measured the way writing tool descriptions the model can use measures a wrong-tool rate: 50 tasks in the users' words, 20 that need one of the six procedures and 30 that need none, each labelled with the skill that should load.

The first six descriptions were titles: "Release notes helper", "Incident write-up". They missed 7 of the 20 — "what shipped in 4.2?" never matched "release notes" — and loaded a body on 5 of the 30. The rewrite gave each description what a tool description carries: the users' phrasings, what the procedure produces, and a when-not naming the neighbour. Misses fell to 1 and false loads to 1. The description is a classifier, so it gets a classifier's treatment: a labelled set, two error rates, a rerun after every edit.

What stays out of a skill

A rule every call needs, such as the output format, stays in the system prompt; as a skill it would load every time and pay a round trip each time. A rule that must hold every time, such as "never delete files outside the build directory", is not an instruction at all: a body the model may not load, and may not follow, is the wrong place for it, and hooks is the right one. Facts that change belong in retrieval or a tool. And a skill from a source you have not read is code and instructions you are about to run with the agent's permissions, the injection path through a different door; review it the way you would a dependency.

Scripts are the part most often skipped. Without step 1's script the model writes its own git log pipeline each run and sometimes gets the tag range wrong; the script returns the same list every time at no cost in context. The model still decides whether to run it, which is the limit of what a skill can promise.

In an interview

The interviewer is checking whether you treat the system prompt as a budget with a usage profile, not a document that grows. Say "descriptions on every call, bodies on the calls that need them", then the arithmetic for one procedure, the round trip the naive formula leaves out, and the break-even share. Name the description as a classifier with a miss rate and a false-load rate.

The mistake that loses points is moving everything into skills. A procedure used on half the calls costs more as a skill, a formatting rule costs a round trip on every call, and a rule that must always hold is no safer in a skill than in the prompt. The second mistake is quoting the saving at P_in when the prompt was already cached.

Check yourself

1. A 2,400-token code-review checklist is used on 45% of an assistant's calls; the context at load time is about 3,000 tokens. Skill or system prompt?

Break-even is (2,400 − 50) ÷ (2,400 + 3,000) ≈ 44%. At 45% it is a wash on tokens, and the skill adds a round trip to almost half the calls, which moves p95. Keep it in the prompt. If it splits into a 600-token core every review needs and language-specific sections each used on 10% of calls, keep the core and move the sections.

2. A team moves a 1,200-token procedure used on 1% of 10,000 daily calls into a skill, with R about 3,000. The prompt was already a cache hit. What did they save?

Uncached, (1,200 − 50 − 0.01 × 4,200) × 10,000 ≈ 11M tokens a day at P_in. Cached, the always-paid part was costing C_r × P_in, so it shrinks by C_r, while the 100 loads a day still pay their round trips. The money is small; the reason to ship it is that the next edit to this procedure touches 1% of calls instead of all of them.

3. A skill misses on 6 of the 20 tasks that need it, and the owner proposes adding "ALWAYS use this skill for release work" to the system prompt. Accept?

No. That line is paid on every call and still asks the model to classify. Rewrite the description with the phrasings the six misses used, add a when-not naming the neighbouring skill, and rerun the 50 tasks. If a task class must always run the procedure, route it in code before the model is called, and stop treating it as a judgment.