Beim Erstellen einer Message kannst du "stream": true setzen, um die Antwort inkrementell mithilfe von Server-Sent Events (SSE) zu streamen.
Die Python- und TypeScript-SDKs bieten mehrere Möglichkeiten für Streaming. Das PHP-SDK stellt Streaming über createStream() bereit. Das Python-SDK ermöglicht sowohl synchrone als auch asynchrone Streams. Details findest du in der Dokumentation des jeweiligen SDKs.
client = anthropic.Anthropic()
with client.messages.stream(
max_tokens=1024,
messages=[{"role": "user", "content": "Hello"}],
model="claude-opus-4-8",
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)Wenn du Text nicht verarbeiten musst, während er eintrifft, bieten die SDKs eine Möglichkeit, Streaming im Hintergrund zu verwenden und dabei das vollständige Message-Objekt zurückzugeben – identisch zu dem, was .create() zurückgibt. Dies ist besonders nützlich für Anfragen mit großen max_tokens-Werten, bei denen die SDKs Streaming erfordern, um HTTP-Timeouts zu vermeiden.
client = anthropic.Anthropic()
with client.messages.stream(
max_tokens=128000,
messages=[{"role": "user", "content": "Write a detailed analysis..."}],
model="claude-opus-4-8",
) as stream:
message = stream.get_final_message()
print(message.content[0].text)Der .stream()-Aufruf hält die HTTP-Verbindung mit Server-Sent Events offen, dann akkumuliert .get_final_message() (Python) bzw. .finalMessage() (TypeScript) alle Events und gibt das vollständige Message-Objekt zurück. In Go rufst du message.Accumulate(event) innerhalb der Stream-Schleife auf, um dasselbe vollständige Message-Objekt zu erstellen. In Java verwendest du MessageAccumulator.create() und rufst accumulator.accumulate(event) für jedes Event auf. In C# wartest du mit await auf die .Aggregate()-Erweiterungsmethode des Streams, um die vollständige Message zu erhalten, oder übergibst einen MessageContentAggregator an .CollectAsync(), um während der Event-Verarbeitung zu aggregieren. In Ruby rufst du .accumulated_message auf dem Stream auf. Im PHP-SDK iterierst du manuell über die Stream-Events, um die Antwort zu akkumulieren.
Jedes Server-Sent Event enthält einen benannten Event-Typ und zugehörige JSON-Daten. Jedes Event verwendet einen SSE-Event-Namen (zum Beispiel event: message_stop) und enthält den passenden Event-type in seinen Daten.
Jeder Stream verwendet den folgenden Event-Ablauf:
message_start: enthält ein Message-Objekt mit leerem content.content_block_start, ein oder mehrere content_block_delta-Events und ein content_block_stop-Event hat. Jeder Content-Block hat einen index, der seinem Index im finalen Message-content-Array entspricht. Eine Ausnahme: Bei serverseitigen Fallback-Antworten kommt an jeder Modellgrenze ein fallback-Content-Block als Paar aus content_block_start und content_block_stop ohne Deltas dazwischen an.message_delta-Events, die Änderungen auf oberster Ebene am finalen Message-Objekt anzeigen.message_stop-Event.Die im usage-Feld des message_delta-Events angezeigten Token-Zahlen sind kumulativ.
Event-Streams können auch eine beliebige Anzahl von ping-Events enthalten.
Die API kann gelegentlich Fehler im Event-Stream senden. Zum Beispiel kannst du in Zeiten hoher Auslastung einen overloaded_error erhalten, der in einem Nicht-Streaming-Kontext normalerweise einem HTTP 529 entsprechen würde:
event: error
data: {"type": "error", "error": {"type": "overloaded_error", "message": "Overloaded"}}Gemäß der Versionierungsrichtlinie können neue Event-Typen hinzugefügt werden, und dein Code sollte unbekannte Event-Typen problemlos verarbeiten können.
Jedes content_block_delta-Event enthält ein delta eines Typs, der den content-Block an einem bestimmten index aktualisiert.
Ein text-Content-Block-Delta sieht so aus:
event: content_block_delta
data: {"type": "content_block_delta","index": 0,"delta": {"type": "text_delta", "text": "ello frien"}}Die Deltas für tool_use-Content-Blöcke entsprechen Aktualisierungen für das input-Feld des Blocks. Um maximale Granularität zu unterstützen, sind die Deltas partielle JSON-Strings, während das finale tool_use.input immer ein Objekt ist.
Du kannst die String-Deltas akkumulieren und das JSON parsen, sobald du ein content_block_stop-Event erhältst, indem du eine Bibliothek wie Pydantic für partielles JSON-Parsing verwendest oder die SDKs nutzt, die Hilfsfunktionen für den Zugriff auf geparste inkrementelle Werte bereitstellen.
Ein tool_use-Content-Block-Delta sieht so aus:
event: content_block_delta
data: {"type": "content_block_delta","index": 1,"delta": {"type": "input_json_delta","partial_json": "{\"location\": \"San Fra"}}}Hinweis: Aktuelle Modelle unterstützen nur das Ausgeben jeweils einer vollständigen Key-Value-Eigenschaft aus input. Daher kann es bei der Verwendung von Tools zu Verzögerungen zwischen Streaming-Events kommen, während das Modell arbeitet. Sobald ein input-Key und -Value akkumuliert sind, werden sie als mehrere content_block_delta-Events mit aufgeteiltem partiellem JSON ausgegeben, sodass das Format in zukünftigen Modellen automatisch eine feinere Granularität unterstützen kann.
Wenn du erweitertes Denken mit aktiviertem Streaming verwendest, erhältst du Thinking-Inhalte über thinking_delta-Events. Diese Deltas entsprechen dem thinking-Feld der thinking-Content-Blöcke.
Für Thinking-Inhalte wird ein spezielles signature_delta-Event direkt vor dem content_block_stop-Event gesendet. Diese Signatur wird verwendet, um die Integrität des Thinking-Blocks zu verifizieren.
Wenn display: "omitted" in der Thinking-Konfiguration gesetzt ist, werden keine thinking_delta-Events gesendet. Der Thinking-Block wird geöffnet, erhält ein einzelnes signature_delta und wird geschlossen. Siehe Steuerung der Thinking-Anzeige.
Ein typisches Thinking-Delta sieht so aus:
event: content_block_delta
data: {"type": "content_block_delta", "index": 0, "delta": {"type": "thinking_delta", "thinking": "I need to find the GCD of 1071 and 462 using the Euclidean algorithm.\n\n1071 = 2 × 462 + 147"}}Das Signature-Delta sieht so aus:
event: content_block_delta
data: {"type": "content_block_delta", "index": 0, "delta": {"type": "signature_delta", "signature": "EqQBCgIYAhIM1gbcDa9GJwZA2b3hGgxBdjrkzLoky3dl1pkiMOYds..."}}Verwende die Client-SDKs, wenn du den Streaming-Modus nutzt. Wenn du jedoch eine direkte API-Integration erstellst, musst du diese Events selbst verarbeiten.
Eine Stream-Antwort besteht aus:
message_start-Eventcontent_block_start-Eventcontent_block_delta-Eventscontent_block_stop-Eventmessage_delta-Eventsmessage_stop-EventEs können auch ping-Events über die gesamte Antwort verteilt sein. Siehe Event-Typen für weitere Details zum Format.
client = anthropic.Anthropic()
with client.messages.stream(
model="claude-opus-4-8",
messages=[{"role": "user", "content": "Hello"}],
max_tokens=256,
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)event: message_start
data: {"type": "message_start", "message": {"id": "msg_1nZdL29xx5MUA1yADyHTEsnR8uuvGzszyY", "type": "message", "role": "assistant", "content": [], "model": "claude-opus-4-8", "stop_reason": null, "stop_sequence": null, "usage": {"input_tokens": 25, "output_tokens": 1}}}
event: content_block_start
data: {"type": "content_block_start", "index": 0, "content_block": {"type": "text", "text": ""}}
event: ping
data: {"type": "ping"}
event: content_block_delta
data: {"type": "content_block_delta", "index": 0, "delta": {"type": "text_delta", "text": "Hello"}}
event: content_block_delta
data: {"type": "content_block_delta", "index": 0, "delta": {"type": "text_delta", "text": "!"}}
event: content_block_stop
data: {"type": "content_block_stop", "index": 0}
event: message_delta
data: {"type": "message_delta", "delta": {"stop_reason": "end_turn", "stop_sequence":null}, "usage": {"output_tokens": 15}}
event: message_stop
data: {"type": "message_stop"}
Tool-Nutzung unterstützt feingranulares Streaming für Parameterwerte. Aktiviere es pro Tool mit eager_input_streaming.
Diese Anfrage bittet Claude, ein Tool zu verwenden, um das Wetter zu melden.
client = anthropic.Anthropic()
tools = [
{
"name": "get_weather",
"description": "Get the current weather in a given location",
"input_schema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA",
}
},
"required": ["location"],
},
}
]
with client.messages.stream(
model="claude-opus-4-8",
max_tokens=1024,
tools=tools,
tool_choice={"type": "any"},
messages=[
{"role": "user", "content": "What is the weather like in San Francisco?"}
],
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)event: message_start
data: {"type":"message_start","message":{"id":"msg_014p7gG3wDgGV9EUtLvnow3U","type":"message","role":"assistant","model":"claude-opus-4-8","stop_sequence":null,"usage":{"input_tokens":472,"output_tokens":2},"content":[],"stop_reason":null}}
event: content_block_start
data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}}
event: ping
data: {"type": "ping"}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Okay"}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":","}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" let"}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"'s"}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" check"}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" the"}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" weather"}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" for"}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" San"}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Francisco"}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":","}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" CA"}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":":"}}
event: content_block_stop
data: {"type":"content_block_stop","index":0}
event: content_block_start
data: {"type":"content_block_start","index":1,"content_block":{"type":"tool_use","id":"toolu_01T1x1fJ34qAmk2tNTrN7Up6","name":"get_weather","input":{}}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":""}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"{\"location\":"}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":" \"San"}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":" Francisc"}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"o,"}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":" CA\"}"}}
event: content_block_stop
data: {"type":"content_block_stop","index":1}
event: message_delta
data: {"type":"message_delta","delta":{"stop_reason":"tool_use","stop_sequence":null},"usage":{"output_tokens":89}}
event: message_stop
data: {"type":"message_stop"}Diese Anfrage aktiviert erweitertes Denken mit Streaming. Die Einstellung display: "summarized" streamt eine komprimierte Zusammenfassung von Claudes Denkprozess anstelle der vollständigen Gedankenkette.
client = anthropic.Anthropic()
with client.messages.stream(
model="claude-opus-4-8",
max_tokens=20000,
thinking={"type": "adaptive", "display": "summarized"},
messages=[
{
"role": "user",
"content": "What is the greatest common divisor of 1071 and 462?",
}
],
) as stream:
for event in stream:
if event.type == "content_block_delta":
if event.delta.type == "thinking_delta":
print(event.delta.thinking, end="", flush=True)
elif event.delta.type == "text_delta":
print(event.delta.text, end="", flush=True)event: message_start
data: {"type": "message_start", "message": {"id": "msg_01...", "type": "message", "role": "assistant", "content": [], "model": "claude-opus-4-8", "stop_reason": null, "stop_sequence": null}}
event: content_block_start
data: {"type": "content_block_start", "index": 0, "content_block": {"type": "thinking", "thinking": "", "signature": ""}}
event: content_block_delta
data: {"type": "content_block_delta", "index": 0, "delta": {"type": "thinking_delta", "thinking": "I need to find the GCD of 1071 and 462 using the Euclidean algorithm.\n\n1071 = 2 × 462 + 147"}}
event: content_block_delta
data: {"type": "content_block_delta", "index": 0, "delta": {"type": "thinking_delta", "thinking": "\n462 = 3 × 147 + 21"}}
event: content_block_delta
data: {"type": "content_block_delta", "index": 0, "delta": {"type": "thinking_delta", "thinking": "\n147 = 7 × 21 + 0"}}
event: content_block_delta
data: {"type": "content_block_delta", "index": 0, "delta": {"type": "thinking_delta", "thinking": "\nThe remainder is 0, so GCD(1071, 462) = 21."}}
event: content_block_delta
data: {"type": "content_block_delta", "index": 0, "delta": {"type": "signature_delta", "signature": "EqQBCgIYAhIM1gbcDa9GJwZA2b3hGgxBdjrkzLoky3dl1pkiMOYds..."}}
event: content_block_stop
data: {"type": "content_block_stop", "index": 0}
event: content_block_start
data: {"type": "content_block_start", "index": 1, "content_block": {"type": "text", "text": ""}}
event: content_block_delta
data: {"type": "content_block_delta", "index": 1, "delta": {"type": "text_delta", "text": "The greatest common divisor of 1071 and 462 is **21**."}}
event: content_block_stop
data: {"type": "content_block_stop", "index": 1}
event: message_delta
data: {"type": "message_delta", "delta": {"stop_reason": "end_turn", "stop_sequence": null}}
event: message_stop
data: {"type": "message_stop"}Diese Anfrage bittet Claude, das Web nach aktuellen Wetterinformationen zu durchsuchen.
client = anthropic.Anthropic()
with client.messages.stream(
model="claude-opus-4-8",
max_tokens=1024,
tools=[{"type": "web_search_20250305", "name": "web_search", "max_uses": 5}],
messages=[
{"role": "user", "content": "What is the weather like in New York City today?"}
],
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)event: message_start
data: {"type":"message_start","message":{"id":"msg_01G...","type":"message","role":"assistant","model":"claude-opus-4-8","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":2679,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":3}}}
event: content_block_start
data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"I'll check"}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" the current weather in New York City for you"}}
event: ping
data: {"type": "ping"}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"."}}
event: content_block_stop
data: {"type":"content_block_stop","index":0}
event: content_block_start
data: {"type":"content_block_start","index":1,"content_block":{"type":"server_tool_use","id":"srvtoolu_014hJH82Qum7Td6UV8gDXThB","name":"web_search","input":{}}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":""}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"{\"query"}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"\":"}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":" \"weather"}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":" NY"}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"C to"}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"day\"}"}}
event: content_block_stop
data: {"type":"content_block_stop","index":1 }
event: content_block_start
data: {"type":"content_block_start","index":2,"content_block":{"type":"web_search_tool_result","tool_use_id":"srvtoolu_014hJH82Qum7Td6UV8gDXThB","content":[{"type":"web_search_result","title":"Weather in New York City in May 2025 (New York) - detailed Weather Forecast for a month","url":"https://world-weather.info/forecast/usa/new_york/may-2025/","encrypted_content":"Ev0DCioIAxgCIiQ3NmU4ZmI4OC1k...","page_age":null},...]}}
event: content_block_stop
data: {"type":"content_block_stop","index":2}
event: content_block_start
data: {"type":"content_block_start","index":3,"content_block":{"type":"text","text":""}}
event: content_block_delta
data: {"type":"content_block_delta","index":3,"delta":{"type":"text_delta","text":"Here's the current weather information for New York"}}
event: content_block_delta
data: {"type":"content_block_delta","index":3,"delta":{"type":"text_delta","text":" City:\n\n# Weather"}}
event: content_block_delta
data: {"type":"content_block_delta","index":3,"delta":{"type":"text_delta","text":" in New York City"}}
event: content_block_delta
data: {"type":"content_block_delta","index":3,"delta":{"type":"text_delta","text":"\n\n"}}
...
event: content_block_stop
data: {"type":"content_block_stop","index":17}
event: message_delta
data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":10682,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":510,"server_tool_use":{"web_search_requests":1}}}
event: message_stop
data: {"type":"message_stop"}Bei Claude 4.5-Modellen und früher kannst du eine Streaming-Anfrage, die aufgrund von Netzwerkproblemen, Timeouts oder anderen Fehlern unterbrochen wurde, wiederherstellen, indem du an der Stelle fortsetzt, an der der Stream unterbrochen wurde. Dieser Ansatz erspart dir die erneute Verarbeitung der gesamten Antwort.
Die grundlegende Wiederherstellungsstrategie umfasst:
Bei Claude 4.6 und späteren Modellen gilt dieselbe Erfassen-und-Fortsetzen-Strategie, aber Schritt 2 ändert sich: Anstatt die partielle Antwort in eine Assistant-Nachricht zu platzieren, fügst du eine User-Nachricht hinzu, die das Modell anweist, dort fortzufahren, wo es aufgehört hat.
Your previous response was interrupted and ended with [previous_response]. Continue from where you left off.text, tool_use, thinking). Tool-Nutzungs- und Extended-Thinking-Blöcke können nicht teilweise wiederhergestellt werden. Du kannst das Streaming ab dem letzten Text-Block fortsetzen.Verarbeite jeden stop_reason-Wert, sobald ein Stream abgeschlossen ist.
Streame Tool-Input-JSON ohne serverseitiges Buffering für geringere Latenz.
Streame die Ausgabe des erweiterten Denkens mit thinking_delta- und signature_delta-Events.
Verwende die offiziellen SDKs, die Streaming, Akkumulation und Wiederverbindung für dich übernehmen.
Verarbeite große Mengen von Anfragen asynchron, wenn du keine Echtzeit-Antworten benötigst.
Was this page helpful?