The Skills API — Teaching Claude Who You Are
Skills are the mechanism for giving Claude reusable, versioned procedural knowledge without loading everything into context on every call — and the local and Managed Agents implementations differ in ways that matter.
The standard approach to giving an agent procedural knowledge is to put it in the system prompt. This works until your system prompt is 8,000 tokens long, the agent has seventeen different procedures to remember, and half of them are irrelevant to any given task. Context is finite and expensive. Loading everything upfront is a blunt instrument.
Skills are the alternative. They give Claude access to a library of procedures without loading all of them on every call. The agent knows the skills exist. It loads the full content of a skill only when that skill is actually relevant to the work at hand. This is progressive disclosure applied to procedural knowledge.
How Skills Work in Claude Code
In Claude Code, skills are directories under ~/.claude/skills/. Each skill is a folder containing a SKILL.md file at its root — the folder name is the skill name, and supporting files (scripts, templates) can live alongside the SKILL.md.
~/.claude/skills/
deploy-to-prod/SKILL.md
review-pr/SKILL.md
morning-brief/SKILL.md
run-trading-retro/SKILL.md
When Claude Code starts a session, it loads a short summary of each skill — the skill name and a brief description, roughly 50-100 tokens per skill. This is cheap enough that 40+ skills can be indexed at session start without meaningful context cost.
When the agent determines a skill is relevant to the current task, it loads the full skill content. A detailed deployment procedure might be 800-1,200 tokens. That cost is only paid when the skill is actually invoked.
The mechanism is not magic — it is token-efficient architecture. Claude reads the description of available skills and uses them as a lookup mechanism, fetching full content only when needed.
The Skill File Format
The SKILL.md (here, ~/.claude/skills/deploy-to-prod/SKILL.md) opens with YAML frontmatter — name and description are the required registration fields — followed by the full procedure:
---
name: deploy-to-prod
description: Deploy a service to the production server via SSH
built_from: memory://session/2026-03-28-deploy-retro
iteration: 3
---
# Deploy to Production Server
Use this skill when deploying any backend service or container to prod-host.
## Prerequisites
- SSH access to prod-host (VPN required)
- Service has a Docker image or source directory
- .env variables confirmed on the target
## Procedure
1. SSH to the production server:
```bash
ssh prod-host
```
2. Pull latest code:
```bash
cd ~/dev/<repo> && git pull
```
3. Rebuild and restart the service:
```bash
export PATH=/opt/homebrew/bin:/usr/local/bin:$PATH
docker compose build <service> && docker compose up -d <service>
```
## Important Notes
- Always export PATH before running docker — non-interactive SSH does not inherit Homebrew
- Verify service is up after restart: docker compose ps
- Check logs: docker compose logs <service> --tail=50
The --- frontmatter block at the top is for provenance tracking. The description field is what loads at session start — it should be one sentence that clearly describes when to invoke this skill.
What Makes a Good Skill
One skill, one procedure. A skill that says "deploy to the production server or, if that fails, deploy to the backup host instead" is not one skill — it is two procedures with a conditional wrapper. Split it. Conditional branches are usually separate procedures, and separate procedures deserve separate skills.
Invocation trigger in the description. The description that loads at session start should answer the question: when should Claude invoke this? "Use this skill when deploying any backend service to the production server" is actionable. "Production server deployment" is not.
Observed behavior, not assumed. The best skills are built from real execution retros, not written from memory about how you think a process works. Hollow skills — written speculatively — fail silently on edge cases. If you are writing a skill that has never been executed, mark it and validate it before dispatching it from an orchestrator.
Minimal scope. A skill that covers deployment, rollback, monitoring setup, and post-deploy verification is doing too much. Scope each skill to the smallest coherent procedure. Users combine skills; they cannot split them.
Skills in the Managed Agents API
In the Managed Agents API, skills are API-managed, versioned resources. The package you upload is the same shape as a local skill — a folder with a SKILL.md at its root — not an inline content string. Skills endpoints use the skills-2025-10-02 beta header (the SDK sets it automatically on client.beta.skills.* calls).
Write the procedure as a SKILL.md first:
---
name: competitor-research
description: Gather publicly available information about a company's product launches, funding, and executive changes
---
# Competitor Research Procedure
## When to Use
Invoke this skill when asked to research a company, competitor, or organization.
## Steps
1. Search for recent news (last 90 days) about the company
2. Check their official blog and press releases
3. Look for funding or acquisition news on Crunchbase
4. Check LinkedIn for recent executive changes
5. Synthesize findings into: Recent Products, Funding/Business, Leadership, Strategic Implications
## Output Format
Return structured markdown with these exact sections.
Then create the skill from the packaged folder and reference it on the agent with a typed entry — {"type": "custom", "skill_id": ..., "version": ...}, not a bare ID string:
import anthropic
client = anthropic.Anthropic()
# Create the skill from the packaged folder (SKILL.md bundle).
# New uploads create versions: POST /v1/skills, then /v1/skills/{id}/versions.
skill = client.beta.skills.create(
display_title="competitor-research",
files=[
(
"competitor-research/SKILL.md",
open("competitor-research/SKILL.md", "rb"),
"text/markdown",
),
],
)
print(f"Skill ID: {skill.id}") # skill_...
# Attach the skill to an agent by typed reference
agent = client.beta.agents.create(
name="intel-agent",
model="claude-sonnet-4-6",
system="You are a competitive intelligence specialist.",
skills=[
{"type": "custom", "skill_id": skill.id, "version": "latest"},
],
)
(Anthropic's pre-built document skills attach the same way with {"type": "anthropic", "skill_id": "xlsx"}.)
The key difference from local skills: Managed Agents skills are reusable across the organization. Any agent can reference a skill by ID and version. Publish a new version once; agents referencing "latest" pick it up everywhere.
When Skills Beat System Prompts
The system prompt wins for:
- Core identity and behavior rules that apply to every task
- Always-relevant context (the user's name, their company, their preferred format)
- Constraints that must be enforced on every response
Skills win for:
- Procedures that apply to specific task types but not all tasks
- Step-by-step workflows that are long enough to add real context cost if always present
- Knowledge that needs to be versioned and updated independently of the agent's identity
- Domain-specific procedures that multiple agents need access to
A useful heuristic: if the content would be relevant to fewer than 40% of the agent's tasks, it probably belongs in a skill rather than the system prompt.
Splitting Skills Correctly
The clearest signal that a skill needs splitting: conditional branching at the top level.
# Deployment Procedure
If deploying to the production server:
- SSH to prod-host
- ...
If deploying to the staging server:
- SSH to 198.51.100.5
- ...
If deploying to Vercel:
- Use vercel deploy
- ...
This is three skills wearing a trench coat. Each target has its own prerequisites, its own steps, its own failure modes. Splitting yields: deploy-to-prod.md, deploy-to-staging.md, deploy-to-vercel.md. The agent can invoke the right one directly rather than loading a branching monolith.
Provenance Discipline
Skills without provenance are a liability. Add a frontmatter block to every skill file that records its lineage:
---
name: deploy-to-prod
built_from: memory://session/2026-03-28-deploy-retro
iteration: 3
last_failure: "2026-04-01 — wrong PATH in non-interactive SSH"
---
built_from — the session or commit that produced this skill. Empty means hand-authored with no execution record. iteration — how many times this skill has gone through a real execution and retro cycle. Iteration 1 is first draft. Iteration 3+ means it has survived real failures and been updated. last_failure — the most recent failure this skill produced, with date and description. A skill with a documented failure is a skill that was tested and improved. A skill with no failure record either has never failed or has never been executed.
The provenance frontmatter is not overhead. It is the mechanism by which your skill library compounds value instead of accumulating risk.