Claude API cheatsheet

Claude API: Tools and structured output

6 common Claude API tasks.

Let the SDK run the tool loop

Decorate Python functions with @beta_tool and the tool runner calls them and feeds results back until Claude is done. The docstring describes the tool to Claude.

from anthropic import beta_tool

@beta_tool
def get_weather(location: str, unit: str = "celsius") -> str:
    """Get current weather for a location.

    Args:
        location: City and state, e.g., San Francisco, CA.
        unit: Temperature unit, either "celsius" or "fahrenheit".
    """
    return f"72°F and sunny in {location}"

runner = client.beta.messages.tool_runner(
    model="claude-opus-5-5",
    max_tokens=16000,
    tools=[get_weather],
    messages=[{"role": "user", "content": "What's the weather in Paris?"}],
)
for message in runner:
    print(message)

Define a tool by hand

A tool has a name, a description and a JSON Schema for its input. Claude replies with a tool_use block when it wants to call it.

tools = [{
    "name": "get_weather",
    "description": "Get the current weather for a city.",
    "input_schema": {
        "type": "object",
        "properties": {"city": {"type": "string"}},
        "required": ["city"],
    },
}]

Return a tool result

Run the tool, then send its output back in a user message whose tool_use_id matches. Return all results for parallel calls in one message.

tool_use = next(b for b in response.content if b.type == "tool_use")
result = run_tool(tool_use.name, tool_use.input)   # your code

messages.append({"role": "assistant", "content": response.content})
messages.append({"role": "user", "content": [
    {"type": "tool_result", "tool_use_id": tool_use.id, "content": result},
]})

Guarantee valid tool input

Set strict: true on a tool so its input always matches the schema. The schema needs additionalProperties: false and required.

tools = [{**tool, "strict": True} for tool in tools]

Get a validated Python object back

Pass a Pydantic class as output_format and read the parsed object. The response is guaranteed to match the schema.

from pydantic import BaseModel

class ContactInfo(BaseModel):
    name: str
    email: str
    interests: list[str]

response = client.messages.parse(
    model="claude-opus-5-5",
    max_tokens=16000,
    messages=[{"role": "user", "content": "Extract: Jane Doe ([email protected]) likes APIs and SDKs."}],
    output_format=ContactInfo,
)
contact = response.parsed_output

Constrain output with a JSON Schema

Use output_config.format when you want raw JSON that follows your schema.

response = client.messages.create(
    model="claude-opus-5-5",
    max_tokens=16000,
    messages=[{"role": "user", "content": "Extract the name from: John Smith wants the Enterprise plan."}],
    output_config={"format": {"type": "json_schema", "schema": {
        "type": "object",
        "properties": {"name": {"type": "string"}},
        "required": ["name"],
        "additionalProperties": False,
    }}},
)

Was this page helpful?