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,
}}},
)