Anthropic Claude SDK
The Anthropic Python SDK calls Claude models via the Messages API. It supports streaming, tool use, vision, and structured outputs for production LLM applications.
Recipe
Quick-reference recipe card - copy-paste ready.
import anthropic
client = anthropic.Anthropic()
message = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
system="You are a helpful assistant.",
messages=[{"role": "user", "content": "Hello!"}],
)
print(message.content[0].text)When to reach for this:
- Building applications on Claude models (Sonnet, Haiku, Opus).
- Streaming long responses to users in real time.
- Giving Claude access to tools (search, database, APIs).
- Processing images or documents with Claude's vision capability.
Working Example
"""anthropic_claude_sdk.py - messages, streaming, and tool use."""
from __future__ import annotations
import json
import anthropic
client = anthropic.Anthropic()
# Basic message
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=512,
system="You are a Python code reviewer. Be concise.",
messages=[{"role": "user", "content": "Review: def add(a,b): return a+b"}],
)
print(response.content[0].text)
# Streaming
print("--- streaming ---")
with client.messages.stream(
model="claude-sonnet-4-20250514",
max_tokens=256,
messages=[{"role": "user", "content": "Count from 1 to 5."}],
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)
print()
# Tool use
tools = [{
"name": "get_weather",
"description": "Get weather for a city",
"input_schema": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
},
}]
def get_weather(city: str) -> str:
return json.dumps({"city": city, "temp_f": 72, "condition": "sunny"})
msg = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
tools=tools,
messages=[{"role": "user", "content": "What's the weather in Austin?"}],
)
while msg.stop_reason == "tool_use":
tool_results = []
for block in msg.content:
if block.type == "tool_use":
result = get_weather(**block.input)
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": result,
})
msg = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
tools=tools,
messages=[
{"role": "user", "content": "What's the weather in Austin?"},
{"role": "assistant", "content": msg.content},
{"role": "user", "content": tool_results},
],
)
print(msg.content[0].text)What this demonstrates:
- Basic synchronous message creation.
- Streaming with
messages.streamandtext_stream. - Tool definition with JSON schema and tool-use loop.
- Multi-turn tool result submission back to Claude.
Deep Dive
How It Works
- Messages API accepts
system,messages, and optionaltools. - Content blocks are typed:
text,tool_use,tool_result,image. - stop_reason indicates why generation ended:
end_turn,tool_use,max_tokens. - Streaming emits events;
text_streamyields only text deltas. - Token counting via
client.messages.count_tokens()before sending.
Model Tiers
| Model | Speed | Capability | Use |
|---|---|---|---|
| Haiku | Fastest | Basic tasks | Classification, extraction |
| Sonnet | Balanced | Strong reasoning | General applications |
| Opus | Slowest | Best quality | Complex analysis, coding |
Python Notes
# Async client
import asyncio
import anthropic
async def main():
client = anthropic.AsyncAnthropic()
msg = await client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=256,
messages=[{"role": "user", "content": "Hi"}],
)
print(msg.content[0].text)
asyncio.run(main())Gotchas
- Missing max_tokens - API requires
max_tokens; requests fail without it. Fix: always setmax_tokensexplicitly. - Tool loop not implemented - Claude returns
tool_usebut code does not handle it. Fix: checkstop_reasonand submittool_resultblocks. - Hardcoded API key - security risk in source code. Fix:
anthropic.Anthropic()readsANTHROPIC_API_KEYfrom environment. - Not handling rate limits - 429 errors crash the app. Fix: exponential backoff retry with
tenacityor SDK retry config. - Ignoring token limits - long conversations exceed context window. Fix: trim old messages or summarize history.
- Wrong content block access - assuming all blocks are text. Fix: check
block.typebefore accessing.text.
Alternatives
| Alternative | Use When | Don't Use When |
|---|---|---|
| Anthropic SDK | Claude models | Need OpenAI ecosystem |
| OpenAI SDK | GPT models, wider tooling | Prefer Claude's safety/style |
| LiteLLM | Multi-provider abstraction | Single-provider simplicity |
| AWS Bedrock | Claude via AWS IAM | Direct API is simpler |
FAQs
How do I set the API key?
export ANTHROPIC_API_KEY="sk-ant-..."- Or pass
api_key=to the constructor. - Never commit keys to git.
What is the tool use loop?
- Send user message with tools defined.
- If
stop_reason == "tool_use", execute the tool. - Send tool results back as a user message.
- Repeat until
stop_reason == "end_turn".
How do I stream responses?
with client.messages.stream(...) as stream:
for text in stream.text_stream:
print(text, end="")- Use async streaming for web servers.
Can Claude read images?
{"role": "user", "content": [
{"type": "image", "source": {"type": "base64", "media_type": "image/png", "data": b64}},
{"type": "text", "text": "What is in this image?"},
]}How do I count tokens?
count = client.messages.count_tokens(
model="claude-sonnet-4-20250514",
messages=[{"role": "user", "content": "Hello"}],
)
print(count.input_tokens)What is extended thinking?
- Some Claude models support a thinking block before the answer.
- Useful for complex reasoning tasks.
- Check model documentation for availability.
How do I handle errors?
import anthropic
try:
client.messages.create(...)
except anthropic.RateLimitError:
time.sleep(5) # backoff
except anthropic.APIStatusError as e:
print(e.status_code, e.message)System prompt vs first user message?
systemparameter is the dedicated system prompt.- Cleaner than embedding instructions in user messages.
How do I use Claude with FastAPI?
- Use
AsyncAnthropicin async route handlers. - Stream with
StreamingResponsefor SSE to clients.
What models are available?
- Check https://docs.anthropic.com for current model IDs.
- Model names include version dates (e.g.,
claude-sonnet-4-20250514).
How do I reduce costs?
- Use Haiku for simple tasks.
- Set appropriate
max_tokens. - Cache repeated system prompts where supported.
Can I get JSON output?
- Instruct Claude to respond in JSON in the system prompt.
- Use tool use with a schema for guaranteed structure.
- See Structured Output.
Related
- OpenAI & Other SDKs - provider comparison
- Tool Use & Function Calling - tool patterns
- Streaming & Async LLM Calls - async streaming
- Prompt Engineering - system prompts
- Tokens, Cost & Rate Limits - budgeting
Stack versions: This page was written for Python 3.14.0 (stable 3.14, maintenance 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, and uv 0.6+.