Anthropic — Skills API (Agent Skills)
Status: DOCUMENTED · LIVE_VERIFIED (all 9 endpoints exercised on 2026-09-18 with a regular API key; one custom skill created with two versions, downloaded, deleted; one Messages call with container.skills + code execution succeeded). The API is GA — no beta header required; anthropic-beta: skills-2025-10-02 is an optional legacy header that switches the response shape (see §7).
Sources:
- https://platform.claude.com/docs/en/build-with-claude/skills-guide (guide, migration table)
- https://platform.claude.com/docs/en/api/skills/create · /list · /retrieve · /delete · /versions/create · /versions/list · /versions/retrieve · /versions/delete (reference) and beta twins under
/api/beta/skills/**(adds/versions/download) - https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview · /quickstart · /best-practices · /enterprise · /claude-api-skill
- https://platform.claude.com/docs/en/managed-agents/skills (skills inside Managed Agents)
- Live run:
tmp-live/platform-anthropic/skills-probes.json
Last verified: 2026-09-18
1. Concept
An Agent Skill is a directory containing a SKILL.md (YAML frontmatter name + description, then Markdown instructions) plus optional resources (scripts, templates, reference files). Claude sees only the metadata (name/description) in its system prompt, and loads the full instructions/files only when relevant ("progressive disclosure"). Skills run inside the code execution container: files are copied to /skills/{skill-name}/ (directory = SKILL.md name, e.g. /skills/xlsx/SKILL.md — observed in the live call).
| Aspect | Anthropic skills | Custom skills |
|---|---|---|
type in container.skills[] |
anthropic |
custom |
skill_id |
short names pptx, xlsx, docx, pdf |
generated skill_01… |
version |
date string (20260914) or latest |
skver_01… or latest |
| Management | read-only, maintained by Anthropic | POST/DELETE /v1/skills… (private to the workspace) |
source.type (list/retrieve) |
anthropic (also anthropic_example for sample skills, plugin for installed plugins) |
custom |
Where skills work: Claude API (Messages + code execution), Managed Agents (skills[] on the agent: {type: "anthropic"|"custom", skill_id, version?}, or loaded from a GitHub repo resource), Claude Code (filesystem ~/.claude/skills/, .claude/skills/; the pre-built document skills are not available there), claude.ai settings, Claude Agent SDK (filesystem skills via setting_sources). The open-source Claude API skill (claude-api-skill) bundles current API/SDK docs for 8 languages.
Anthropic-provided skills (observed with GET /v1/skills?source=anthropic, 2026-09-18)
| id | display_name | latest_version_id | created_at | updated_at |
|---|---|---|---|---|
xlsx |
xlsx | skver_01VjgyVDe1t75fvdG94bvEaQ |
2025-10-14 | 2026-09-14 |
pptx |
pptx | skver_01NcgaDAkpvpzt4YRmxgghsy |
2025-10-14 | 2026-09-14 |
pdf |
skver_01CsNFhoTLfMuLDRhVKynLwo |
2025-10-14 | 2026-07-10 | |
docx |
docx | skver_01FM1raxosQBBYK826f6pzwR |
2025-10-14 | 2026-09-14 |
With the legacy header the same list returns display_title, source: "anthropic" (string) and latest_version: "20260914" (catalog date).
2. Endpoints
| Method | Path | Title | Path/query params | Body | Pagination | Beta header | Status |
|---|---|---|---|---|---|---|---|
GET |
/v1/skills |
List Skills | limit, page, source | — | opaque_cursor | — | LV |
POST |
/v1/skills |
Create Skill | — | multipart | — | — | LV |
DELETE |
/v1/skills/{skill_id} |
Delete Skill | — | — | — | — | LV |
GET |
/v1/skills/{skill_id} |
Get Skill | — | — | — | — | LV |
GET |
/v1/skills/{skill_id}/versions |
List Skill Versions | limit, page | — | opaque_cursor | — | LV |
POST |
/v1/skills/{skill_id}/versions |
Create Skill Version | — | multipart | — | — | LV |
DELETE |
/v1/skills/{skill_id}/versions/{version} |
Delete Skill Version | — | — | — | — | LV |
GET |
/v1/skills/{skill_id}/versions/{version} |
Get Skill Version | — | — | — | — | LV |
GET |
/v1/skills/{skill_id}/versions/{version}/content |
Download Skill Version Content | — | — | — | — | LV |
Optional header on every call: anthropic-workspace-id. Pagination: opaque cursor (limit 1–1000, default 20; page = previous next_page); versions are listed newest first.
Create (multipart/form-data)
POST /v1/skills
files[] = @atlas-demo/SKILL.md (repeatable; all files under one top-level directory, SKILL.md at its root — or at the upload root)
display_name = "atlas-platform-agent-demo" (optional, ≤ 255 chars, not unique; defaults to frontmatter name)Response Skill:
{"type":"skill","id":"skill_011tJbtUvs2xQ2drGLcC8Z1M","display_name":"atlas-platform-agent-demo",
"source":{"type":"custom"},"latest_version_id":"skver_01CKzJKuF5LExdXSAvYPcPmW",
"created_at":"2026-09-19T01:51:47.851333Z","updated_at":"2026-09-19T01:51:47.851333Z"}POST /v1/skills/{skill_id}/versions takes the same files[] (no display_name) and returns a SkillVersion:
{"type":"skill_version","id":"skver_01NudXrqZ4awLQWMpe8zQHua","skill_id":"skill_011tJbtUvs2xQ2drGLcC8Z1M",
"name":"atlas-platform-agent-demo","description":"Tiny demo skill …","created_at":"2026-09-19T01:51:50.377187Z"}GET /v1/skills/{id}/versions/latest resolves the newest version in one call (observed 200). GET …/versions/{v}/content returns a zip archive (PK…, observed 317 bytes for one file) — beta reference page only, but works without the header.
Delete semantics (observed)
| Call | Result |
|---|---|
DELETE /v1/skills/{id}/versions/{v} (not the only version) |
200 {"type":"skill_version_deleted","id":"skver_…"} |
DELETE …/versions/{v} (the only remaining version) |
400 invalid_request_error "cannot delete a Skill's only version. Delete the Skill, or create another version first" |
DELETE /v1/skills/{id} |
200 {"type":"skill_deleted","id":"skill_…"} — deletes all versions |
GET/DELETE afterwards |
404 not_found_error "Skill not found: skill_…" |
3. SKILL.md format
---
name: atlas-platform-agent-demo # ≤ 64 chars, lowercase letters/digits/hyphens, no XML tags, not "anthropic"/"claude"
description: Tiny demo skill … # ≤ 1024 chars, non-empty, no XML tags — this is what Claude sees to decide to load the skill
---
# Instructions (Markdown) — loaded only when the skill is usedObserved validation error for a file without frontmatter: 400 invalid_request_error "SKILL.mdmust be UTF-8 text opening with a----fenced YAML frontmatter mapping".
4. Limits & environment (documented)
- ≤ 20 skills per request (
container.skills), ≤ 30 MB per upload (uncompressed, all files). - Container: no network, no runtime package install, fresh container unless
container.idis reused (multi-turn: reuse thecontainer.idreturned in the response to keep files). - Rate limits: skills have their own group (
group_type: skillsin the Rate Limits Admin API). - Data retention: skills are not ZDR-eligible. Creation/deletion is recorded in the Compliance API Activity Feed when enabled.
- Prompt caching: skill metadata sits in the system prompt — changing the skill set invalidates the cache prefix.
5. Using skills in Messages
POST /v1/messages (anthropic-beta: code-execution-2025-08-25)
{"model":"claude-haiku-4-5-20251001","max_tokens":200,
"container":{"skills":[{"type":"anthropic","skill_id":"xlsx","version":"latest"}]},
"tools":[{"type":"code_execution_20250825","name":"code_execution"}],
"messages":[{"role":"user","content":"…"}]}Live result (2026-09-18, sent with code-execution-2025-08-25,skills-2025-10-02): 200, Claude ran text_editor_code_execution view /skills/xlsx/SKILL.md (server tool, srvtoolu_…), then answered; usage: 8315 input / 130 output tokens, stop_reason: end_turn → ≈ $0.009 at Haiku 4.5 prices (the skill metadata + tool descriptions add ~8k input tokens). Response container field carries the container id and expiry. Generated files are downloaded with the Files API (file_id in code_execution results). Whether the skills-2025-10-02 header is needed on Messages requests with container.skills was not isolated (we always sent it); the guide states skills need only code execution.
Model compatibility = code-execution-tool compatibility list. Managed Agents: skills: [{type:"custom", skill_id, version}] on POST /v1/agents (observed skills: [] echo on create).
6. SDK surface
| Python | TypeScript | |
|---|---|---|
| GA namespace | client.skills.create(files=[...], display_name=…), .retrieve, .list(source="anthropic"), .delete; client.skills.versions.create/retrieve/list/delete |
client.skills.*, client.skills.versions.* |
| Beta namespace | client.beta.skills.* — since Python 1.2.0 / TS 0.122.0 no longer sends skills-2025-10-02 (types BetaSkill, BetaSkillVersion, BetaDeletedSkill, BetaDeletedSkillVersion); older releases send it implicitly |
same |
| Download content | client.beta.skills.versions.download(...) (beta reference) |
same |
| Container skill reference type | ContainerSkill (beta: BetaContainerSkill, formerly BetaSkill) |
— |
7. Legacy header skills-2025-10-02 vs GA shapes (documented table, both observed on list)
| With header | Without header (GA) | |
|---|---|---|
| Label | display_title (≤ 64, unique per workspace) |
display_name (≤ 255, not unique) |
| Newest version pointer | latest_version (epoch-µs string; Anthropic skills: catalog date "20260914") |
latest_version_id (skver_…) |
| Version id in URLs | epoch string | skver_… (old skill_version_… ids accepted) |
source |
string "custom"/"anthropic" |
object {"type": "custom"} (anthropic_example, plugin possible) |
| List response | {data, has_more, next_page} |
{data, next_page} |
| Versions order | oldest first | newest first |
| Delete skill | 400 while versions exist | deletes skill and versions |
| Delete only version | allowed (skill left empty) | 400 |
| Upload layout | files inside top-level dir named as the skill | SKILL.md may sit at the upload root |
| Version object | has directory |
no directory |
8. Live run summary (2026-09-18)
GET /v1/skills?source=anthropic 200 (4 skills) · with legacy header 200 (legacy shape) · ?source=custom 200 ([]) · POST /v1/skills 200 · GET /v1/skills/{id} 200 · GET …/versions 200 (1) · GET …/versions/{id} 200 · GET …/versions/latest 200 · GET …/versions/{id}/content 200 (zip) · POST …/versions (2 files) 200 · GET …/versions 200 (2, newest first) · invalid SKILL.md 400 · DELETE …/versions/{v2} 200 · DELETE …/versions/{v1} 400 (only version) · DELETE /v1/skills/{id} 200 · GET 404 · DELETE again 404 · POST /v1/messages with container.skills 200. Cleanup complete (no custom skills remain). Examples: examples/anthropic/skills/; tests: tests/anthropic/test_skills.py.