Overview
The anthropic Python package wraps the Messages API with typed requests, streaming helpers, and automatic retries. This guide installs it, sends a first request, turns on adaptive thinking, streams, and runs a tool-use loop. Model choice and prompt design are covered in prompt-design and cost-control; Claude Agent SDK users want claude-agent-sdk (Python) or @anthropic-ai/claude-agent-sdk (TypeScript) instead.
Prerequisites
- Python 3.10 or newer, in a virtual environment (
python -m venv .venv && source .venv/bin/activate). - An API key from the Anthropic Console in
ANTHROPIC_API_KEY. Never hardcode it.
Steps
1. Install and create the client
pip install anthropicimport json
import anthropic
client = anthropic.Anthropic() # reads ANTHROPIC_API_KEYThe constructor does not validate the key. A missing key raises TypeError: Could not resolve authentication method on the first request, and a wrong key raises anthropic.AuthenticationError.
2. Send a request
def text_of(message):
return "".join(b.text for b in message.content if b.type == "text")
message = client.messages.create(
model="claude-sonnet-5-5",
max_tokens=1024,
system="You are a concise technical writer. Reply in plain text.",
messages=[{"role": "user", "content": "Explain HNSW indexing in two sentences."}],
)
print(text_of(message), message.stop_reason, message.usage)Read text blocks by type, not by content[0]: responses can start with a thinking block. Current model IDs have no date suffix (claude-sonnet-5-5, claude-opus-5-5, claude-fable-5-1, claude-haiku-5-5). Details to know:
- Opus 4.7 and later, Sonnet 5.x, Haiku 5.5, and Fable 5.x reject non-default
temperature,top_p, andtop_kvalues with a 400. Omit them and steer with instructions instead. - Prefilling the assistant turn returns 400 on 4.6 and later models. For fixed-format output use structured outputs (below and structured-output).
max_tokensis a ceiling on thinking plus reply text combined; a reply cut off at it hasstop_reason == "max_tokens". Raise it, or lower the effort level, when thinking uses the budget.
Structured outputs go in output_config.format (the top-level output_format is deprecated):
message = client.messages.create(
model="claude-sonnet-5-5",
max_tokens=1024,
output_config={"format": {"type": "json_schema", "schema": {
"type": "object",
"properties": {"summary": {"type": "string"}},
"required": ["summary"],
"additionalProperties": False,
}}},
messages=[{"role": "user", "content": "Summarize HNSW in one sentence."}],
)
data = json.loads(text_of(message))3. Use adaptive thinking
message = client.messages.create(
model="claude-sonnet-5-5",
max_tokens=4096,
thinking={"type": "adaptive"},
output_config={"effort": "medium"}, # low | medium | high | xhigh | max
messages=[{"role": "user", "content": "Plan a zero-downtime column rename in Postgres."}],
)budget_tokens returns 400 on Opus 4.7 and later, Sonnet 5.x, Haiku 5.5, and Fable 5.x, and is deprecated on Opus and Sonnet 4.6; adaptive thinking plus an effort level replaces it. The previous-generation Haiku 4.5 and older still use thinking={"type": "enabled", "budget_tokens": N}.
Opus 5.5, Sonnet 5.5, and Fable 5.x think adaptively by default, and thinking={"type": "disabled"} returns 400 on them. To switch up-front thinking off on Sonnet 5.5, send thinking={"type": "between_tools"} at effort high or below; on Opus 5.5 and Fable 5.x there is no off switch, so omit the parameter. Opus 5 accepts disabled only at effort high or below. The default effort is medium on Opus 5.5 and Haiku 5.5 and high on most other models.
4. Stream
with client.messages.stream(
model="claude-sonnet-5-5",
max_tokens=1024,
messages=[{"role": "user", "content": "List five Postgres performance tips."}],
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)
final = stream.get_final_message() # includes usage5. Run a tool-use loop
Define the tool with strict: True so the model’s input always matches the schema. Do not force a tool with tool_choice of any or tool; Fable 5.1, Opus 5.5, and Sonnet 5.5 return 400. Leave it on auto.
tools = [{
"name": "get_weather",
"description": "Return the current temperature for a city.",
"strict": True,
"input_schema": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
"additionalProperties": False,
},
}]
messages = [{"role": "user", "content": "What is the weather in Tokyo?"}]
while True:
resp = client.messages.create(model="claude-sonnet-5-5", max_tokens=1024, tools=tools, messages=messages)
if resp.stop_reason != "tool_use":
break
messages.append({"role": "assistant", "content": resp.content}) # keep thinking blocks intact
results = [
{"type": "tool_result", "tool_use_id": b.id, "content": '{"temperature": 22, "unit": "celsius"}'}
for b in resp.content if b.type == "tool_use" # call your real function here
]
messages.append({"role": "user", "content": results})
print(text_of(resp))Return every tool_result from one assistant turn in a single user message, with each tool_use_id copied from its call.
Verify it worked
msg = client.messages.create(model="claude-haiku-5-5", max_tokens=1024,
output_config={"effort": "low"}, # Haiku 5.5 thinks by default; thinking counts toward max_tokens
messages=[{"role": "user", "content": "Reply with the word OK only."}])
assert text_of(msg).strip() == "OK" and msg.usage.output_tokens > 0Common errors
anthropic.AuthenticationError. The key is invalid or revoked; confirm the variable is set with[ -n "$ANTHROPIC_API_KEY" ] && echo set, then create a new key in the Console.anthropic.RateLimitError. The SDK retries 429s automatically with backoff; reduce concurrency if it persists. See cost-control.BadRequestErrormentioningtemperatureorbudget_tokens. The model no longer accepts it; remove the parameter.BadRequestErroron prefill or forcedtool_choice. Remove the assistant prefill; switch toautowith strict tools.- A tool result is rejected. Its
tool_use_iddoes not match a call in the previous assistant turn.
FAQ
Can I set temperature on claude-sonnet-5-5?
No; Opus 4.7 and later, Sonnet 5.x, Haiku 5.5, and Fable 5.x reject non-default temperature, top_p, and top_k values with a 400, so omit them and steer with instructions.
How do I turn off thinking on Sonnet 5.5?
thinking={"type": "disabled"} returns 400 on Sonnet 5.5; send thinking={"type": "between_tools"} at effort high or below instead.
Can I force a tool call with tool_choice on Fable 5.1, Opus 5.5, or Sonnet 5.5?
No; they return 400 for tool_choice of any or tool, so leave it on auto and define tools with strict: True. Haiku 5.5 accepts a forced tool_choice, and its response then starts with the tool call and has no thinking block.