#!/usr/bin/env python3 """Skills API lifecycle + one Messages call using an Anthropic skill (official Python SDK). STATUS: LIVE_VERIFIED 2026-09-18 for the HTTP sequence (executed via scripts/live.py: list/create/retrieve/versions/ download/delete, and POST /v1/messages with container.skills + code_execution → 200, ~8.3k input tokens ≈ $0.009). The SDK calls below map 1:1 (client.skills.*, client.skills.versions.*). Skills API is GA — no beta header. Run: .venv/bin/python examples/anthropic/skills/skills_lifecycle.py [--messages] (--messages adds the ~$0.01 call) """ from __future__ import annotations import io, sys from pathlib import Path ROOT = Path(__file__).resolve().parents[3] sys.path.insert(0, str(ROOT)) from scripts.live import load_env, log_request # noqa: E402 load_env() import anthropic # noqa: E402 client = anthropic.Anthropic() # 1. Anthropic skills for s in client.skills.list(source="anthropic"): print("anthropic skill:", s.id, s.display_name, s.latest_version_id) log_request("anthropic", "GET", "/v1/skills", 200, 0, "sdk skills list anthropic") # 2. create a custom skill (files must include SKILL.md with YAML frontmatter name + description) skill_md = ("---\nname: atlas-platform-agent-demo\ndescription: Tiny demo skill created by the API Atlas example; " "says OK when asked for a status check.\n---\n# Atlas demo skill\nWhen asked for a status check, reply with exactly `OK`.\n") files = [("atlas-platform-agent-demo/SKILL.md", io.BytesIO(skill_md.encode()), "text/markdown")] skill = client.skills.create(files=files, display_name="atlas-platform-agent-demo") log_request("anthropic", "POST", "/v1/skills", 200, 0, "sdk skills create") print("created", skill.id, skill.source.type, skill.latest_version_id) # 3. retrieve / versions / latest / download print("retrieve", client.skills.retrieve(skill.id).display_name) print("versions", [v.id for v in client.skills.versions.list(skill_id=skill.id)]) latest = client.skills.versions.retrieve("latest", skill_id=skill.id) print("latest", latest.id, latest.name) # download (beta reference endpoint GET /v1/skills/{id}/versions/{v}/content → zip) content = client.beta.skills.versions.download(latest.id, skill_id=skill.id) print("download zip bytes:", len(content.read()) if hasattr(content, "read") else content) # 4. second version, then delete it (deleting the ONLY version → 400) v2 = client.skills.versions.create(skill_id=skill.id, files=[ ("atlas-platform-agent-demo/SKILL.md", io.BytesIO(skill_md.replace("`OK`", "`OK` (v2)").encode()), "text/markdown"), ("atlas-platform-agent-demo/notes.md", io.BytesIO(b"# notes\n"), "text/markdown")]) print("v2", v2.id, "deleted:", client.skills.versions.delete(v2.id, skill_id=skill.id).type) # 5. cleanup: delete skill (removes all versions) print("delete skill:", client.skills.delete(skill.id).type) log_request("anthropic", "DELETE", "/v1/skills/{id}", 200, 0, "sdk skills delete") # 6. optional: use the Anthropic `xlsx` skill in a Messages call (needs code execution; ~$0.01 on Haiku 4.5) if "--messages" in sys.argv: msg = client.beta.messages.create( model="claude-haiku-4-5-20251001", max_tokens=200, betas=["code-execution-2025-08-25"], container={"skills": [{"type": "anthropic", "skill_id": "xlsx", "version": "latest"}]}, tools=[{"type": "code_execution_20250825", "name": "code_execution"}], messages=[{"role": "user", "content": "Do not run code or create files. In one sentence, what does the loaded skill help with? Then reply OK."}], ) log_request("anthropic", "POST", "/v1/messages", 200, 0.01, "sdk messages with container.skills xlsx") print([b.type for b in msg.content], msg.usage.input_tokens, msg.usage.output_tokens)