Streaming d'outils à granularité fine
Diffusez les entrées d'outils sans mise en mémoire tampon JSON côté serveur pour les applications sensibles à la latence.
Le « fine-grained tool streaming » (streaming d'outils à granularité fine) transmet l'entrée d'un outil à votre client au fur et à mesure que Claude la génère, sans mise en mémoire tampon côté serveur ni validation JSON. Le fait de sauter l'étape de mise en mémoire tampon réduit le délai avant le premier fragment d'un paramètre volumineux, tel qu'un document ou un bloc de code, et les fragments arrivent via les mêmes événements de Streaming de messages que l'utilisation d'outils standard.
Comment utiliser le streaming d'outils à granularité fine
Tous les modèles prennent en charge le streaming d'outils à granularité fine sur l'API Claude, Amazon Bedrock, Claude Platform sur AWS, Google Cloud et Microsoft Foundry. Pour l'utiliser, définissez eager_input_streaming sur true pour tout outil défini par l'utilisateur sur lequel vous souhaitez activer le streaming à granularité fine, et activez le streaming sur votre requête.
Le champ eager_input_streaming est facultatif. Le définir sur true active le streaming à granularité fine pour cet outil, et l'omettre vous donne le streaming standard avec mise en mémoire tampon, dans lequel l'API met en mémoire tampon et valide chaque valeur de paramètre avant de la renvoyer en streaming. L'exception concerne une requête qui envoie encore l'en-tête bêta hérité fine-grained-tool-streaming-2025-05-14, qui active le streaming à granularité fine pour les outils qui laissent le champ non défini. Le champ par outil remplace cet en-tête, et une valeur explicite false conserve le streaming avec mise en mémoire tampon pour un outil même lorsqu'une requête l'envoie encore. L'en-tête hérité ne peut pas être combiné avec une entrée d'ensemble d'outils computer use ou browser use : l'API rejette une requête qui envoie les deux, donc supprimez l'en-tête et définissez eager_input_streaming sur les outils définis par l'utilisateur qui en ont besoin. Consultez la Référence des outils pour la définition du champ.
L'exemple suivant active le streaming à granularité fine pour un outil make_file et demande à Claude un long poème, afin que l'entrée de l'outil soit suffisamment volumineuse pour la voir arriver en streaming :
client = anthropic.Anthropic()
with client.messages.stream(
max_tokens=65536,
model="claude-opus-5-5",
tools=[
{
"name": "make_file",
"description": "Write text to a file",
"eager_input_streaming": True,
"input_schema": {
"type": "object",
"properties": {
"filename": {
"type": "string",
"description": "The filename to write text to",
},
"lines_of_text": {
"type": "array",
"description": "An array of lines of text to write to the file",
},
},
"required": ["filename", "lines_of_text"],
},
}
],
messages=[
{
"role": "user",
"content": "Can you write a long poem and make a file called poem.txt?",
}
],
) as stream:
for event in stream:
if event.type == "input_json":
print(event.partial_json, end="", flush=True)
final_message = stream.get_final_message()
print()
for block in final_message.content:
if block.type == "tool_use":
print(f"Complete tool input: {block.input}")Chaque onglet active le streaming à granularité fine pour l'outil make_file. Les onglets SDK affichent chaque fragment d'entrée dès son arrivée, puis affichent l'entrée complète accumulée une fois le flux terminé. L'onglet cURL montre le flux d'événements brut, et l'onglet CLI utilise jq pour n'afficher que les fragments. Comme les fragments affichés se rejoignent pour former l'entrée complète de l'outil, le poème remplit votre terminal au fur et à mesure que Claude l'écrit :
{"filename": "poem.txt", "lines_of_text": ["The Wanderer's Journey", "", "I.", "", "Beneath the vast and star-strewn sky,", "Where silver moonbeams softly lie,", ...
Complete tool input: {"filename": "poem.txt", "lines_of_text": ["The Wanderer's Journey", ...]}Sans eager_input_streaming, l'API met en mémoire tampon et valide chaque valeur de paramètre avant de la renvoyer en streaming, de sorte que rien ne s'affiche pour un paramètre volumineux tant que Claude n'a pas fini de le générer. Avec ce champ, les fragments commencent à arriver dès que Claude entame le paramètre, et ils sont généralement plus longs, avec moins de coupures au milieu des mots.
Accumulation des deltas d'entrée d'outil
Le contrat d'accumulation est le même que pour le streaming d'utilisation d'outils standard, donc cette section s'applique avec et sans eager_input_streaming. Consultez Delta JSON d'entrée dans Streaming de messages pour le format des événements. Le streaming d'outils à granularité fine modifie ce que vous pouvez supposer du résultat : le serveur diffuse les fragments sans les valider, de sorte que la chaîne accumulée pourrait ne pas être du JSON valide.
Lorsqu'un bloc de contenu tool_use est diffusé en streaming, l'événement initial content_block_start contient input: {} (un objet vide). Il s'agit d'un espace réservé. L'entrée réelle arrive sous la forme d'une série d'événements input_json_delta, chacun transportant un fragment de chaîne partial_json. Pour assembler l'entrée complète, concaténez ces fragments et analysez le résultat lorsque le bloc se ferme.
Lorsque votre SDK fournit un utilitaire d'accumulation (comme le font les onglets Python, TypeScript, Go, Java et Ruby de l'exemple précédent), il s'en charge pour vous. Le modèle manuel est destiné aux SDK sans utilitaire, ou aux cas où vous souhaitez un contrôle total sur la manière dont l'entrée est assemblée.
Le contrat d'accumulation :
- Sur
content_block_startavectype: "tool_use", initialisez une chaîne vide :input_json = "" - Pour chaque
content_block_deltaavectype: "input_json_delta", ajoutez :input_json += event.delta.partial_json - Sur
content_block_stop, analysez la chaîne accumulée
Protégez l'analyse, comme le font les exemples SDK suivants. Une réponse peut également s'arrêter à max_tokens au milieu d'un paramètre. Vérifiez le motif d'arrêt et décidez s'il faut relancer la requête avec une valeur max_tokens plus élevée ou réparer l'entrée partielle.
La différence de type entre le input: {} initial (objet) et partial_json (chaîne) est intentionnelle. L'objet vide marque l'emplacement dans le tableau de contenu. Les chaînes delta construisent la valeur réelle.
client = anthropic.Anthropic()
tool_inputs: dict[int, str] = {} # index -> accumulated JSON string
with client.messages.stream(
model="claude-opus-5-5",
max_tokens=1024,
tools=[
{
"name": "get_weather",
"description": "Get current weather for a city",
"eager_input_streaming": True,
"input_schema": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
},
}
],
messages=[{"role": "user", "content": "Weather in Paris?"}],
) as stream:
for event in stream:
match event.type:
case "content_block_start" if event.content_block.type == "tool_use":
tool_inputs[event.index] = ""
case "content_block_delta" if event.delta.type == "input_json_delta":
tool_inputs[event.index] += event.delta.partial_json
case "content_block_stop" if event.index in tool_inputs:
raw_input = tool_inputs[event.index]
try:
parsed = json.loads(raw_input)
except json.JSONDecodeError:
# La chaîne accumulée n'est pas garantie d'être un JSON valide.
# Consultez « Handling invalid JSON in tool responses » sur cette page.
print(f"Invalid tool input: {raw_input}")
else:
print(f"Tool input: {parsed}")Gestion du JSON invalide dans les réponses d'outils
Avec le streaming d'outils à granularité fine, l'entrée accumulée pour un appel d'outil pourrait être du JSON invalide ou incomplet. Dans ce cas, vous ne pouvez pas exécuter l'outil, donc signalez plutôt l'échec à Claude. Le content d'un résultat d'outil n'a pas besoin d'être du JSON, mais envelopper la chaîne brute dans un objet JSON sous une clé unique indique sans ambiguïté à Claude que vous avez reçu du JSON invalide, et préserve l'entrée d'origine pour le débogage :
{
"INVALID_JSON": "<the unparseable input you received>"
}Renvoyez l'enveloppe, sérialisée en chaîne, comme content d'un bloc de contenu de résultat d'outil avec is_error défini sur true :
{
"type": "tool_result",
"tool_use_id": "toolu_01A09q90qw90lq917835lq9",
"is_error": true,
"content": "{\"INVALID_JSON\": \"<the unparseable input you received>\"}"
}Prochaines étapes
Comprenez comment fonctionne la fenêtre de contexte, comment la réflexion étendue et l'utilisation d'outils y sont comptabilisées, et comment gérer le contexte à mesure que les conversations s'allongent.
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.
Analysez les blocs tool_use, formatez les réponses tool_result et gérez les erreurs avec is_error.
Répertoire des outils fournis par Anthropic et référence des propriétés facultatives de définition d'outils.
Was this page helpful?