caching: 1h tools cache + cache token chip in status bar
ober
8a5bea9171f2cf468274d5391d9decd38698ccbd
new file mode 100644 --- /dev/null +++ b/claude-api-skill.md @@ -0,0 +1,1299 @@ +# Claude API Skill — Comprehensive Reference + +This document is a comprehensive reference for building LLM-powered applications with Claude, derived from the `claude-api` skill bundled with Claude Code. + +--- + +## Table of Contents + +1. [Overview & Output Requirements](#overview--output-requirements) +2. [Defaults](#defaults) +3. [Subcommands](#subcommands) +4. [Language Detection](#language-detection) +5. [Which Surface Should I Use?](#which-surface-should-i-use) +6. [Architecture](#architecture) +7. [Current Models](#current-models) +8. [Thinking & Effort](#thinking--effort) +9. [Compaction](#compaction) +10. [Prompt Caching](#prompt-caching) +11. [Python SDK Reference](#python-sdk-reference) +12. [TypeScript SDK Reference](#typescript-sdk-reference) +13. [Tool Use](#tool-use) +14. [Managed Agents](#managed-agents) +15. [Batches API](#batches-api) +16. [Files API](#files-api) +17. [Streaming](#streaming) +18. [Structured Outputs](#structured-outputs) +19. [Model Migration](#model-migration) +20. [Error Handling](#error-handling) +21. [Cloud Providers](#cloud-providers) +22. [Live Sources](#live-sources) + +--- + +## Overview & Output Requirements + +### Before You Start + +Scan the target file (or, if no target file, the prompt and project) for non-Anthropic provider markers — `import openai`, `from openai`, `langchain_openai`, `OpenAI(`, `gpt-4`, `gpt-5`, file names like `agent-openai.py` or `*-generic.py`, or any explicit instruction to keep the code provider-neutral. If you find any, stop and tell the user that this skill produces Claude/Anthropic SDK code; ask whether they want to switch the file to Claude or want a non-Claude implementation. Do not edit a non-Anthropic file with Anthropic SDK calls. + +### Output Requirement + +When the user asks you to add, modify, or implement a Claude feature, your code must call Claude through one of: + +1. **The official Anthropic SDK** for the project's language (`anthropic`, `@anthropic-ai/sdk`, `com.anthropic.*`, etc.). This is the default whenever a supported SDK exists for the project. +2. **Raw HTTP** (`curl`, `requests`, `fetch`, `httpx`, etc.) — only when the user explicitly asks for cURL/REST/raw HTTP, the project is a shell/cURL project, or the language has no official SDK. + +Never mix the two — don't reach for `requests`/`fetch` in a Python or TypeScript project just because it feels lighter. Never fall back to OpenAI-compatible shims. + +**Never guess SDK usage.** Function names, class names, namespaces, method signatures, and import paths must come from explicit documentation — either the `{lang}/` files in this skill or the official SDK repositories or documentation links listed in `shared/live-sources.md`. If the binding you need is not explicitly documented in the skill files, WebFetch the relevant SDK repo before writing code. Do not infer Ruby/Java/Go/PHP/C# APIs from cURL shapes or from another language's SDK. + +--- + +## Defaults + +Unless the user requests otherwise: + +- **Model**: Use Claude Opus 4.7, exact model string `claude-opus-4-7`. +- **Thinking**: Default to adaptive thinking (`thinking: {type: "adaptive"}`) for anything remotely complicated. +- **Streaming**: Default to streaming for any request that may involve long input, long output, or high `max_tokens` — it prevents hitting request timeouts. Use the SDK's `.get_final_message()` / `.finalMessage()` helper to get the complete response if you don't need to handle individual stream events. + +--- + +## Subcommands + +| Subcommand | Action | +|---|---| +| `migrate` | Migrate existing Claude API code to a newer model. Read `shared/model-migration.md` immediately and follow it in order: Step 0 (confirm scope — ask which files/directories before any edit), Step 1 (classify each file), then the per-target breaking-changes section. | + +--- + +## Language Detection + +Before reading code examples, determine which language the user is working in: + +1. **Look at project files** to infer the language: + - `*.py`, `requirements.txt`, `pyproject.toml`, `setup.py`, `Pipfile` → **Python** + - `*.ts`, `*.tsx`, `package.json`, `tsconfig.json` → **TypeScript** + - `*.js`, `*.jsx` (no `.ts` files present) → **TypeScript** (JS uses the same SDK) + - `*.java`, `pom.xml`, `build.gradle` → **Java** + - `*.kt`, `*.kts`, `build.gradle.kts` → **Java** (Kotlin uses Java SDK) + - `*.scala`, `build.sbt` → **Java** (Scala uses Java SDK) + - `*.go`, `go.mod` → **Go** + - `*.rb`, `Gemfile` → **Ruby** + - `*.cs`, `*.csproj` → **C#** + - `*.php`, `composer.json` → **PHP** + +2. **If multiple languages detected**: Ask which language the user is using. + +3. **If language can't be inferred**: Ask, with options Python/TypeScript/Java/Go/Ruby/cURL/C#/PHP. + +4. **If unsupported language** (Rust, Swift, C++, Elixir, etc.): Suggest cURL/raw HTTP, note that community SDKs may exist. + +5. **For cURL/raw HTTP examples**, use the curl reference patterns. + +### Language-Specific Feature Support + +| Language | Tool Runner | Managed Agents | Notes | +| ---------- | ----------- | -------------- | ------------------------------------- | +| Python | Yes (beta) | Yes (beta) | Full support — `@beta_tool` decorator | +| TypeScript | Yes (beta) | Yes (beta) | Full support — `betaZodTool` + Zod | +| Java | Yes (beta) | Yes (beta) | Beta tool use with annotated classes | +| Go | Yes (beta) | Yes (beta) | `BetaToolRunner` in `toolrunner` pkg | +| Ruby | Yes (beta) | Yes (beta) | `BaseTool` + `tool_runner` in beta | +| C# | Yes (beta) | Yes (beta) | `BetaToolRunner` + raw JSON schema | +| PHP | Yes (beta) | Yes (beta) | `BetaRunnableTool` + `toolRunner()` | +| cURL | N/A | Yes (beta) | Raw HTTP, no SDK features | + +--- + +## Which Surface Should I Use? + +> **Start simple.** Default to the simplest tier that meets your needs. Single API calls and workflows handle most use cases — only reach for agents when the task genuinely requires open-ended, model-driven exploration. + +| Use Case | Tier | Recommended Surface | Why | +| ----------------------------------------------- | --------------- | ------------------------- | ------------------------------------------------------------ | +| Classification, summarization, extraction, Q&A | Single LLM call | **Claude API** | One request, one response | +| Batch processing or embeddings | Single LLM call | **Claude API** | Specialized endpoints | +| Multi-step pipelines with code-controlled logic | Workflow | **Claude API + tool use** | You orchestrate the loop | +| Custom agent with your own tools | Agent | **Claude API + tool use** | Maximum flexibility | +| Server-managed stateful agent with workspace | Agent | **Managed Agents** | Anthropic runs the loop and hosts the tool-execution sandbox | +| Persisted, versioned agent configs | Agent | **Managed Agents** | Agents are stored objects; sessions pin to a version | +| Long-running multi-turn agent with file mounts | Agent | **Managed Agents** | Per-session containers, SSE event stream, Skills + MCP | + +> **Cloud-provider access.** **Claude Platform on AWS** is Anthropic-operated with same-day API parity — Managed Agents and every feature work there. **Amazon Bedrock**, **Google Vertex AI**, and **Microsoft Foundry** do NOT support Managed Agents or Anthropic server-side tools; use **Claude API + tool use** on those. + +### Decision Tree + +``` +What does your application need? + +0. Which provider? + ├── First-party API or Claude Platform on AWS → continue (full surface available). + └── Amazon Bedrock, Google Vertex AI, or Microsoft Foundry → Claude API (+ tool use for agents); Managed Agents not available there. + +1. Single LLM call (classification, summarization, extraction, Q&A) + └── Claude API — one request, one response + +2. Do you want Anthropic to run the agent loop and host a per-session + container where Claude executes tools (bash, file ops, code)? + └── Yes → Managed Agents — server-managed sessions, persisted agent configs, + SSE event stream, Skills + MCP, file mounts. + +3. Workflow (multi-step, code-orchestrated, with your own tools) + └── Claude API with tool use — you control the loop + +4. Open-ended agent (model decides its own trajectory, your own tools, you host the compute) + └── Claude API agentic loop (maximum flexibility) +``` + +### Should I Build an Agent? + +Before choosing the agent tier, check all four criteria: + +- **Complexity** — Is the task multi-step and hard to fully specify in advance? +- **Value** — Does the outcome justify higher cost and latency? +- **Viability** — Is Claude capable at this task type? +- **Cost of error** — Can errors be caught and recovered from? (tests, review, rollback) + +If "no" to any, stay at a simpler tier (single call or workflow). + +--- + +## Architecture + +Everything goes through `POST /v1/messages`. Tools and output constraints are features of this single endpoint — not separate APIs. + +**User-defined tools** — You define tools (via decorators, Zod schemas, or raw JSON), and the SDK's tool runner handles calling the API, executing your functions, and looping until Claude is done. For full control, you can write the loop manually. + +**Server-side tools** — Anthropic-hosted tools that run on Anthropic's infrastructure. Code execution is fully server-side (declare it in `tools`, Claude runs code automatically). Computer use can be server-hosted or self-hosted. + +**Structured outputs** — Constrains the Messages API response format (`output_config.format`) and/or tool parameter validation (`strict: true`). The recommended approach is `client.messages.parse()` which validates responses against your schema automatically. Note: the old `output_format` parameter is deprecated; use `output_config: {format: {...}}` on `messages.create()`. + +**Supporting endpoints** — Batches (`POST /v1/messages/batches`), Files (`POST /v1/files`), Token Counting, and Models (`GET /v1/models`, `GET /v1/models/{id}` — live capability/context-window discovery) feed into or support Messages API requests. + +--- + +## Current Models + +(Cached: 2026-04-29) + +| Model | Model ID | Context | Input $/1M | Output $/1M | +| ----------------- | ------------------- | -------------- | ---------- | ----------- | +| Claude Opus 4.7 | `claude-opus-4-7` | 1M | $5.00 | $25.00 | +| Claude Opus 4.6 | `claude-opus-4-6` | 1M | $5.00 | $25.00 | +| Claude Sonnet 4.6 | `claude-sonnet-4-6` | 1M | $3.00 | $15.00 | +| Claude Haiku 4.5 | `claude-haiku-4-5` | 200K | $1.00 | $5.00 | + +**ALWAYS use `claude-opus-4-7` unless the user explicitly names a different model.** Do not use `claude-sonnet-4-6`, `claude-sonnet-4-5`, or any other model unless the user literally says "use sonnet" or "use haiku". Never downgrade for cost — that's the user's decision, not yours. + +**CRITICAL: Use only the exact model ID strings from the table above — they are complete as-is. Do not append date suffixes.** For example, use `claude-sonnet-4-6`, never `claude-sonnet-4-6-20251114`. + +**Live capability lookup:** The table above is cached. When the user asks "what's the context window for X", "does X support vision/thinking/effort", or "which models support Y", query the Models API (`client.models.retrieve(id)` / `client.models.list()`). + +--- + +## Thinking & Effort + +### Opus 4.7 — Adaptive thinking only + +Use `thinking: {type: "adaptive"}`. `thinking: {type: "enabled", budget_tokens: N}` returns a 400 on Opus 4.7 — adaptive is the only on-mode. `{type: "disabled"}` and omitting `thinking` both work. Sampling parameters (`temperature`, `top_p`, `top_k`) are also removed and will 400. + +### Opus 4.6 — Adaptive thinking (recommended) + +Use `thinking: {type: "adaptive"}`. Claude dynamically decides when and how much to think. No `budget_tokens` needed — `budget_tokens` is deprecated on Opus 4.6 and Sonnet 4.6 and should not be used for new code. Adaptive thinking also automatically enables interleaved thinking (no beta header needed). + +**When the user asks for "extended thinking", a "thinking budget", or `budget_tokens`: always use Opus 4.7 or 4.6 with `thinking: {type: "adaptive"}`.** The concept of a fixed token budget for thinking is deprecated — adaptive thinking replaces it. + +### Effort parameter (GA, no beta header) + +Controls thinking depth and overall token spend via `output_config: {effort: "low"|"medium"|"high"|"max"}` (inside `output_config`, not top-level). Default is `high`. `max` is Opus-tier only (Opus 4.6 and later). Opus 4.7 adds `"xhigh"` (between `high` and `max`) — the best setting for most coding and agentic use cases on 4.7, and the default in Claude Code. + +Works on Opus 4.5, Opus 4.6, Opus 4.7, and Sonnet 4.6. Will error on Sonnet 4.5 / Haiku 4.5. + +- `low` for subagents or simple tasks +- `medium` for moderate work +- `high` is the sweet spot balancing quality and token efficiency +- `xhigh` (Opus 4.7 only) — best for coding/agentic +- `max` when correctness matters more than cost + +### Opus 4.7 — thinking content omitted by default + +`thinking` blocks still stream but their text is empty unless you opt in with `thinking: {type: "adaptive", display: "summarized"}` (default is `"omitted"`). Silent change — no error. If you stream reasoning to users, set `"summarized"` to restore visible progress. + +### Task Budgets (beta, Opus 4.7) + +`output_config: {task_budget: {type: "tokens", total: N}}` tells the model how many tokens it has for a full agentic loop — it sees a running countdown and self-moderates (minimum 20,000; beta header `task-budgets-2026-03-13`). Distinct from `max_tokens`, which is an enforced per-response ceiling the model is not aware of. + +### Sonnet 4.6 + +Supports adaptive thinking (`thinking: {type: "adaptive"}`). `budget_tokens` is deprecated on Sonnet 4.6 — use adaptive thinking instead. + +### Older models (only if explicitly requested) + +If the user specifically asks for Sonnet 4.5 or another older model, use `thinking: {type: "enabled", budget_tokens: N}`. `budget_tokens` must be less than `max_tokens` (minimum 1024). Never choose an older model just because the user mentions `budget_tokens` — use Opus 4.7 with adaptive thinking instead. + +--- + +## Compaction + +**Beta, Opus 4.7, Opus 4.6, and Sonnet 4.6.** For long-running conversations that may exceed the 1M context window, enable server-side compaction. The API automatically summarizes earlier context when it approaches the trigger threshold (default: 150K tokens). Requires beta header `compact-2026-01-12`. + +**Critical:** Append `response.content` (not just the text) back to your messages on every turn. Compaction blocks in the response must be preserved — the API uses them to replace the compacted history on the next request. Extracting only the text string and appending that will silently lose the compaction state. + +### Example (Python) + +```python +from anthropic import Anthropic + +client = Anthropic(default_headers={"anthropic-beta": "compact-2026-01-12"}) + +messages = [] +for user_input in conversation_inputs: + messages.append({"role": "user", "content": user_input}) + response = client.messages.create( + model="claude-opus-4-7", + max_tokens=4096, + messages=messages, + compact={"enabled": True, "trigger_threshold": 150_000}, + ) + # CRITICAL: append response.content (the full content array), not just text + messages.append({"role": "assistant", "content": response.content}) +``` + +--- + +## Prompt Caching + +**Prefix match.** Any byte change anywhere in the prefix invalidates everything after it. Render order is `tools` → `system` → `messages`. Keep stable content first (frozen system prompt, deterministic tool list), put volatile content (timestamps, per-request IDs, varying questions) after the last `cache_control` breakpoint. + +**Top-level auto-caching** (`cache_control: {type: "ephemeral"}` on `messages.create()`) is the simplest option when you don't need fine-grained placement. Max 4 breakpoints per request. Minimum cacheable size: 1024 tokens (Opus/Sonnet) or 2048 tokens (Haiku). + +### Economics + +- **Cache write**: ~1.25x normal input price (5-minute TTL) or ~2x (1-hour TTL) +- **Cache hit**: ~0.1x normal input price +- **Cache miss**: full input price + +### TTL options + +- **Default**: 5 minutes (`cache_control: {type: "ephemeral"}`) +- **Extended**: 1 hour (`cache_control: {type: "ephemeral", ttl: "1h"}`) + +### Placement Strategy + +```python +# Stable content (system prompt, tools, large context) — cached +# Volatile content (per-request user message) — NOT cached + +response = client.messages.create( + model="claude-opus-4-7", + max_tokens=4096, + system=[ + { + "type": "text", + "text": LARGE_STABLE_SYSTEM_PROMPT, + "cache_control": {"type": "ephemeral"}, + } + ], + messages=[ + {"role": "user", "content": "Today's question changes per request"}, + ], +) +``` + +### Cache hits/misses inspection + +```python +print(response.usage.cache_creation_input_tokens) # Tokens written to cache +print(response.usage.cache_read_input_tokens) # Tokens read from cache (hit) +print(response.usage.input_tokens) # Tokens NOT cached (miss/uncached) +``` + +--- + +## Python SDK Reference + +### Installation + +```bash +pip install anthropic +``` + +### Basic Usage + +```python +from anthropic import Anthropic + +client = Anthropic() # Reads ANTHROPIC_API_KEY from env + +response = client.messages.create( + model="claude-opus-4-7", + max_tokens=1024, + messages=[ + {"role": "user", "content": "Hello, Claude!"} + ], +) +print(response.content[0].text) +``` + +### With Adaptive Thinking + +```python +response = client.messages.create( + model="claude-opus-4-7", + max_tokens=4096, + thinking={"type": "adaptive"}, # Or {"type": "adaptive", "display": "summarized"} + messages=[{"role": "user", "content": "Solve this complex problem..."}], +) +``` + +### With Effort Parameter + +```python +response = client.messages.create( + model="claude-opus-4-7", + max_tokens=4096, + output_config={"effort": "xhigh"}, # Opus 4.7 only: "low"|"medium"|"high"|"xhigh"|"max" + messages=[{"role": "user", "content": "Write production-grade code for..."}], +) +``` + +### Multi-turn Conversations + +```python +messages = [] + +def chat(user_input): + messages.append({"role": "user", "content": user_input}) + response = client.messages.create( + model="claude-opus-4-7", + max_tokens=2048, + messages=messages, + ) + # Append the full content array, not just text + messages.append({"role": "assistant", "content": response.content}) + return response.content[0].text +``` + +### Vision (Image Input) + +```python +import base64 + +with open("image.jpg", "rb") as f: + image_data = base64.standard_b64encode(f.read()).decode("utf-8") + +response = client.messages.create( + model="claude-opus-4-7", + max_tokens=1024, + messages=[ + { + "role": "user", + "content": [ + { + "type": "image", + "source": { + "type": "base64", + "media_type": "image/jpeg", + "data": image_data, + }, + }, + {"type": "text", "text": "What's in this image?"}, + ], + } + ], +) +``` + +### Async Client + +```python +from anthropic import AsyncAnthropic + +client = AsyncAnthropic() + +async def main(): + response = await client.messages.create( + model="claude-opus-4-7", + max_tokens=1024, + messages=[{"role": "user", "content": "Hello!"}], + ) + print(response.content[0].text) +``` + +### Error Handling + +```python +from anthropic import APIError, RateLimitError, APIConnectionError + +try: + response = client.messages.create(...) +except RateLimitError as e: + # 429 — back off and retry + print(f"Rate limited: {e}") +except APIConnectionError as e: + # Network error — retry with backoff + print(f"Connection error: {e}") +except APIError as e: + # Other API errors + print(f"API error: {e}") +``` + +--- + +## TypeScript SDK Reference + +### Installation + +```bash +npm install @anthropic-ai/sdk +``` + +### Basic Usage + +```typescript +import Anthropic from "@anthropic-ai/sdk"; + +const client = new Anthropic(); // Reads ANTHROPIC_API_KEY from env + +const response = await client.messages.create({ + model: "claude-opus-4-7", + max_tokens: 1024, + messages: [{ role: "user", content: "Hello, Claude!" }], +}); + +console.log(response.content[0].type === "text" ? response.content[0].text : ""); +``` + +### With Adaptive Thinking + +```typescript +const response = await client.messages.create({ + model: "claude-opus-4-7", + max_tokens: 4096, + thinking: { type: "adaptive" }, + messages: [{ role: "user", content: "Solve this..." }], +}); +``` + +### Streaming + +```typescript +const stream = client.messages.stream({ + model: "claude-opus-4-7", + max_tokens: 4096, + messages: [{ role: "user", content: "Write a story" }], +}); + +for await (const event of stream) { + if (event.type === "content_block_delta" && event.delta.type === "text_delta") { + process.stdout.write(event.delta.text); + } +} + +const finalMessage = await stream.finalMessage(); +``` + +--- + +## Tool Use + +### Python Tool Runner (Beta) + +The Tool Runner handles the entire agentic loop: API calls, tool execution, message updates, and termination. + +```python +from anthropic import Anthropic +from anthropic.lib.tools import beta_tool, beta_tool_runner + +client = Anthropic() + +@beta_tool +def get_weather(location: str, unit: str = "celsius") -> str: + """Get the current weather for a location. + + Args: + location: City and state, e.g. "San Francisco, CA" + unit: Temperature unit, "celsius" or "fahrenheit" + """ + return f"The weather in {location} is sunny, 22°{unit[0].upper()}" + +@beta_tool +def calculate(expression: str) -> float: + """Evaluate a math expression.""" + return eval(expression) # Don't actually use eval in production + +result = beta_tool_runner( + client=client, + model="claude-opus-4-7", + max_tokens=4096, + tools=[get_weather, calculate], + messages=[{"role": "user", "content": "What's the weather in Paris?"}], +) + +print(result.final_message.content[0].text) +``` + +### Manual Agentic Loop (Python) + +For fine-grained control (approval gates, custom logging, conditional execution): + +```python +tools = [ + { + "name": "get_weather", + "description": "Get the current weather for a location", + "input_schema": { + "type": "object", + "properties": { + "location": {"type": "string"}, + }, + "required": ["location"], + }, + } +] + +messages = [{"role": "user", "content": "What's the weather in Paris?"}] + +while True: + response = client.messages.create( + model="claude-opus-4-7", + max_tokens=4096, + tools=tools, + messages=messages, + ) + + if response.stop_reason == "end_turn": + break + + if response.stop_reason == "tool_use": + messages.append({"role": "assistant", "content": response.content}) + + tool_results = [] + for block in response.content: + if block.type == "tool_use": + # Execute the tool + result = run_tool(block.name, block.input) + tool_results.append({ + "type": "tool_result", + "tool_use_id": block.id, + "content": result, + }) + + messages.append({"role": "user", "content": tool_results}) + else: + break +``` + +### TypeScript Tool Runner + +```typescript +import Anthropic from "@anthropic-ai/sdk"; +import { betaZodTool, betaToolRunner } from "@anthropic-ai/sdk/helpers/beta"; +import { z } from "zod"; + +const client = new Anthropic(); + +const getWeather = betaZodTool({ + name: "get_weather", + description: "Get the current weather for a location", + inputSchema: z.object({ + location: z.string(), + unit: z.enum(["celsius", "fahrenheit"]).default("celsius"), + }), + run: async ({ location, unit }) => { + return `Weather in ${location}: sunny, 22°${unit[0].toUpperCase()}`; + }, +}); + +const result = await betaToolRunner({ + client, + model: "claude-opus-4-7", + max_tokens: 4096, + tools: [getWeather], + messages: [{ role: "user", content: "Weather in Paris?" }], +}); +``` + +### Server-Side Code Execution + +Anthropic hosts the execution sandbox; you only declare the tool: + +```python +response = client.messages.create( + model="claude-opus-4-7", + max_tokens=4096, + tools=[{"type": "code_execution_20250825", "name": "code_execution"}], + messages=[{"role": "user", "content": "Calculate fibonacci(20)"}], + extra_headers={"anthropic-beta": "code-execution-2025-08-25"}, +) +``` + +### Memory Tool + +A built-in tool for persistent memory across conversations. Useful for long-running agents that need to remember facts between sessions. + +### MCP (Model Context Protocol) Integration + +The Python SDK includes MCP helpers for connecting to MCP servers as tool sources: + +```python +from anthropic.lib.tools import beta_tool_runner_with_mcp + +# Connect to local MCP server +result = beta_tool_runner_with_mcp( + client=client, + model="claude-opus-4-7", + mcp_servers=[{"command": "python", "args": ["server.py"]}], + messages=[{"role": "user", "content": "Use the MCP tools"}], +) +``` + +--- + +## Managed Agents + +Server-managed stateful agents where Anthropic runs the loop and hosts the per-session container. + +**Key concept**: Agents are persistent — create once, reference by ID. Store the agent ID returned by `agents.create` and pass it to every subsequent `sessions.create`; do not call `agents.create` in the request path. + +### Python Example + +```python +from anthropic import Anthropic + +client = Anthropic(default_headers={"anthropic-beta": "agents-2026-01-01"}) + +# Create environment (one-time, version-controlled config) +environment = client.beta.environments.create( + name="my-coding-env", + container={ + "image": "anthropic/agent-base:latest", + "resources": {"cpu": "2", "memory": "4Gi"}, + }, + tools=["bash", "file_editor", "code_execution"], +) + +# Create agent (one-time, persistent) +agent = client.beta.agents.create( + name="my-coding-agent", + model="claude-opus-4-7", + environment_id=environment.id, + system="You are a coding assistant...", +) + +# Per-task: create a session, send messages, stream events +session = client.beta.sessions.create(agent_id=agent.id) + +with client.beta.sessions.events.stream(session_id=session.id) as stream: + client.beta.sessions.messages.create( + session_id=session.id, + content="Build a TODO app in Python", + ) + for event in stream: + print(event) +``` + +### Session Lifecycle + +1. **Create environment** (one-time, version-controlled) +2. **Create agent** (one-time, references environment) +3. **Create session** (per-task, references agent) +4. **Stream events** (SSE) — `text_delta`, `tool_use`, `tool_result`, `message_done`, etc. +5. **Send messages** to session +6. **Close session** when done (or let it expire) + +### Custom Tools in Managed Agents + +You can register custom tools that execute in your own infrastructure, with Anthropic forwarding tool calls to your endpoint: + +```python +agent = client.beta.agents.create( + name="agent-with-custom-tools", + model="claude-opus-4-7", + environment_id=environment.id, + custom_tools=[ + { + "name": "lookup_user", + "description": "Look up a user by ID in our database", + "input_schema": {...}, + "execution": { + "type": "webhook", + "url": "https://my-api.example.com/tools/lookup_user", + }, + } + ], +) +``` + +### File Mounts + +Sessions can mount files (read-only or read-write) that Claude can access in the workspace. + +### Skills + MCP in Managed Agents + +Agents can load skills (versioned, named bundles of instructions + tools) and connect to MCP servers for additional tool sources. + +### Anthropic CLI (`ant`) + +Convenient way to create agents and environments from version-controlled YAML: + +```yaml +# agent.yaml +name: my-coding-agent +model: claude-opus-4-7 +environment: my-env +system: | + You are a coding assistant... +tools: + - bash + - file_editor +``` + +```bash +ant agents create -f agent.yaml +ant sessions create --agent my-coding-agent +``` + +--- + +## Batches API + +Process many messages asynchronously at 50% cost. + +### Python Example + +```python +batch = client.messages.batches.create( + requests=[ + { + "custom_id": f"req-{i}", + "params": { + "model": "claude-opus-4-7", + "max_tokens": 1024, + "messages": [{"role": "user", "content": f"Question {i}"}], + }, + } + for i in range(100) + ] +) + +# Poll for completion +import time +while batch.processing_status not in ("ended", "canceled", "expired"): + time.sleep(60) + batch = client.messages.batches.retrieve(batch.id) + +# Stream results +for result in client.messages.batches.results(batch.id): + print(result.custom_id, result.result) +``` + +### Constraints + +- Max 100,000 requests per batch +- Results available for 29 days +- Cost: 50% of normal Messages API pricing +- Async-only, no real-time response + +--- + +## Files API + +Upload files for use across multiple requests without re-uploading. + +### Constraints + +- Max file size: 500MB +- Max total storage per organization: 100GB +- Supported types: PDF, images (PNG, JPEG, GIF, WebP), text files + +### Python Example + +```python +# Upload a file +with open("document.pdf", "rb") as f: + file = client.files.create(file=f, purpose="user_data") + +# Reference in a message +response = client.messages.create( + model="claude-opus-4-7", + max_tokens=1024, + messages=[ + { + "role": "user", + "content": [ + {"type": "document", "source": {"type": "file", "file_id": file.id}}, + {"type": "text", "text": "Summarize this document"}, + ], + } + ], +) + +# Delete when done +client.files.delete(file.id) +``` + +--- + +## Streaming + +### Python — Iterating Events + +```python +with client.messages.stream( + model="claude-opus-4-7", + max_tokens=4096, + messages=[{"role": "user", "content": "Write a story"}], +) as stream: + for text in stream.text_stream: + print(text, end="", flush=True) + + # Or get the final message after streaming + final = stream.get_final_message() +``` + +### Python — Lower-level Events + +```python +with client.messages.stream(...) as stream: + for event in stream: + if event.type == "content_block_start": + ... + elif event.type == "content_block_delta": + if event.delta.type == "text_delta": + print(event.delta.text, end="") + elif event.delta.type == "thinking_delta": + # Streaming thinking content (if display="summarized") + ... + elif event.type == "message_stop": + ... +``` + +### When to Use Streaming + +- **Long output**: Stream so users see progress, not a long wait +- **Long input**: Avoid client-side timeouts +- **High `max_tokens`**: Server may return SSE-only above some threshold +- **Real-time UX**: Show tokens as they're generated + +--- + +## Structured Outputs + +Constrain Claude's output to match a JSON schema. + +### Python — `messages.parse()` (Recommended) + +```python +from pydantic import BaseModel + +class WeatherReport(BaseModel): + location: str + temperature_c: float + conditions: str + +response = client.messages.parse( + model="claude-opus-4-7", + max_tokens=1024, + messages=[{"role": "user", "content": "Weather in Paris?"}], + response_format=WeatherReport, +) + +# Validated, typed result +report: WeatherReport = response.parsed +print(report.location, report.temperature_c) +``` + +### Strict Tool Parameters + +For tools, pass `strict: true` to enforce schema: + +```python +tools = [ + { + "name": "create_user", + "description": "Create a new user", + "input_schema": { + "type": "object", + "properties": { + "name": {"type": "string"}, + "age": {"type": "integer", "minimum": 0}, + }, + "required": ["name", "age"], + }, + "strict": True, # Enforce strict schema matching + } +] +``` + +### Using `output_config.format` + +```python +response = client.messages.create( + model="claude-opus-4-7", + max_tokens=1024, + output_config={ + "format": { + "type": "json_schema", + "schema": { + "type": "object", + "properties": {...}, + "required": [...], + }, + } + }, + messages=[...], +) +``` + +The old `output_format` parameter is deprecated; use `output_config: {format: {...}}`. + +--- + +## Model Migration + +### Migrating to Opus 4.7 — Breaking Changes + +1. **`budget_tokens` no longer accepted.** Replace `thinking: {type: "enabled", budget_tokens: N}` with `thinking: {type: "adaptive"}`. The old form returns a 400. + +2. **Sampling parameters removed.** `temperature`, `top_p`, `top_k` are gone. They return a 400. The model is deterministic-by-default with adaptive thinking. + +3. **Thinking content omitted by default.** `thinking` blocks stream but their text is empty. Opt in with `thinking: {type: "adaptive", display: "summarized"}`. + +4. **Effort parameter expanded.** New `"xhigh"` level between `high` and `max`. Re-tune effort when migrating from 4.6 — `xhigh` is the new sweet spot for coding/agentic. + +5. **Task Budgets (beta).** New feature: `output_config: {task_budget: {type: "tokens", total: N}}` with beta header `task-budgets-2026-03-13`. + +### Migrating to Opus 4.6 — Breaking Changes + +1. **`budget_tokens` is deprecated** but still functional as a transitional escape hatch. Prefer `thinking: {type: "adaptive"}`. + +2. **Interleaved thinking is automatic** with adaptive thinking. No beta header needed. + +3. **Effort parameter is GA.** Use `output_config: {effort: "high"}` etc. + +### Migration Workflow + +1. **Confirm scope**: Ask which files/directories to migrate before any edit. +2. **Classify each file**: What model is it currently using? What features does it use? +3. **Apply per-target breaking changes**: Use the breaking-changes section for the target model. +4. **Test**: Run the code, verify behavior matches expectations. Effort/thinking changes can affect output quality, so re-test thoroughly. + +### Transitional Escape Hatch (Opus 4.6, Sonnet 4.6 only) + +`budget_tokens` is still functional on Opus 4.6 and Sonnet 4.6 as a transitional escape hatch. If you're migrating existing code and need a hard token ceiling before you've tuned `effort`, keep `budget_tokens` temporarily. Does NOT apply to Opus 4.7 — `budget_tokens` is fully removed there. + +--- + +## Error Handling + +### Common HTTP Status Codes + +| Code | Meaning | Action | +| ---- | ------- | ------ | +| 400 | Invalid request (bad params, schema, model) | Fix the request — don't retry | +| 401 | Invalid API key | Check `ANTHROPIC_API_KEY` |