Claude Platform Docs
MessagesModellfähigkeiten

Streaming von Nachrichten

Streame Antworten der Messages API inkrementell mit Server-Sent Events, einschließlich Text-, Tool-Nutzungs- und erweiterten Denk-Deltas.

Beim Erstellen einer Message kannst du "stream": true setzen, um die Antwort inkrementell mithilfe von Server-Sent Events (SSE) zu streamen.

Streaming mit SDKs

Das Python SDK und das TypeScript SDK bieten mehrere Möglichkeiten für „streaming“ (Streaming). Das PHP SDK stellt Streaming über createStream() bereit. Das Python SDK erlaubt sowohl synchrone als auch asynchrone Streams. Details findest du in der Dokumentation des jeweiligen SDK.

client = anthropic.Anthropic()

with client.messages.stream(
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello"}],
    model="claude-opus-5-5",
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)

Die finale Nachricht ohne Event-Verarbeitung erhalten

Wenn du Text nicht verarbeiten musst, während er eintrifft, bieten die SDKs eine Möglichkeit, Streaming intern zu verwenden und dabei das vollständige Message-Objekt zurückzugeben, identisch mit 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-5-5",
) as stream:
    message = stream.get_final_message()

for block in message.content:
    if block.type == "text":
        print(block.text)

Der .stream()-Aufruf hält die HTTP-Verbindung mit Server-Sent Events offen, anschließend sammelt .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 dieselbe vollständige Message aufzubauen. 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.

Event-Typen

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:

  1. message_start: enthält ein Message-Objekt mit leerem content. Unter dem Beta-Header thinking-binding-controls-2026-08-01 trägt dieses Message-Objekt zusätzlich das Array input_transformations. Nach einem serverseitigen Fallback mitten im Stream trägt das finale message_delta-Event das Array erneut mit den Einträgen des ausliefernden Modells.
  2. Eine Reihe von Content-Blöcken, von denen jeder ein content_block_start-Event, ein oder mehrere content_block_delta-Events und ein content_block_stop-Event hat. Jeder Content-Block hat einen index, der seinem Index im content-Array der finalen Message entspricht. Eine Ausnahme: Bei Antworten mit serverseitigem Fallback trifft an jeder Modellgrenze ein fallback-Content-Block als Paar aus content_block_start und content_block_stop ohne Deltas dazwischen ein.
  3. Ein oder mehrere message_delta-Events, die Änderungen auf oberster Ebene am finalen Message-Objekt anzeigen.
  4. Ein abschließendes message_stop-Event.

Ping-Events

Event-Streams können außerdem eine beliebige Anzahl von ping-Events enthalten.

Error-Events

Die API kann gelegentlich Fehler im Event-Stream senden. Beispielsweise kannst du in Zeiten hoher Auslastung einen overloaded_error erhalten, der in einem Nicht-Streaming-Kontext normalerweise einem HTTP 529 entsprechen würde:

Example error
event: error
data: {"type": "error", "error": {"type": "overloaded_error", "message": "Overloaded"}}

Andere Events

Gemäß der Versionierungsrichtlinie können neue Event-Typen hinzugefügt werden, und dein Code sollte unbekannte Event-Typen robust behandeln.

Content-Block-Delta-Typen

Jedes content_block_delta-Event enthält ein delta eines Typs, der den content-Block an einem bestimmten index aktualisiert.

Text-Delta

Ein text-Content-Block-Delta sieht so aus:

Text delta
event: content_block_delta
data: {"type": "content_block_delta","index": 0,"delta": {"type": "text_delta", "text": "ello frien"}}

Input-JSON-Delta

Die Deltas für tool_use-Content-Blöcke entsprechen Aktualisierungen des input-Felds 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:

Input JSON delta
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 die Ausgabe jeweils einer vollständigen Schlüssel-Wert-Eigenschaft aus input auf einmal. Daher kann es bei der Verwendung von Tools zu Verzögerungen zwischen Streaming-Events kommen, während das Modell arbeitet. Sobald ein input-Schlüssel und -Wert akkumuliert sind, werden sie als mehrere content_block_delta-Events mit gestückeltem partiellem JSON ausgegeben, sodass das Format in zukünftigen Modellen automatisch feinere Granularität unterstützen kann.

Thinking-Delta

Wenn du Thinking 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 unmittelbar vor dem content_block_stop-Event ein spezielles signature_delta-Event gesendet. Diese Signatur wird verwendet, um die Integrität des Thinking-Blocks zu verifizieren.

Wenn in der Thinking-Konfiguration display: "omitted" gesetzt ist, wird kein Thinking-Text gestreamt. Der Thinking-Block wird geöffnet, erhält ein thinking_delta mit einem leeren thinking-String und anschließend ein einzelnes signature_delta und wird dann geschlossen. Mit display: "updates" (Beta) werden Reasoning-Blöcke auf dieselbe Weise gestreamt, und nur die Fortschrittsaktualisierungen, die manche Modelle zwischen Tool-Aufrufen schreiben, streamen thinking_delta-Events, die Text enthalten. Siehe Anzeige des Nachdenkens steuern.

Ein typisches Thinking-Delta sieht so aus:

Thinking delta
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 Signatur-Delta sieht so aus:

Signature delta
event: content_block_delta
data: {"type": "content_block_delta", "index": 0, "delta": {"type": "signature_delta", "signature": "EqQBCgIYAhIM1gbcDa9GJwZA2b3hGgxBdjrkzLoky3dl1pkiMOYds..."}}

Vollständige HTTP-Stream-Antwort

Verwende die Client-SDKs, wenn du den Streaming-Modus nutzt. Wenn du jedoch eine direkte API-Integration baust, musst du diese Events selbst verarbeiten.

Eine Stream-Antwort besteht aus:

  1. Einem message_start-Event
  2. Möglicherweise mehreren Content-Blöcken, von denen jeder Folgendes enthält:
    • Ein content_block_start-Event
    • Möglicherweise mehrere content_block_delta-Events
    • Ein content_block_stop-Event
  3. Einem oder mehreren message_delta-Events
  4. Einem message_stop-Event

Es können außerdem ping-Events über die gesamte Antwort verteilt sein. Weitere Details zum Format findest du unter Event-Typen.

Einfache Streaming-Anfrage

client = anthropic.Anthropic()

with client.messages.stream(
    model="claude-opus-5-5",
    messages=[{"role": "user", "content": "Hello"}],
    max_tokens=256,
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)
Response
event: message_start
data: {"type": "message_start", "message": {"id": "msg_1nZdL29xx5MUA1yADyHTEsnR8uuvGzszyY", "type": "message", "role": "assistant", "content": [], "model": "claude-opus-5-5", "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"}

Streaming-Anfrage mit Tool-Nutzung

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-5",
    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)
Response
event: message_start
data: {"type":"message_start","message":{"id":"msg_014p7gG3wDgGV9EUtLvnow3U","type":"message","role":"assistant","model":"claude-opus-5","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"}

Streaming-Anfrage mit Thinking

Diese Anfrage aktiviert Thinking mit Streaming. Die Einstellung display: "summarized" streamt eine verdichtete Zusammenfassung von Claudes Überlegungen anstelle der vollständigen Gedankenkette.

client = anthropic.Anthropic()

with client.messages.stream(
    model="claude-opus-5-5",
    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":
            delta = event.delta
            match delta.type:
                case "thinking_delta":
                    print(delta.thinking, end="", flush=True)
                case "text_delta":
                    print(delta.text, end="", flush=True)
Response
event: message_start
data: {"type": "message_start", "message": {"id": "msg_01...", "type": "message", "role": "assistant", "content": [], "model": "claude-opus-5-5", "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"}

Streaming-Anfrage mit Web-Search-Tool-Nutzung

Diese Anfrage bittet Claude, im Web nach aktuellen Wetterinformationen zu suchen.

client = anthropic.Anthropic()

with client.messages.stream(
    model="claude-opus-5-5",
    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)
Response
event: message_start
data: {"type":"message_start","message":{"id":"msg_01G...","type":"message","role":"assistant","model":"claude-opus-5-5","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"}

Fehlerbehebung

Claude 4.5 und früher

Bei Claude-4.5-Modellen und früheren 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:

  1. Die partielle Antwort erfassen: Speichere alle Inhalte, die vor dem Auftreten des Fehlers erfolgreich empfangen wurden.
  2. Eine Fortsetzungsanfrage konstruieren: Erstelle eine neue API-Anfrage, die die partielle Assistant-Antwort als Beginn einer neuen Assistant-Nachricht enthält.
  3. Streaming fortsetzen: Empfange den Rest der Antwort ab der Stelle, an der sie unterbrochen wurde.

Claude 4.6 und später

Für Claude 4.6 und spätere Modelle gilt dieselbe Erfassen-und-Fortsetzen-Strategie, aber Schritt 2 ändert sich: Anstatt die partielle Antwort in eine Assistant-Nachricht zu legen, füge eine User-Nachricht hinzu, die das Modell anweist, dort fortzufahren, wo es aufgehört hat.

  1. Die partielle Antwort erfassen: Speichere alle Inhalte, die vor dem Auftreten des Fehlers erfolgreich empfangen wurden.
  2. Eine Fortsetzungsanfrage konstruieren: Erstelle eine neue API-Anfrage mit einer User-Nachricht, die die partielle Antwort und eine Anweisung zum Fortfahren enthält, zum Beispiel:
    Sample prompt
    Your previous response was interrupted and ended with [previous_response]. Continue from where you left off.
  3. Streaming fortsetzen: Empfange den Rest der Antwort ab der Stelle, an der sie unterbrochen wurde.

Best Practices zur Fehlerbehebung

  1. SDK-Funktionen nutzen: Nutze die integrierten Funktionen des SDK zur Nachrichtenakkumulation und Fehlerbehandlung.
  2. Content-Typen berücksichtigen: Beachte, dass Nachrichten mehrere Content-Blöcke enthalten können (text, tool_use, thinking). Blöcke für Tool-Nutzung und erweitertes Nachdenken können nicht partiell wiederhergestellt werden. Du kannst das Streaming ab dem letzten Text-Block fortsetzen.

Nächste Schritte

Behandle jeden stop_reason-Wert, sobald ein Stream abgeschlossen ist.

Streame Tool-Input-JSON ohne serverseitiges Puffern für geringere Latenz.

Streame Thinking-Ausgaben 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?