Tutorials

Claude Agent Skills API Guide: Using Skills with the Claude API

Claude Agent Skills API guide — learn how to use Agent Skills with the Claude API. Complete guide to the Claude Agent Skills API with code examples in Python, TypeScript, and cURL.

AnthropicOctober 16, 202518 min read
#agent-skills#claude-api#python#typescript#code-examples
Claude Agent Skills API

This article is based on Anthropic's official documentation on Using Agent Skills with the API.

The Claude Agent Skills API extends Claude's capabilities through organized folders of instructions, scripts, and resources. This Claude Agent Skills API guide shows you how to use both pre-built and custom Agent Skills with the Claude API.

Claude Agent Skills API Overview

The Claude Agent Skills API integrates with the Messages API through the code execution tool. Whether using pre-built Agent Skills managed by Anthropic or custom Agent Skills you've uploaded, the Claude Agent Skills API integration is identical — both require code execution and use the same container structure.

Claude Agent Skills API architecture and integration flow
Claude Agent Skills API architecture and integration flow

Claude Agent Skills API: Anthropic Skills vs Custom Skills

AspectAnthropic SkillsCustom Skills
Type valueanthropiccustom
Skill IDsShort names: pptx, xlsx, docx, pdfGenerated: skill_01AbCdEfGhIjKlMnOpQrStUv
Version formatDate-based: 20251013 or latestEpoch timestamp: 1759178010641129 or latest
ManagementPre-built and maintained by AnthropicUpload and manage via Skills API
AvailabilityAvailable to all usersPrivate to your workspace

Claude Agent Skills API Prerequisites

To use the Claude Agent Skills API, you need:

  1. Anthropic API key from the Console
  2. Beta headers:
    • code-execution-2025-08-25 - Enables code execution (required for Skills)
    • skills-2025-10-02 - Enables Skills API
    • files-api-2025-04-14 - For uploading/downloading files to/from container
  3. Code execution tool enabled in your requests

Using Agent Skills in the Claude API

Container Parameter

In the Claude Agent Skills API, Agent Skills are specified using the container parameter in the Messages API. You can include up to 8 Agent Skills per request.

import anthropic

client = anthropic.Anthropic()

response = client.beta.messages.create(
    model="claude-sonnet-4-5-20250929",
    max_tokens=4096,
    betas=["code-execution-2025-08-25", "skills-2025-10-02"],
    container={
        "skills": [{"type": "anthropic", "skill_id": "pptx", "version": "latest"}]
    },
    messages=[
        {"role": "user", "content": "Create a presentation about renewable energy"}
    ],
    tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
)

TypeScript equivalent:

import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic();

const response = await client.beta.messages.create({
  model: "claude-sonnet-4-5-20250929",
  max_tokens: 4096,
  betas: ["code-execution-2025-08-25", "skills-2025-10-02"],
  container: {
    skills: [{ type: "anthropic", skill_id: "pptx", version: "latest" }]
  },
  messages: [{
    role: "user",
    content: "Create a presentation about renewable energy"
  }],
  tools: [{ type: "code_execution_20250825", name: "code_execution" }]
});

Downloading Generated Files

When Skills create documents, they return file_id attributes in the response. Use the Files API to download these files:

  1. Skills create files during code execution
  2. Response includes file_id for each created file
  3. Use Files API to download the actual file content
# Step 1: Use a Skill to create a file
response = client.beta.messages.create(
    model="claude-sonnet-4-5-20250929",
    max_tokens=4096,
    betas=["code-execution-2025-08-25", "skills-2025-10-02"],
    container={
        "skills": [{"type": "anthropic", "skill_id": "xlsx", "version": "latest"}]
    },
    messages=[
        {"role": "user", "content": "Create an Excel file with a budget spreadsheet"}
    ],
    tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
)

# Step 2: Extract file IDs from the response
def extract_file_ids(response):
    file_ids = []
    for item in response.content:
        if item.type == "bash_code_execution_tool_result":
            content_item = item.content
            if content_item.type == "bash_code_execution_result":
                for file in content_item.content:
                    if hasattr(file, "file_id"):
                        file_ids.append(file.file_id)
    return file_ids

# Step 3: Download each file
for file_id in extract_file_ids(response):
    file_metadata = client.beta.files.retrieve_metadata(
        file_id=file_id, betas=["files-api-2025-04-14"]
    )
    file_content = client.beta.files.download(
        file_id=file_id, betas=["files-api-2025-04-14"]
    )
    file_content.write_to_file(file_metadata.filename)
    print(f"Downloaded: {file_metadata.filename}")

Multi-Turn Conversations

Reuse the same container across multiple messages by specifying the container ID:

# First request creates container
response1 = client.beta.messages.create(
    model="claude-sonnet-4-5-20250929",
    max_tokens=4096,
    betas=["code-execution-2025-08-25", "skills-2025-10-02"],
    container={
        "skills": [{"type": "anthropic", "skill_id": "xlsx", "version": "latest"}]
    },
    messages=[{"role": "user", "content": "Analyze this sales data"}],
    tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
)

# Continue conversation with same container
messages = [
    {"role": "user", "content": "Analyze this sales data"},
    {"role": "assistant", "content": response1.content},
    {"role": "user", "content": "What was the total revenue?"},
]

response2 = client.beta.messages.create(
    model="claude-sonnet-4-5-20250929",
    max_tokens=4096,
    betas=["code-execution-2025-08-25", "skills-2025-10-02"],
    container={
        "id": response1.container.id,  # Reuse container
        "skills": [{"type": "anthropic", "skill_id": "xlsx", "version": "latest"}],
    },
    messages=messages,
    tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
)

Long-Running Operations

Skills may perform operations that require multiple turns. Handle pause_turn stop reasons:

messages = [{"role": "user", "content": "Process this large dataset"}]
max_retries = 10

response = client.beta.messages.create(
    model="claude-sonnet-4-5-20250929",
    max_tokens=4096,
    betas=["code-execution-2025-08-25", "skills-2025-10-02"],
    container={
        "skills": [{"type": "custom", "skill_id": "skill_01...", "version": "latest"}]
    },
    messages=messages,
    tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
)

for i in range(max_retries):
    if response.stop_reason != "pause_turn":
        break

    messages.append({"role": "assistant", "content": response.content})
    response = client.beta.messages.create(
        model="claude-sonnet-4-5-20250929",
        max_tokens=4096,
        betas=["code-execution-2025-08-25", "skills-2025-10-02"],
        container={
            "id": response.container.id,
            "skills": [{"type": "custom", "skill_id": "skill_01...", "version": "latest"}],
        },
        messages=messages,
        tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
    )

Using Multiple Skills

Combine multiple Skills in a single request (up to 8):

response = client.beta.messages.create(
    model="claude-sonnet-4-5-20250929",
    max_tokens=4096,
    betas=["code-execution-2025-08-25", "skills-2025-10-02"],
    container={
        "skills": [
            {"type": "anthropic", "skill_id": "xlsx", "version": "latest"},
            {"type": "anthropic", "skill_id": "pptx", "version": "latest"},
            {"type": "custom", "skill_id": "skill_01...", "version": "latest"},
        ]
    },
    messages=[
        {"role": "user", "content": "Analyze sales data and create a presentation"}
    ],
    tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
)

Managing Custom Agent Skills via the Claude API

Creating an Agent Skill

from anthropic.lib import files_from_dir

skill = client.beta.skills.create(
    display_title="Financial Analysis",
    files=files_from_dir("/path/to/financial_analysis_skill"),
    betas=["skills-2025-10-02"],
)

print(f"Created skill: {skill.id}")
print(f"Latest version: {skill.latest_version}")

You can also upload using a zip file or individual file tuples:

# Option 2: Using a zip file
skill = client.beta.skills.create(
    display_title="Financial Analysis",
    files=[("skill.zip", open("financial_analysis_skill.zip", "rb"))],
    betas=["skills-2025-10-02"],
)

# Option 3: Using file tuples
skill = client.beta.skills.create(
    display_title="Financial Analysis",
    files=[
        ("financial_skill/SKILL.md", open("financial_skill/SKILL.md", "rb"), "text/markdown"),
        ("financial_skill/analyze.py", open("financial_skill/analyze.py", "rb"), "text/x-python"),
    ],
    betas=["skills-2025-10-02"],
)

Requirements:

  • Must include a SKILL.md file at the top level
  • All files must specify a common root directory
  • Total upload size must be under 8MB
  • name: Maximum 64 characters, lowercase letters/numbers/hyphens only
  • description: Maximum 1024 characters, non-empty

Listing Skills

# List all Skills
skills = client.beta.skills.list(betas=["skills-2025-10-02"])
for skill in skills.data:
    print(f"{skill.id}: {skill.display_title} (source: {skill.source})")

# List only custom Skills
custom_skills = client.beta.skills.list(source="custom", betas=["skills-2025-10-02"])

Retrieving a Skill

skill = client.beta.skills.retrieve(
    skill_id="skill_01AbCdEfGhIjKlMnOpQrStUv",
    betas=["skills-2025-10-02"]
)
print(f"Skill: {skill.display_title}")
print(f"Latest version: {skill.latest_version}")

Deleting a Skill

You must first delete all versions before deleting the Skill:

# Step 1: Delete all versions
versions = client.beta.skills.versions.list(
    skill_id="skill_01...", betas=["skills-2025-10-02"]
)
for version in versions.data:
    client.beta.skills.versions.delete(
        skill_id="skill_01...",
        version=version.version,
        betas=["skills-2025-10-02"],
    )

# Step 2: Delete the Skill
client.beta.skills.delete(
    skill_id="skill_01...", betas=["skills-2025-10-02"]
)

Versioning

Skills support versioning for safe updates:

# Create a new version
new_version = client.beta.skills.versions.create(
    skill_id="skill_01...",
    files=files_from_dir("/path/to/updated_skill"),
    betas=["skills-2025-10-02"],
)

# Use specific version for production stability
container = {
    "skills": [{
        "type": "custom",
        "skill_id": "skill_01...",
        "version": "1759178010641129",  # Pinned version
    }]
}

# Use latest for development
container = {
    "skills": [{
        "type": "custom",
        "skill_id": "skill_01...",
        "version": "latest",
    }]
}

How the Claude Agent Skills API Loads Skills

When you specify Agent Skills in a container via the Claude Agent Skills API:

  1. Metadata Discovery: Claude sees metadata for each Skill (name, description) in the system prompt
  2. File Loading: Skill files are copied into the container at /skills/{directory}/
  3. Automatic Use: Claude automatically loads and uses Skills when relevant to your request
  4. Composition: Multiple Skills compose together for complex workflows

The progressive disclosure architecture ensures efficient context usage — Claude only loads full Skill instructions when needed.

Use Cases

Organizational Skills

  • Brand & Communications: Apply company-specific formatting, generate communications following templates
  • Project Management: Structure notes with company-specific formats, create standardized meeting recaps
  • Business Operations: Create company-standard reports, execute analytical procedures

Personal Skills

  • Content Creation: Custom document templates, specialized formatting
  • Data Analysis: Custom data processing pipelines, specialized visualizations
  • Development: Code generation templates, testing frameworks, deployment workflows

Example: Financial Modeling

Combine Excel and custom DCF analysis Skills:

dcf_skill = client.beta.skills.create(
    display_title="DCF Analysis",
    files=files_from_dir("/path/to/dcf_skill"),
    betas=["skills-2025-10-02"],
)

response = client.beta.messages.create(
    model="claude-sonnet-4-5-20250929",
    max_tokens=4096,
    betas=["code-execution-2025-08-25", "skills-2025-10-02"],
    container={
        "skills": [
            {"type": "anthropic", "skill_id": "xlsx", "version": "latest"},
            {"type": "custom", "skill_id": dcf_skill.id, "version": "latest"},
        ]
    },
    messages=[{
        "role": "user",
        "content": "Build a DCF valuation model for a SaaS company"
    }],
    tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
)

Best Practices

Prompt Caching

Changing the Skills list in your container will break the prompt cache. For best caching performance, keep your Skills list consistent across requests.

Version Management

  • Production: Pin to specific versions for stability
  • Development: Use "latest" for active iteration

Error Handling

try:
    response = client.beta.messages.create(...)
except anthropic.BadRequestError as e:
    if "skill" in str(e):
        print(f"Skill error: {e}")
    else:
        raise

Claude Agent Skills API Limits and Constraints

  • Maximum Agent Skills per request: 8
  • Maximum Agent Skill upload size: 8MB (all files combined)
  • No network access in the execution container
  • No runtime package installation — only pre-installed packages available
  • Isolated environment — each Claude Agent Skills API request gets a fresh container

Skills in This Post

Related Posts