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 anthropic
import json
import anthropic
 
client = anthropic.Anthropic()   # reads ANTHROPIC_API_KEY

The 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, and top_k values 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_tokens is a ceiling on thinking plus reply text combined; a reply cut off at it has stop_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 usage

5. 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 > 0

Common 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.
  • BadRequestError mentioning temperature or budget_tokens. The model no longer accepts it; remove the parameter.
  • BadRequestError on prefill or forced tool_choice. Remove the assistant prefill; switch to auto with strict tools.
  • A tool result is rejected. Its tool_use_id does 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.