Claude API —
Developer guide
Python SDK, Tool Use, Extended Thinking, Vision, building an MCP Server and smart agents — with detailed code examples.
Two separate guides — choose by what you need:
First installation — Python SDK
Anthropic provides an official SDK for Python and TypeScript. Installation is simple and requires an API Key from console.anthropic.com.
pip install anthropic
import anthropic
client = anthropic.Anthropic(api_key="YOUR_API_KEY")
# recommended: ANTHROPIC_API_KEY as an env variable, then you can omit api_key=
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[
{"role": "user", "content": "Hello! What can you do?"}
]
)
print(message.content[0].text)
Never write an API Key directly in code. UseANTHROPIC_API_KEY as an environment variable: export ANTHROPIC_API_KEY="sk-ant-..." or a .env with python-dotenv.
The models — April 2026
| Model | Input / Output | Context | Recommended for |
|---|---|---|---|
| claude-sonnet-4-6 | $3 / $15 | 1M | Default — most uses |
| claude-opus-4-6 | $5 / $25 | 1M | Complex tasks, Agent Teams |
| claude-haiku-4-5 | $1 / $5 | 1M | High volume, low latency, drafts |
System Prompts
The System Prompt is the instruction sent before every conversation that defines the model's "personality", output format, and boundaries. In Claude this works especially strongly thanks to Constitutional AI.
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
system="""You are an expert in financial data analysis.
Always answer in the format: key figure → meaning → recommendation.
If information is missing — ask before you guess.
Language: English only.""",
messages=[
{"role": "user", "content": "Analyze the following data: ..."}
]
)
XML Tags — Anthropic's preferred technique
Claude responds excellently to XML structure within the prompt. Anthropic officially recommends this for complex prompts:
system_prompt = """
<role>You are a legal assistant that helps startups.</role>
<instructions>
- Answer only legal questions related to startups
- Always add a disclaimer: "This is not binding legal advice"
- If you're unsure — say so explicitly
</instructions>
<output_format>
1. A direct answer
2. A short explanation
3. A recommendation for action
</output_format>
"""
Tool Use (Function Calling)
Tool Use lets Claude "call functions" you define — search the web, pull data from a DB, send emails, and anything else. The model decides when to call a tool and what to send it.
tools = [
{
"name": "get_weather",
"description": "Returns the current weather for a given city",
"input_schema": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "the city name, e.g. 'Tel Aviv'"
},
"units": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "temperature units"
}
},
"required": ["city"]
}
}
]
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
tools=tools,
messages=[{"role": "user", "content": "What is the weather in Tel Aviv right now?"}]
)
# Claude returns a tool_use block
if response.stop_reason == "tool_use":
tool_call = next(b for b in response.content if b.type == "tool_use")
print(f"Tool call: {tool_call.name}")
print(f"Input: {tool_call.input}")
# here you run the actual function and return a result
Tool Use requires a loop: send a request → get tool_use → run the function → send the result → get a final answer. After receiving the tool_use, add a message role: "user" with type: "tool_result" and tool_use_id.
Extended Thinking
Extended Thinking lets Claude "think out loud" before answering — it generates hidden thinking tokens that dramatically improve answers to complex problems: math, logic, hard code.
response = client.messages.create(
model="claude-opus-4-6", # Thinking is recommended with Opus
max_tokens=16000,
thinking={
"type": "enabled",
"budget_tokens": 10000 # how many tokens for "thinking" — up to 10K recommended
},
messages=[{
"role": "user",
"content": "Solve the following problem step by step: ..."
}]
)
for block in response.content:
if block.type == "thinking":
print("Internal thinking:", block.thinking[:200], "...")
elif block.type == "text":
print("Answer:", block.text)
Suited to problems requiring multi-step reasoning: complex algorithms, business analysis, multi-variable decisions. It costs more — use it wisely.
Vision — analyzing images and documents
Claude can analyze images, screenshots, PDFs and charts — send base64 or a direct URL.
import base64
from pathlib import Path
# reading a local image
img_data = base64.standard_b64encode(Path("chart.png").read_bytes()).decode()
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[{
"role": "user",
"content": [
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/png",
"data": img_data
}
},
{
"type": "text",
"text": "Analyze the chart: what is the trend? Which outliers stand out?"
}
]
}]
)
print(response.content[0].text)
Building an MCP Server
MCP (Model Context Protocol) lets you connect Claude to external tools. When you build an MCP Server, any compatible MCP client (including claude.ai, Claude Code, Cursor) can use it.
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp import types
app = Server("my-tool-server")
@app.list_tools()
async def list_tools() -> list[types.Tool]:
return [
types.Tool(
name="search_db",
description="Searches records in the database by a query",
inputSchema={
"type": "object",
"properties": {
"query": {"type": "string", "description": "the search query"}
},
"required": ["query"]
}
)
]
@app.call_tool()
async def call_tool(name: str, arguments: dict) -> list[types.TextContent]:
if name == "search_db":
results = await db.search(arguments["query"]) # your logic here
return [types.TextContent(type="text", text=str(results))]
async def main():
async with stdio_server() as streams:
await app.run(*streams, app.create_initialization_options())
if __name__ == "__main__":
import asyncio
asyncio.run(main())
pip install mcp — Anthropic's official SDK for MCP. After building the server, register it in claude_desktop_config.json to connect it to the Claude Desktop interface.
AI Agents with Claude
An Agent is a loop where Claude receives a task, decides on actions (Tool Use), runs them, and uses the results to continue — until the task is complete.
def run_agent(task: str, tools: list, max_iterations: int = 10) -> str:
messages = [{"role": "user", "content": task}]
for i in range(max_iterations):
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=4096,
tools=tools,
messages=messages
)
# add Claude's response to the history
messages.append({"role": "assistant", "content": response.content})
if response.stop_reason == "end_turn":
# finished — return the final text
return next(b.text for b in response.content if hasattr(b, "text"))
if response.stop_reason == "tool_use":
tool_results = []
for block in response.content:
if block.type == "tool_use":
result = execute_tool(block.name, block.input) # your logic
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": str(result)
})
messages.append({"role": "user", "content": tool_results})
return "Reached the iterations limit"
Anthropic provides an official claude-agent SDK with built-in support for Tool Use, Memory, and Multi-agent orchestration. It simplifies writing the agent loop.
Multiple agents with Claude Opus as the Orchestrator and Sonnet/Haiku as Subagents — Opus decides what to do, the agents execute. Saves costs and improves quality.
Cheat sheet — Claude API
Up-to-date Model IDs
| Model ID | Strength | Thinking | Cost |
|---|---|---|---|
| claude-sonnet-4-6 | Balanced | ✓ | $$ |
| claude-opus-4-6 | Strongest | ✓ | $$$ |
| claude-haiku-4-5-20251001 | Fastest | — | $ |
Common errors and solutions
Prompt Caching — savings of up to 90%
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
system=[{
"type": "text",
"text": "A long document used in all the calls...",
"cache_control": {"type": "ephemeral"} # ← stores this in the cache
}],
messages=[{"role": "user", "content": "A question about the document"}]
)
# the first call writes to the cache, the rest of the calls are 90% cheaper
Ready to build?
Get an API Key from console.anthropic.com, install the SDK, and start with the examples from the guide.