SPB Git forge

spb/doc-api

Public
2commits 1branches 0releases
15.7 MBsize
maindefault branch
13 days agolast push
Python 88.3% TypeScript 7.6% Shell 4.1%
11.1 KB

# 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:

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 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)

text
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:

json
{"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:

json
{"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

markdown
---
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 used

Observed 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.id is reused (multi-turn: reuse the container.id returned in the response to keep files).
  • Rate limits: skills have their own group (group_type: skills in 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

json
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.