Loading only what the skill needs
The previous lesson ended with a release skill that ran from a new session in a clean clone. Suppose the team then had a release go wrong, and someone added a section to the skill on how to undo one. The section is useful, and it is needed in one release out of many. This lesson measures what that section costs on every other release, moves it into a separate file the skill points to, and measures again.
The measuring is done by a short Python script that only reads files, and
the course checks its output on every build. It is in the course repository
at site/examples/customizing-agents/progressive-disclosure/, next to two
versions of the release skill. Run the commands in this lesson from that
directory. In the cd line, replace <course-repo> with the path to your
copy of the course repository.
cd <course-repo>/site/examples/customizing-agents/progressive-disclosureWhat the agent reads, and when
Section titled “What the agent reads, and when”An agent that supports the open skill format doesn’t read a whole skill at
once. It reads it in stages, and the specification names three
[1]. At startup the agent loads the name and
description of every skill it can see. When a task matches a
description, it loads that skill’s whole SKILL.md. Other files in the
skill’s directory are loaded only when a step in SKILL.md sends the agent
to them. Anthropic’s overview of skills describes the same three stages for
Claude [2]. Designing a skill for this is
called progressive disclosure: each stage holds only what the agent
needs at that point [3].
Each stage has its own cost. The name and description are in context on every turn of every session, whether the skill runs or not. Both documents put that stage at about 100 tokens per skill. The specification recommends keeping the body under 5000 tokens, and Anthropic’s overview gives the same figure for the body [1] [2]. In Claude Code, the body stays in the conversation on the turns after the skill runs [4]. As How a language model works showed, the model reads everything so far each time it predicts a token, so a body that’s still in context is read again on each of those turns. A file the agent never opens doesn’t cost any tokens [2].
When does the agent load it?
Section titled “When does the agent load it?”A release skill has a SKILL.md file with front matter and a body, and a rollback.md file next to it that one step of the body points to. An agent that follows the open skill format loads the parts of a skill at different times.
Which part does the agent need to decide whether to use the skill, which part to run it, and which part only in one case?
Measure the skill as it stands
Section titled “Measure the skill as it stands”The directory grown/release/ holds the release skill from the previous
lesson with the new section added. It is called “When a release goes wrong”
and has five numbered steps. A release that nobody has pushed yet is undone
with git tag -d and a reset. For a release that was pushed, the agent
leaves the remote tag alone and makes a new fix release. The section is
between the release steps and “Done when”. The agent reads it on every
release.
The script measure.py prints one line per stage. For the first stage it
counts the name and description lines of the front matter. The second
stage is the whole SKILL.md, and each other Markdown file in the
directory gets a line of its own. Then it prints two totals, one for a run
that reads only SKILL.md and one for a run that reads every file.
The counts are estimates. The script uses the same rule as the counter in What the model can see, about four characters per token. A word of up to six characters counts as one token and a longer word as one token per four characters. Each punctuation mark counts as a token of its own. Markdown has a lot of punctuation, and the rule gives a higher count for a skill than for plain prose of the same length. The exact count for a model comes from the vendor’s own tokenizer. The rule is the same for both versions of the skill, so the difference between them is what matters here.
Before you run it, guess the second line. The file is about two pages of Markdown, and the counter from the concepts lesson gave 115 tokens for half a page of notes.
Measure the skill as it stands
Section titled “Measure the skill as it stands”Run this, and compare with the output below.
python3 measure.py grown/releasegrown/release always loaded, name and description: 39 when the skill runs, SKILL.md: 1256 when a step reads it: no other files total, SKILL.md read: 1295 total, every file read: 1295
Output verified in CI from site/examples/customizing-agents/progressive-disclosure/before.py.
The first line is small, and it should be. A description of two short
sentences is far below the figure of about 100 tokens. The second line is
the one to read. A release loads all 1256 tokens of SKILL.md, and the
rollback steps are part of them even when the release goes right.
Move the rollback into a reference file
Section titled “Move the rollback into a reference file”The fix is to keep the common path in SKILL.md and move the rare case
into its own file. The specification suggests keeping SKILL.md short and
moving detailed material into separate files, referenced by a relative
path and one level deep from SKILL.md [1]. Anthropic’s
guide explains the one level. The agent may read only part of a file it
reaches through another reference file [5].
Make a copy of the grown skill to work on. The first line deletes
~/skill-copy, so the commands also work on a second attempt. The copy’s
directory is named release, because a skill’s directory name must equal
its name.
rm -rf ~/skill-copymkdir ~/skill-copycp -R grown/release ~/skill-copy/releaseIn ~/skill-copy/release/, create rollback.md with the heading and the
opening line below. Move the text of the “When a release goes wrong”
section into it, from its first sentence to the end of step 5. Change “Use
this section only when” to “Use these steps only when”, because the text
is now a file of its own.
# Undo a release of the notes package
The release skill sends you here. Use these steps only when the userasks you to undo a release, or when a check after the tag shows that therelease is wrong. Undo nothing else.
1. Run `git describe --tags`, `git log --format='%h %s' -n 3` and ...Then leave the heading in SKILL.md and replace the text under it with a
pointer that says when to read the file:
## When a release goes wrong
If the user asks you to undo a release, or a check after the tag showsthat the release is wrong, read `rollback.md` in this skill's directoryand follow it. Don't undo anything before you have read it.The pointer names the situation, and that is what makes it work. A line
that says only “see rollback.md” gives the agent no way to tell whether
this run needs the file, so it may read it every time, or never.
Anthropic’s guide says to watch for this when you test a skill: an agent
that never opens a bundled file may be missing a clear enough signal in
SKILL.md [5]. The agent reads the pointer only
in a run where the skill has loaded. An undo asked for in a new session
loads the skill only if its description names that request.
The course repository has the result in split/release/. Measure it, and
then measure your copy with python3 measure.py ~/skill-copy/release. If
you moved the text as shown, your copy gives the same numbers. Its first
line is your path.
Which line drops?
Section titled “Which line drops?”A release skill had a rollback section in its SKILL.md. The section was moved into a rollback.md file in the same directory, and a three-line pointer that says when to read it was left in its place. A script prints an estimated token count for the name and description, for SKILL.md and for each other file, then the total when only SKILL.md is read and the total when every file is read.
Before you run the script on the split skill, predict which line drops compared with the grown skill.
Which file lost the undo steps, and which parts of the skill did the move leave as they were?
Measure the split skill
Section titled “Measure the split skill”Run this, and compare with the output below.
python3 measure.py split/releasesplit/release always loaded, name and description: 39 when the skill runs, SKILL.md: 813 when a step reads it, rollback.md: 516 total, SKILL.md read: 852 total, every file read: 1368
Output verified in CI from site/examples/customizing-agents/progressive-disclosure/after.py.
The description didn’t change, so the first line is still 39. A release that goes right now loads 852 tokens where it loaded 1295. A rollback reads both files and loads 1368, a little more than before, because the agent reads the pointer and the new file’s heading as well as the steps. The split makes the common run cheaper, and the rare run pays a small amount extra.
Where does the table go?
Section titled “Where does the table go?”A deployment skill has a 200-line table that explains each error code the deploy tool can print. The agent needs the table only when a deploy fails, which is about one run in twenty.
Where should the error-code table go?
Which place costs nothing on the nineteen runs that don't need the table, and is still found on the run that does?
What moves out of the body?
Section titled “What moves out of the body?”A team reviews a release skill whose SKILL.md body has grown to twice its first size. They decide which parts to move into files next to SKILL.md that the body points to, and which parts stay in the body.
Which two parts should move into files the body points to?
For each part, ask how many release runs need it.
Which pointer line works?
Section titled “Which pointer line works?”A release skill's undo steps were moved from SKILL.md into a file named rollback.md next to it, and the author must write the line in SKILL.md that points to the file.
Which line should SKILL.md have in place of the moved steps?
Which line lets the agent decide, on a given run, whether it needs the file?
What does each session load?
Section titled “What does each session load?”A release skill has a two-sentence description that names requests to release, bump the version or tag, a SKILL.md body with the release steps and a pointer line, and a rollback.md file the pointer names. Each row is a kind of session, and the options say which parts of the skill it loads.
Match each session to what it loads of the release skill.
Which part is loaded for every skill, which when the skill runs, and which only when a step sends the agent there?
Exercise
If you followed the walkthrough, your ~/skill-copy/release/ is the
exercise. Go to the result below. Otherwise make the copy
with the commands in the last section. Measure it with measure.py, move
the “When a release goes wrong” section into rollback.md with a pointer
that says when to read it, and measure again. The script only reads files,
and you change only the copy. Afterwards you can check any skill you write
for a rare case that every run pays for.
For the stretch, these commands put your split skill into the clean clone from the last lesson and commit it, then make one change for the release to list. The skill edits files and makes commits and tags, so run it only in that clone, which has no remote.
rm -rf ~/notes-clean/.claude/skills/releasecp -R ~/skill-copy/release ~/notes-clean/.claude/skills/releasecd ~/notes-cleangit add .claude/skills/releasegit commit -q -m "Split the release skill"echo 'Run `python3 notes.py list` to see your notes.' >> README.mdgit commit -q -a -m "Document the list command"A good result: the first line didn’t change, the second dropped from 1256
to 813 if you moved the text as shown, and rollback.md appears as its own
line. The pointer in SKILL.md names the requests that need the file.
Read the body that is left. Is there another part that only some runs
need?
Stretch: After the commands above, type /release 0.4.1 in a new session in ~/notes-clean, and check in the transcript whether the agent opened rollback.md.
Recap
- An agent loads a skill in stages: the name and description of every
skill at startup, the whole
SKILL.mdwhen a task matches it, and other files only when a step points to them [1] [2]. - The description is paid for on every turn of every session, and the body on every run of the skill. In Claude Code the body stays in the conversation for the turns after it runs [4].
- Keep the common path in
SKILL.md. Move a rare case or a long reference into a file one level fromSKILL.md, and leave a pointer that names when to read it [5]. - Measure the skill with the same rule before and after a change. An estimate is enough to compare two versions. The exact count for a model comes from the vendor’s tokenizer.
- Skills grow a little at a time, so measure after each addition.
You can now
- Structures a skill so the agent loads only what it needs
References
Section titled “References”- Anthropic. Agent Skills specification. agentskills.io. Reference.
Agent Skills spec - Anthropic. Agent Skills. Claude Platform documentation. Reference.
Claude docs agent-skills-overview - Addy Osmani, Ivar Soares Urdalen, Leo Simons. Agent skills: skills versus tools, the spec, progressive disclosure. Agent Engineer Course. Course.
AEC-17 - Anthropic. Extend Claude with skills. Claude Code documentation. Reference.
Claude Code skills - Anthropic. Skill authoring best practices. Claude Platform documentation. Reference.
Claude docs best-practices