Streaming de messages
Diffusez les réponses de l'API Messages de manière incrémentale avec des événements envoyés par le serveur, y compris les deltas de texte, d'utilisation d'outils et de réflexion étendue.
Lors de la création d'un Message, vous pouvez définir "stream": true pour diffuser la réponse de manière incrémentale en « streaming » (diffusion en flux) à l'aide de « server-sent events » (événements envoyés par le serveur), ou SSE.
Streaming avec les SDK
Le SDK Python et le SDK TypeScript offrent plusieurs façons d'effectuer du streaming. Le SDK PHP fournit le streaming via createStream(). Le SDK Python prend en charge les flux synchrones et asynchrones. Consultez la documentation de chaque SDK pour plus de détails.
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)Obtenir le message final sans gérer les événements
Si vous n'avez pas besoin de traiter le texte au fur et à mesure de son arrivée, les SDK offrent un moyen d'utiliser le streaming en interne tout en renvoyant l'objet Message complet, identique à celui que renvoie .create(). Cela est particulièrement utile pour les requêtes avec des valeurs max_tokens élevées, pour lesquelles les SDK exigent le streaming afin d'éviter les délais d'expiration 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)L'appel .stream() maintient la connexion HTTP active grâce aux server-sent events, puis .get_final_message() (Python) ou .finalMessage() (TypeScript) accumule tous les événements et renvoie l'objet Message complet. En Go, vous appelez message.Accumulate(event) dans la boucle du flux pour construire le même Message complet. En Java, utilisez MessageAccumulator.create() et appelez accumulator.accumulate(event) sur chaque événement. En C#, attendez (await) la méthode d'extension .Aggregate() du flux pour obtenir le Message complet, ou passez un MessageContentAggregator à .CollectAsync() pour agréger tout en gérant les événements. En Ruby, appelez .accumulated_message sur le flux. Dans le SDK PHP, vous itérez manuellement sur les événements du flux pour accumuler la réponse.
Types d'événements
Chaque événement envoyé par le serveur comprend un type d'événement nommé et des données JSON associées. Chaque événement utilise un nom d'événement SSE (par exemple, event: message_stop) et inclut le type d'événement correspondant dans ses données.
Chaque flux suit le déroulement d'événements suivant :
message_start: contient un objetMessageavec uncontentvide. Avec l'en-tête bêtathinking-binding-controls-2026-08-01, cet objetMessagecontient également le tableauinput_transformations. Après un repli côté serveur en cours de flux, l'événementmessage_deltafinal contient à nouveau le tableau avec les entrées du modèle ayant servi la réponse.- Une série de blocs de contenu, chacun ayant un événement
content_block_start, un ou plusieurs événementscontent_block_deltaet un événementcontent_block_stop. Chaque bloc de contenu possède unindexqui correspond à son index dans le tableaucontentdu Message final. Une exception : lors des réponses avec repli côté serveur, un bloc de contenufallbackarrive à chaque frontière de modèle sous la forme d'une pairecontent_block_startetcontent_block_stopsans aucun delta entre les deux. - Un ou plusieurs événements
message_delta, indiquant des modifications de premier niveau de l'objetMessagefinal. - Un événement
message_stopfinal.
Événements ping
Les flux d'événements peuvent également inclure un nombre quelconque d'événements ping.
Événements d'erreur
L'API peut occasionnellement envoyer des erreurs dans le flux d'événements. Par exemple, pendant les périodes de forte utilisation, vous pouvez recevoir une overloaded_error, qui correspondrait normalement à un HTTP 529 dans un contexte sans streaming :
event: error
data: {"type": "error", "error": {"type": "overloaded_error", "message": "Overloaded"}}Autres événements
Conformément à la politique de gestion des versions, de nouveaux types d'événements peuvent être ajoutés, et votre code doit gérer correctement les types d'événements inconnus.
Types de deltas de blocs de contenu
Chaque événement content_block_delta contient un delta d'un type qui met à jour le bloc content à un index donné.
Delta de texte
Un delta de bloc de contenu text ressemble à ceci :
event: content_block_delta
data: {"type": "content_block_delta","index": 0,"delta": {"type": "text_delta", "text": "ello frien"}}Delta JSON d'entrée
Les deltas des blocs de contenu tool_use correspondent à des mises à jour du champ input du bloc. Pour offrir une granularité maximale, les deltas sont des chaînes JSON partielles, tandis que le tool_use.input final est toujours un objet.
Vous pouvez accumuler les deltas de chaînes et analyser le JSON une fois que vous recevez un événement content_block_stop, en utilisant une bibliothèque comme Pydantic pour effectuer une analyse JSON partielle, ou en utilisant les SDK, qui fournissent des utilitaires pour accéder aux valeurs incrémentales analysées.
Un delta de bloc de contenu tool_use ressemble à ceci :
event: content_block_delta
data: {"type": "content_block_delta","index": 1,"delta": {"type": "input_json_delta","partial_json": "{\"location\": \"San Fra"}}}Remarque : les modèles actuels ne prennent en charge que l'émission d'une seule propriété clé-valeur complète de input à la fois. Ainsi, lors de l'utilisation d'outils, il peut y avoir des délais entre les événements de streaming pendant que le modèle travaille. Une fois qu'une clé et une valeur de input sont accumulées, elles sont émises sous forme de plusieurs événements content_block_delta avec du JSON partiel découpé en morceaux, afin que le format puisse automatiquement prendre en charge une granularité plus fine dans les futurs modèles.
Delta de réflexion
Lorsque vous utilisez la réflexion avec le streaming activé, vous recevez le contenu de réflexion via des événements thinking_delta. Ces deltas correspondent au champ thinking des blocs de contenu thinking.
Pour le contenu de réflexion, un événement spécial signature_delta est envoyé juste avant l'événement content_block_stop. Cette signature est utilisée pour vérifier l'intégrité du bloc de réflexion.
Lorsque display: "omitted" est défini dans la configuration de réflexion, aucun texte de réflexion n'est diffusé. Le bloc de réflexion s'ouvre, reçoit un thinking_delta avec une chaîne thinking vide puis un unique signature_delta, et se ferme. Avec display: "updates" (bêta), les blocs de raisonnement sont diffusés de la même manière, et seules les mises à jour de progression que certains modèles rédigent entre les appels d'outils diffusent des événements thinking_delta contenant du texte. Consultez Contrôler l'affichage de la réflexion.
Un delta de réflexion typique ressemble à ceci :
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"}}Le delta de signature ressemble à ceci :
event: content_block_delta
data: {"type": "content_block_delta", "index": 0, "delta": {"type": "signature_delta", "signature": "EqQBCgIYAhIM1gbcDa9GJwZA2b3hGgxBdjrkzLoky3dl1pkiMOYds..."}}Réponse HTTP complète en streaming
Utilisez les SDK clients lorsque vous utilisez le mode streaming. Toutefois, si vous construisez une intégration directe avec l'API, vous devez gérer ces événements vous-même.
Une réponse en streaming se compose de :
- Un événement
message_start - Potentiellement plusieurs blocs de contenu, chacun contenant :
- Un événement
content_block_start - Potentiellement plusieurs événements
content_block_delta - Un événement
content_block_stop
- Un événement
- Un ou plusieurs événements
message_delta - Un événement
message_stop
Des événements ping peuvent également être dispersés tout au long de la réponse. Consultez Types d'événements pour plus de détails sur le format.
Requête de streaming de 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)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"}
Requête de streaming avec utilisation d'outils
Cette requête demande à Claude d'utiliser un outil pour indiquer la météo.
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)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"}Requête de streaming avec réflexion
Cette requête active la réflexion avec le streaming. Le paramètre display: "summarized" transmet en streaming un résumé condensé du raisonnement de Claude plutôt que la chaîne de pensée complète.
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)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"}Requête de streaming avec utilisation de l'outil de recherche web
Cette requête demande à Claude de rechercher sur le web des informations météorologiques actuelles.
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)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"}Récupération après erreur
Claude 4.5 et versions antérieures
Pour les modèles Claude 4.5 et antérieurs, vous pouvez récupérer une requête de streaming interrompue en raison de problèmes réseau, de délais d'expiration ou d'autres erreurs en reprenant à partir de l'endroit où le flux a été interrompu. Cette approche vous évite de retraiter l'intégralité de la réponse.
La stratégie de récupération de base consiste à :
- Capturer la réponse partielle : enregistrez tout le contenu reçu avec succès avant que l'erreur ne se produise.
- Construire une requête de continuation : créez une nouvelle requête API qui inclut la réponse partielle de l'assistant comme début d'un nouveau message d'assistant.
- Reprendre le streaming : continuez à recevoir le reste de la réponse à partir de l'endroit où elle a été interrompue.
Claude 4.6 et versions ultérieures
Pour les modèles Claude 4.6 et ultérieurs, la même stratégie de capture et de reprise s'applique, mais l'étape 2 change : au lieu de placer la réponse partielle dans un message d'assistant, ajoutez un message utilisateur qui demande au modèle de continuer là où il s'est arrêté.
- Capturer la réponse partielle : enregistrez tout le contenu reçu avec succès avant que l'erreur ne se produise.
- Construire une requête de continuation : créez une nouvelle requête API avec un message utilisateur contenant la réponse partielle et une instruction de continuer, par exemple :
Sample prompt
Your previous response was interrupted and ended with [previous_response]. Continue from where you left off. - Reprendre le streaming : continuez à recevoir le reste de la réponse à partir de l'endroit où elle a été interrompue.
Bonnes pratiques de récupération après erreur
- Utilisez les fonctionnalités du SDK : tirez parti des capacités intégrées d'accumulation de messages et de gestion des erreurs du SDK.
- Gérez les types de contenu : sachez que les messages peuvent contenir plusieurs blocs de contenu (
text,tool_use,thinking). Les blocs d'utilisation d'outils et de réflexion étendue ne peuvent pas être récupérés partiellement. Vous pouvez reprendre le streaming à partir du bloc de texte le plus récent.
Étapes suivantes
Gérez chaque valeur de stop_reason une fois qu'un flux est terminé.
Diffusez le JSON d'entrée des outils sans mise en mémoire tampon côté serveur pour une latence réduite.
Diffusez la sortie de réflexion avec les événements thinking_delta et signature_delta.
Utilisez les SDK officiels, qui gèrent pour vous le streaming, l'accumulation et la reconnexion.
Traitez de grands volumes de requêtes de manière asynchrone lorsque vous n'avez pas besoin de réponses en temps réel.
Was this page helpful?