KI-Agent erstellen mit Python: Claude Agent SDK Schritt für Schritt
KI-Agent erstellen, der selbst Code liest und repariert: Claude Agent SDK installieren, ersten Agenten schreiben, eigenes Tool und MCP hinzufügen.
Dieser Artikel in anderen Sprachen:العربيةEnglishEspañolFrançaisItaliano日本語Polski简体中文
In diesem Artikel
- Was ist ein KI-Agent aus Sicht eines Entwicklers?
- Schritt 1: Wie installiert man das Claude Agent SDK?
- Schritt 2: Wie setzt man den API-Schlüssel?
- Schritt 3: Wie schreibt man den ersten KI-Agenten?
- Schritt 4: Wie legt man fest, was der Agent selbst tun darf?
- Schritt 5: Wie gibt man dem Agenten ein eigenes Tool?
- Schritt 6: Wie verbindet man den Agenten mit einem MCP-Server?
- Wie geht es nach dem ersten Agenten weiter?
- Worauf sollte man achten?
- FAQ
Wie kann man einen KI-Agenten erstellen, ohne die ganze Schleife von Grund auf zu schreiben? Der kürzeste Weg, den ich kenne, ist das Claude Agent SDK, eine Bibliothek für Python und TypeScript, die uns dieselben Tools, dieselbe Agentenschleife und dasselbe Kontextmanagement gibt, auf denen Claude Code läuft. Wir schreiben ein Dutzend Zeilen Code, und der Agent liest selbst Dateien, behebt Fehler und führt Befehle aus.
In dieser Anleitung bauen wir einen ersten Agenten in Python, legen seine Berechtigungen fest und fügen ein eigenes Tool und einen MCP-Server hinzu. Alle Befehle und Codebeispiele stammen aus dem offiziellen Agent-SDK-Quickstart und den Dokumentationsseiten, die ich unterwegs verlinke.
Was ist ein KI-Agent aus Sicht eines Entwicklers?
Laut Dokumentation ist ein Agent eine Anwendung, die eine Aufgabe erledigt, indem sie ihre nächsten Schritte selbst plant und Tools aufruft: Sie liest Dateien, führt Befehle aus oder bearbeitet Code. Das Gesamtbild ohne Code habe ich in Was ist ein KI-Agent beschrieben.
Für Entwickler ist die Schleife entscheidend: Das Modell denkt nach, ruft ein Tool auf, schaut sich das Ergebnis an und entscheidet, was als Nächstes kommt. Das Agent SDK übernimmt diese Schleife, die Ausführung der Tools, das Kontextmanagement und die Wiederholungsversuche, und wir lesen nur den Nachrichtenstrom.
Die Dokumentation unterscheidet dabei vier Arten, mit Claude zu arbeiten:
- Agent SDK, eine Bibliothek, die den Claude-Code-Agenten in unserer Anwendung ausführt (in einem Prozess, den wir selbst verwalten),
- Claude Code CLI, das Terminal für die tägliche, interaktive Arbeit (dazu gibt es meine Claude-Code-Anleitung),
- Client SDK, direkter Zugriff auf die Claude API, bei dem wir die Tool-Schleife selbst schreiben (oder sie dem „Tool Runner“ in der Beta überlassen),
- Managed Agents, ein von Anthropic gehosteter Agent, der über die API konfiguriert wird.
Diese Anleitung behandelt die erste Option.
Schritt 1: Wie installiert man das Claude Agent SDK?
Wir brauchen Python 3.10+ (oder Node.js 18.14+ für TypeScript) und ein Konto in der Claude Console. Zuerst legen wir einen Projektordner an:
mkdir my-agent
cd my-agent
Der Agent hat standardmäßig Zugriff auf die Dateien in diesem Verzeichnis und seinen Unterverzeichnissen. Die Dokumentation empfiehlt den Paketmanager uv:
uv init
uv add claude-agent-sdk
Mit normalem pip (macOS und Linux) sieht es so aus:
python3 -m venv .venv
source .venv/bin/activate
pip install claude-agent-sdk
Interessant: Eine separate Installation von Claude Code ist meist nicht nötig, denn beide SDKs bringen eine native Claude-Code-Binärdatei mit. Ausnahmen sind Plattformen ohne fertiges Paket, etwa Windows ARM64 (dann installieren wir Claude Code manuell, und das SDK findet es im PATH).
Schritt 2: Wie setzt man den API-Schlüssel?
Den Schlüssel erstellen wir in der Claude Console und setzen ihn als Umgebungsvariable in dem Terminal, in dem wir den Agenten starten:
export ANTHROPIC_API_KEY=your-api-key
Das SDK lädt .env-Dateien nicht automatisch. Wer den Schlüssel in .env speichert, muss ihn also selbst laden (z. B. mit dem Paket dotenv). Statt eines Anthropic-Schlüssels lassen sich auch Amazon Bedrock, Claude Platform on AWS, Google Cloud oder Microsoft Foundry nutzen, indem man die passende Variable setzt, z. B. CLAUDE_CODE_USE_BEDROCK=1.
Ein Vorbehalt aus der Dokumentation: Ohne vorherige Zustimmung erlaubt Anthropic nicht, dass Produkte auf Basis des Agent SDK einen claude.ai-Login anbieten oder Abo-Limits nutzen. Der Agent läuft mit einem API-Schlüssel, und wir zahlen für Tokens (wie man sie verfolgt, habe ich bei den Claude-API-Kosten beschrieben).
Schritt 3: Wie schreibt man den ersten KI-Agenten?
Das Beispiel aus dem Quickstart ist ein Agent, der Fehler im Code findet und behebt. Zuerst legen wir eine Datei utils.py mit zwei absichtlichen Fehlern an:
def calculate_average(numbers):
total = 0
for num in numbers:
total += num
return total / len(numbers)
def get_user_name(user):
return user["name"].upper()
calculate_average([]) stürzt bei der Division durch null ab, get_user_name(None) mit einem TypeError. Jetzt der eigentliche Agent, die Datei agent.py:
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage, ResultMessage
async def main():
# Agentic loop: streams messages as Claude works
async for message in query(
prompt="Review utils.py for bugs that would cause crashes. Fix any issues you find.",
options=ClaudeAgentOptions(
allowed_tools=["Read", "Edit", "Glob"], # Auto-approve these tools
permission_mode="acceptEdits", # Auto-approve file edits
),
):
# Print human-readable output
if isinstance(message, AssistantMessage):
for block in message.content:
if hasattr(block, "text"):
print(block.text) # Claude's reasoning
elif hasattr(block, "name"):
print(f"Tool: {block.name}") # Tool being called
elif isinstance(message, ResultMessage):
print(f"Done: {message.subtype}") # Final result
asyncio.run(main())
Der Code hat drei Teile:
queryerzeugt die Agentenschleife und gibt einen asynchronen Iterator zurück, also lesen wir die Nachrichten laufend perasync for,promptist die Aufgabe. Claude entscheidet selbst, welche Tools es nutzt,optionsist die Konfiguration: Hier genehmigtallowed_toolsvorabRead,EditundGlob, undpermission_mode="acceptEdits"akzeptiert Dateiänderungen automatisch.
Wir starten ihn:
uv run agent.py
(oder python agent.py in einer aktiven venv). Der Agent gibt seine Überlegungen und jedes aufgerufene Tool aus, am Ende Done: success. Danach behandelt utils.py eine leere Liste und einen fehlenden Benutzer. Der Agent hat die Datei selbst gelesen, die Randfälle gefunden und den Code repariert, und wir haben keine einzige Funktion zur Tool-Behandlung geschrieben.
Bei Not logged in oder Invalid API key ist fast sicher die Variable ANTHROPIC_API_KEY in diesem Terminal nicht gesetzt.
Schritt 4: Wie legt man fest, was der Agent selbst tun darf?
Was der Agent kann, bestimmen die Tools. Die Dokumentation nennt drei typische Sets:
Read,Glob,Grep: nur Analyse, keine Änderungen an Dateien,Read,Edit,Glob: Analyse und Code-Bearbeitung,Read,Edit,Bash,Glob,Grep: volle Automatisierung mit Terminalbefehlen.
Damit der Agent z. B. im Web suchen oder Tests ausführen kann, fügen wir ein Tool hinzu und ändern den Prompt:
options = ClaudeAgentOptions(
allowed_tools=["Read", "Edit", "Glob", "Bash"], permission_mode="acceptEdits"
)
Mit aktiviertem Bash schlägt der Quickstart die Aufgabe „Write unit tests for utils.py, run them, and fix any failures“ vor. Über system_prompt kann man dem Agenten auch eine Rolle geben, etwa die eines erfahrenen Python-Entwicklers, der auf PEP 8 achtet.
Der zweite Hebel ist der Berechtigungsmodus (permission_mode):
"default"leitet jeden nicht genehmigten Aufruf an unsere FunktioncanUseToolweiter und lehnt ab, wenn es keine gibt,"acceptEdits"akzeptiert Dateiänderungen und einfache Befehle wiemkdirodermvim Arbeitsverzeichnis,"plan"lässt den Agenten zuerst den Code untersuchen und einen Plan erstellen,"dontAsk"fragt nie: Es läuft nur, was wir vorab genehmigt haben, der Rest wird abgelehnt (gut für Agenten ohne Mensch an der Tastatur),"auto"schickt Aktionen durch einen Klassifikator, der jede prüft und blockiert oder erlaubt,"bypassPermissions"führt alles ohne Nachfrage aus und gehört laut Dokumentation nur in isolierte Umgebungen wie CI oder Container.
Die goldene Regel aus der Dokumentation: "acceptEdits" auf dem Entwicklerrechner, "bypassPermissions" nur dort, wo der Agent nichts Wichtiges beschädigen kann. Warum das wichtig ist, steht in meiner Anleitung zur Sicherheit von KI-Agenten.
Limits sollte man gleich mit setzen: max_turns begrenzt die Zahl der Runden, und max_budget_usd stoppt die Schleife, sobald die geschätzten Kosten überschritten sind. Ohne sie läuft der Agent, bis er selbst fertig ist, und das kann bei offenen Aufgaben wie „verbessere dieses Projekt“ dauern ;)
Schritt 5: Wie gibt man dem Agenten ein eigenes Tool?
Die eingebauten Tools sind erst der Anfang. Ein eigenes Tool definieren wir mit dem Dekorator @tool (Name, Beschreibung, Eingabeschema und Funktion) und packen es dann in einen MCP-Server, der im selben Prozess läuft. Das Beispiel aus der Dokumentation holt die Temperatur von der Open-Meteo-API, also fügen wir zuerst die Bibliothek httpx hinzu:
uv add httpx
Die Tool-Definition:
from typing import Annotated, Any
import httpx
from claude_agent_sdk import tool, create_sdk_mcp_server
# Define a tool: name, description, input schema, handler
@tool(
"get_temperature",
"Get the current temperature at a location",
{
"latitude": Annotated[float, "Latitude coordinate"],
"longitude": Annotated[float, "Longitude coordinate"],
},
)
async def get_temperature(args: dict[str, Any]) -> dict[str, Any]:
async with httpx.AsyncClient() as client:
response = await client.get(
"https://api.open-meteo.com/v1/forecast",
params={
"latitude": args["latitude"],
"longitude": args["longitude"],
"current": "temperature_2m",
"temperature_unit": "fahrenheit",
},
)
data = response.json()
# Return a content array - Claude sees this as the tool result
return {
"content": [
{
"type": "text",
"text": f"Temperature: {data['current']['temperature_2m']}°F",
}
]
}
# Wrap the tool in an in-process MCP server
weather_server = create_sdk_mcp_server(
name="weather",
version="1.0.0",
tools=[get_temperature],
)
In derselben Datei übergeben wir den Server an den Agenten. Der vollständige Tool-Name hat das Format mcp__{server}__{tool}, und genau der kommt in allowed_tools, damit das Tool ohne Rückfrage läuft:
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage
async def main():
options = ClaudeAgentOptions(
mcp_servers={"weather": weather_server},
allowed_tools=["mcp__weather__get_temperature"],
)
async for message in query(
prompt="What's the temperature in San Francisco?",
options=options,
):
# ResultMessage is the final message after all tool calls complete
if isinstance(message, ResultMessage) and message.subtype == "success":
print(message.result)
asyncio.run(main())
Der Agent ruft unser Tool auf und antwortet auf Basis des Ergebnisses. Statt des Wetters können wir alles anschließen: unsere Datenbank, eine interne API oder ein Skript.
Schritt 6: Wie verbindet man den Agenten mit einem MCP-Server?
Fertige MCP-Server (das Protokoll selbst habe ich in Was ist MCP erklärt) tragen wir in der Option mcp_servers ein. Das Beispiel aus der Dokumentation verbindet den Agenten per HTTP mit dem entfernten Dokumentationsserver von Claude Code:
options = ClaudeAgentOptions(
mcp_servers={
"claude-code-docs": {
"type": "http",
"url": "https://code.claude.com/docs/mcp",
}
},
allowed_tools=["mcp__claude-code-docs__*"],
)
Das Sternchen in allowed_tools genehmigt alle Tools dieses Servers. Mit dem Prompt „Use the docs MCP server to explain what hooks are in Claude Code“ durchsucht der Agent die Dokumentation und liefert eine Antwort.
Wie geht es nach dem ersten Agenten weiter?
Das Agent SDK hat auch die übrigen Funktionen von Claude Code:
- Hooks: eigener Code, der vor oder nach einem Tool-Aufruf läuft,
- Subagenten für abgegrenzte Teilaufgaben,
- Sitzungen: Mit der ID aus
ResultMessage.session_idlässt sich ein Gespräch mit vollem Kontext fortsetzen oder verzweigen, - Skills, Befehle und Gedächtnis, die wie in Claude Code aus dem Verzeichnis
.claude/geladen werden.
Fertige Beispielanwendungen (u. a. ein E-Mail-Assistent und ein Recherche-Agent) liegen im Repository claude-agent-sdk-demos.
Worauf sollte man achten?
Erstens auf die Kosten. Der Kontext wächst mit jeder Runde, und eine große Datei oder ein gesprächiger Befehl kann auf einen Schlag Tausende Tokens verbrauchen. Statische Teile (System-Prompt, Tool-Definitionen) werden automatisch gecacht, aber max_budget_usd sollte man trotzdem vom ersten Tag an setzen (das Limit kann um die Kosten einer Antwort überschritten werden, also lieber etwas Puffer lassen).
Zweitens auf die Berechtigungen. Ein Agent mit Bash und bypassPermissions auf einem normalen Laptop ist eine Einladung für Ärger, also bleibt volle Automatisierung den Containern vorbehalten.
Drittens auf das Branding. Laut Dokumentation darf ein Produkt auf Basis des SDK z. B. „Claude Agent“ oder „
FAQ
Wie kann man einen KI-Agenten erstellen, ohne die Schleife selbst zu schreiben?
Am einfachsten mit einer Bibliothek, die diese Schleife schon hat, z. B. dem Claude Agent SDK. Wir installieren claude-agent-sdk, setzen ANTHROPIC_API_KEY und rufen query() mit einem Prompt und einer Liste erlaubter Tools auf. Den Rest, also Tool-Aufrufe und Kontextmanagement, erledigt das SDK.
Ist das Claude Agent SDK kostenlos?
Die Bibliothek selbst kostet nichts, aber der Agent nutzt die Claude API, also zahlen wir für die verbrauchten Tokens. Ohne Zustimmung von Anthropic lässt er sich nicht an ein claude.ai-Abo anbinden.
Was unterscheidet das Agent SDK von der Claude API?
Beim normalen Client SDK (Claude API) schreiben wir die Tool-Schleife selbst oder nutzen den Tool Runner in der Beta. Das Agent SDK bringt die eingebauten Tools von Claude Code mit (Dateien lesen und bearbeiten, Befehle, Websuche), dazu Berechtigungen, Sitzungen und Hooks.
Kann man den Agenten in TypeScript schreiben?
Ja. Das Paket heißt @anthropic-ai/claude-agent-sdk und braucht Node.js 18.14+. Die Optionen heißen in den Beispielen der Dokumentation genauso wie in Python, nur in camelCase (allowedTools, permissionMode).