Skip to content

Add skills: instructions the model loads when a task needs them - #42

Merged
igalshilman merged 1 commit into
mainfrom
skills-api
Oct 9, 2026
Merged

igalshilman merged 1 commit into
mainfrom
skills-api

Conversation

@igalshilman

Copy link
Copy Markdown
Collaborator

Adds skills to the SDK: instructions for one kind of task that the model loads by name when a task needs them. The API doesn't depend on any particular store. The application supplies a SkillSource, and lesson 19 backs one with a folder of SKILL.md files in Anthropic's Agent Skills format.

const writer = agent({model, instructions: "...", skills: source});
// source: {list, load, read?, retry?}, plain async functions

Behavior

  • Every call to list, load and read is journaled, like an asyncTool. A source can do plain I/O, and a replay never calls it again.
  • The run lists skills once at its start and appends each name and description after the agent's instructions. That list doesn't change during the run, so the cached prompt prefix holds.
  • The model gets load_skill(name), and read_skill_file(name, path) when the source has read.
    • Absolute paths and .. are rejected before the source sees them.
    • An unknown skill or a missing file comes back as a tool error.
    • Long skill text and files use the existing toolResults previews.
  • A listed skill can carry an opaque location, such as a folder or a URL pinned to a commit. It's journaled with the list and passed back to load and read, so a source over something that changes pins it for the run. The model never sees it.
  • Skills belong to the run, so they survive a handoff.
  • Validation: names use lowercase letters, digits and hyphens, up to 64 characters, and must be unique. A name can't clash with a run tool. Each skill needs a description, of any length; published skills, Anthropic's own among them, go past the format's 1,024 characters.
  • skills([...]) builds a source from skills defined in code.
  • Skill scripts are out of scope: the SDK provides no shell to run them.

Lesson 19: folderSkills reads packages/examples/skills/, which holds two samples: release-notes with a template.md, and incident-summary. A small frontmatter parser handles key: value lines and YAML > and | blocks.

Docs:

  • both READMEs
  • the restate-agents skill: its lesson table, a "find the right tool" row and a Skills section in agent-basics.md
  • a "Skill" entry in the CONTEXT.md glossary

Tests

  • skills.test.ts covers:
    • loading and reading, with replay not calling the source again
    • instructions and tools unchanged across steps
    • errors: an unknown skill, a path outside the skill, a missing file
    • a source without read, and an empty source
    • invalid names, and clashes with run tools
    • location reaching load and read
  • The example integration tests run lesson 19 against the real files.
  • Build and lint pass. 207 unit tests and 63 integration tests pass.

🤖 Generated with Claude Code

agent({skills}) takes a SkillSource: plain async list, load and an
optional read, each run journaled. The run lists the skills once and adds
each name and description after the instructions, so the cached prefix
stays stable. It gives the model load_skill, and read_skill_file when the
source can read files. A listed skill's optional location is journaled
with the list and passed back to load and read, so a source over
something that changes pins it per run. skills([...]) builds a source
from skills defined in code.

Lesson 19 reads a folder of SKILL.md files. Skill scripts are out of
scope.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@igalshilman
igalshilman merged commit 320c483 into main Oct 9, 2026
3 checks passed
@igalshilman
igalshilman deleted the skills-api branch October 9, 2026 08:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant