Claude Platform Docs
MessagesCapacità del modello

Streaming dei messaggi

Trasmetti in streaming le risposte della Messages API in modo incrementale con server-sent events, inclusi testo, uso degli strumenti e delta di ragionamento esteso.

Quando crei un Message, puoi impostare "stream": true per trasmettere in streaming la risposta in modo incrementale utilizzando i server-sent events (SSE).

Streaming con gli SDK

Il Python SDK e il TypeScript SDK offrono molteplici modi di effettuare lo streaming. Il PHP SDK fornisce lo streaming tramite createStream(). Il Python SDK consente sia stream sincroni che asincroni. Consulta la documentazione di ciascun SDK per i dettagli.

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)

Ottenere il messaggio finale senza gestire gli eventi

Se non hai bisogno di elaborare il testo man mano che arriva, gli SDK forniscono un modo per utilizzare lo streaming internamente restituendo al contempo l'oggetto Message completo, identico a quello che restituisce .create(). Questo è particolarmente utile per le richieste con valori max_tokens elevati, dove gli SDK richiedono lo streaming per evitare timeout HTTP.

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)

La chiamata .stream() mantiene attiva la connessione HTTP con i server-sent events, quindi .get_final_message() (Python) o .finalMessage() (TypeScript) accumula tutti gli eventi e restituisce l'oggetto Message completo. In Go, chiami message.Accumulate(event) all'interno del ciclo dello stream per costruire lo stesso Message completo. In Java, usa MessageAccumulator.create() e chiama accumulator.accumulate(event) su ciascun evento. In C#, attendi il metodo di estensione .Aggregate() dello stream per ottenere il Message completo, oppure passa un MessageContentAggregator a .CollectAsync() per aggregare mentre gestisci gli eventi. In Ruby, chiama .accumulated_message sullo stream. Nel PHP SDK, itera manualmente sugli eventi dello stream per accumulare la risposta.

Tipi di eventi

Ogni server-sent event include un tipo di evento denominato e i dati JSON associati. Ogni evento utilizza un nome di evento SSE (ad esempio, event: message_stop) e include il type di evento corrispondente nei suoi dati.

Ogni stream utilizza il seguente flusso di eventi:

  1. message_start: contiene un oggetto Message con content vuoto. Sotto l'header beta thinking-binding-controls-2026-08-01, questo oggetto Message trasporta anche l'array input_transformations. Dopo un fallback lato server a metà stream, l'evento finale message_delta trasporta nuovamente l'array con le voci del modello che serve la richiesta.
  2. Una serie di blocchi di contenuto, ciascuno dei quali ha un content_block_start, uno o più eventi content_block_delta e un evento content_block_stop. Ogni blocco di contenuto ha un index che corrisponde al suo indice nell'array content del Message finale. Un'eccezione: durante le risposte di fallback lato server, un blocco di contenuto fallback arriva a ogni confine del modello come una coppia content_block_start e content_block_stop senza delta nel mezzo.
  3. Uno o più eventi message_delta, che indicano modifiche di alto livello all'oggetto Message finale.
  4. Un evento finale message_stop.

Eventi ping

I flussi di eventi possono anche includere un numero qualsiasi di eventi ping.

Eventi di errore

L'API può occasionalmente inviare errori nel flusso di eventi. Ad esempio, durante i periodi di utilizzo elevato, potresti ricevere un overloaded_error, che normalmente corrisponderebbe a un HTTP 529 in un contesto non-streaming:

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

Altri eventi

In conformità con la politica di versioning, possono essere aggiunti nuovi tipi di eventi, e il tuo codice dovrebbe gestire in modo appropriato i tipi di eventi sconosciuti.

Tipi di delta dei blocchi di contenuto

Ogni evento content_block_delta contiene un delta di un tipo che aggiorna il blocco content a un dato index.

Delta di testo

Un delta di blocco di contenuto text appare così:

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

Delta JSON di input

I delta per i blocchi di contenuto tool_use corrispondono agli aggiornamenti del campo input del blocco. Per supportare la massima granularità, i delta sono stringhe JSON parziali, mentre il tool_use.input finale è sempre un oggetto.

Puoi accumulare i delta di stringa e analizzare il JSON una volta ricevuto un evento content_block_stop, utilizzando una libreria come Pydantic per eseguire l'analisi JSON parziale, oppure utilizzando gli SDK, che forniscono helper per accedere ai valori incrementali analizzati.

Un delta di blocco di contenuto tool_use appare così:

Input JSON delta
event: content_block_delta
data: {"type": "content_block_delta","index": 1,"delta": {"type": "input_json_delta","partial_json": "{\"location\": \"San Fra"}}}

Nota: i modelli attuali supportano solo l'emissione di una proprietà chiave-valore completa da input alla volta. Pertanto, quando si utilizzano gli strumenti, potrebbero esserci ritardi tra gli eventi di streaming mentre il modello sta lavorando. Una volta accumulati una chiave e un valore di input, vengono emessi come più eventi content_block_delta con JSON parziale suddiviso in blocchi, in modo che il formato possa supportare automaticamente una granularità più fine nei modelli futuri.

Delta di ragionamento

Quando utilizzi il ragionamento con lo streaming abilitato, riceverai il contenuto del ragionamento tramite eventi thinking_delta. Questi delta corrispondono al campo thinking dei blocchi di contenuto thinking.

Per il contenuto del ragionamento, un evento speciale signature_delta viene inviato appena prima dell'evento content_block_stop. Questa firma viene utilizzata per verificare l'integrità del blocco di ragionamento.

Quando nella configurazione del ragionamento è impostato display: "omitted", non viene trasmesso alcun testo di ragionamento. Il blocco di ragionamento si apre, riceve un thinking_delta con una stringa thinking vuota e poi un singolo signature_delta, e si chiude. Con display: "updates" (beta), i blocchi di ragionamento vengono trasmessi allo stesso modo, e solo gli aggiornamenti di avanzamento che alcuni modelli scrivono tra le chiamate agli strumenti trasmettono eventi thinking_delta che contengono testo. Consulta Controllare la visualizzazione del ragionamento.

Un tipico delta di ragionamento appare così:

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"}}

Il delta di firma appare così:

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

Risposta completa dello stream HTTP

Usa gli SDK client quando utilizzi la modalità streaming. Tuttavia, se stai costruendo un'integrazione API diretta, devi gestire questi eventi tu stesso.

Una risposta in streaming consiste in:

  1. Un evento message_start
  2. Potenzialmente più blocchi di contenuto, ciascuno dei quali contiene:
    • Un evento content_block_start
    • Potenzialmente più eventi content_block_delta
    • Un evento content_block_stop
  3. Uno o più eventi message_delta
  4. Un evento message_stop

Potrebbero esserci anche eventi ping dispersi nella risposta. Consulta Tipi di eventi per maggiori dettagli sul formato.

Richiesta di streaming di base

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"}

Richiesta di streaming con uso degli strumenti

Questa richiesta chiede a Claude di utilizzare uno strumento per riportare il meteo.

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"}

Richiesta di streaming con ragionamento

Questa richiesta abilita il ragionamento con lo streaming. L'impostazione display: "summarized" trasmette in streaming un riepilogo condensato del ragionamento di Claude anziché l'intera catena di pensiero.

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"}

Richiesta di streaming con uso dello strumento di ricerca web

Questa richiesta chiede a Claude di cercare sul web informazioni meteo attuali.

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"}

Recupero dagli errori

Claude 4.5 e precedenti

Per i modelli Claude 4.5 e precedenti, puoi recuperare una richiesta di streaming che è stata interrotta a causa di problemi di rete, timeout o altri errori riprendendo dal punto in cui lo stream è stato interrotto. Questo approccio ti evita di rielaborare l'intera risposta.

La strategia di recupero di base prevede:

  1. Cattura la risposta parziale: Salva tutto il contenuto ricevuto con successo prima che si verificasse l'errore.
  2. Costruisci una richiesta di continuazione: Crea una nuova richiesta API che includa la risposta parziale dell'assistente come inizio di un nuovo messaggio dell'assistente.
  3. Riprendi lo streaming: Continua a ricevere il resto della risposta dal punto in cui è stata interrotta.

Claude 4.6 e successivi

Per i modelli Claude 4.6 e successivi, si applica la stessa strategia di cattura e ripresa, ma il passaggio 2 cambia: invece di inserire la risposta parziale in un messaggio dell'assistente, aggiungi un messaggio utente che istruisce il modello a continuare dal punto in cui si era interrotto.

  1. Cattura la risposta parziale: Salva tutto il contenuto ricevuto con successo prima che si verificasse l'errore.
  2. Costruisci una richiesta di continuazione: Crea una nuova richiesta API con un messaggio utente contenente la risposta parziale e un'istruzione per continuare, ad esempio:
    Sample prompt
    Your previous response was interrupted and ended with [previous_response]. Continue from where you left off.
  3. Riprendi lo streaming: Continua a ricevere il resto della risposta dal punto in cui è stata interrotta.

Best practice per il recupero dagli errori

  1. Usa le funzionalità dell'SDK: Sfrutta le capacità integrate di accumulo dei messaggi e gestione degli errori dell'SDK.
  2. Gestisci i tipi di contenuto: Tieni presente che i messaggi possono contenere più blocchi di contenuto (text, tool_use, thinking). I blocchi di uso degli strumenti e di ragionamento esteso non possono essere recuperati parzialmente. Puoi riprendere lo streaming dal blocco di testo più recente.

Prossimi passi

Gestisci ogni valore stop_reason una volta completato uno stream.

Trasmetti in streaming il JSON di input degli strumenti senza buffering lato server per una latenza inferiore.

Trasmetti in streaming l'output del ragionamento con gli eventi thinking_delta e signature_delta.

Usa gli SDK ufficiali, che gestiscono per te lo streaming, l'accumulo e la riconnessione.

Elabora grandi volumi di richieste in modo asincrono quando non hai bisogno di risposte in tempo reale.

Was this page helpful?