Diese Funktion ist für Zero Data Retention (ZDR) qualifiziert. Wenn deine Organisation eine ZDR-Vereinbarung hat, werden Daten, die über diese Funktion gesendet werden, nicht gespeichert, nachdem die API-Antwort zurückgegeben wurde.
„Fine-grained tool streaming" (feingranulares Tool-Streaming) liefert die Eingabe eines Tools an deinen Client, während Claude sie generiert – ohne serverseitiges Buffering oder JSON-Validierung. Das Überspringen des Buffering-Schritts reduziert die Zeit bis zum ersten Fragment eines großen Parameters, etwa eines Dokuments oder eines Codeblocks, und die Fragmente kommen über dieselben Streaming-Messages-Events an wie bei der standardmäßigen Tool-Nutzung.
Da die API die Eingabe eines Tools vor dem Streaming weder puffert noch validiert, erhältst du möglicherweise partielles oder ungültiges JSON. Eine Antwort, die mit dem Stop-Reason max_tokens endet, kann einen Parameter auch mittendrin abschneiden. Akkumuliere die Fragmente, sichere das Parsen ab und lies unter Umgang mit ungültigem JSON in Tool-Antworten, wie du nicht parsbare Eingaben an Claude zurückgibst.
Alle Modelle unterstützen feingranulares Tool-Streaming auf der Claude API, Claude Platform on AWS, Amazon Bedrock, Google Cloud und Microsoft Foundry. Um es zu verwenden, setze eager_input_streaming auf true bei jedem benutzerdefinierten Tool, für das du feingranulares Streaming aktivieren möchtest, und aktiviere Streaming für deine Anfrage.
Das Feld eager_input_streaming ist optional. Wenn du es auf true setzt, wird feingranulares Streaming für dieses Tool aktiviert; wenn du es weglässt, erhältst du das standardmäßige gepufferte Streaming, bei dem die API jeden Parameterwert puffert und validiert, bevor sie ihn zurückstreamt. Die Ausnahme ist eine Anfrage, die noch den Legacy-Beta-Header fine-grained-tool-streaming-2025-05-14 sendet – dieser aktiviert feingranulares Streaming für Tools, bei denen das Feld nicht gesetzt ist. Das Feld pro Tool ersetzt diesen Header, und ein explizites false behält das gepufferte Streaming für ein Tool bei, selbst wenn eine Anfrage den Header noch sendet. Siehe Tool-Referenz für die Felddefinition.
Das folgende Beispiel aktiviert feingranulares Streaming für ein make_file-Tool und bittet Claude um ein langes Gedicht, sodass die Tool-Eingabe groß genug ist, um das Streaming zu beobachten:
client = anthropic.Anthropic()
with client.messages.stream(
max_tokens=65536,
model="claude-opus-4-8",
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}")Jeder Tab aktiviert feingranulares Streaming für das make_file-Tool. Die SDK-Tabs geben jedes Eingabefragment aus, sobald es ankommt, und geben dann die vollständige akkumulierte Eingabe aus, sobald der Stream endet. Der cURL-Tab zeigt den rohen Event-Stream, und der CLI-Tab verwendet jq, um nur die Fragmente auszugeben. Da sich die ausgegebenen Fragmente zur vollständigen Tool-Eingabe zusammenfügen, füllt das Gedicht dein Terminal, während Claude es schreibt:
{"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", ...]}Ohne eager_input_streaming puffert und validiert die API jeden Parameterwert, bevor sie ihn zurückstreamt, sodass bei einem großen Parameter nichts ausgegeben wird, bis Claude ihn vollständig generiert hat. Mit dieser Option beginnen Fragmente anzukommen, sobald Claude mit dem Parameter beginnt, und sie sind typischerweise länger, mit weniger Unterbrechungen mitten im Wort.
Der Akkumulations-Vertrag ist derselbe wie beim standardmäßigen Tool-Nutzungs-Streaming, daher gilt dieser Abschnitt mit und ohne eager_input_streaming. Siehe Input JSON delta in Streaming-Messages für das Event-Format. Feingranulares Tool-Streaming ändert, was du über das Ergebnis annehmen kannst: Der Server streamt Fragmente, ohne sie zu validieren, sodass der akkumulierte String möglicherweise kein gültiges JSON ist.
Wenn ein tool_use-Content-Block streamt, enthält das initiale content_block_start-Event input: {} (ein leeres Objekt). Dies ist ein Platzhalter. Die eigentliche Eingabe kommt als eine Reihe von input_json_delta-Events an, die jeweils ein partial_json-String-Fragment enthalten. Um die vollständige Eingabe zusammenzusetzen, verkette diese Fragmente und parse das Ergebnis, wenn der Block geschlossen wird.
Wenn dein SDK einen Akkumulator-Helper bereitstellt (wie es die Python-, TypeScript-, Go-, Java- und Ruby-Tabs im vorherigen Beispiel tun), übernimmt dieser das für dich. Das manuelle Muster ist für SDKs ohne Helper gedacht oder wenn du volle Kontrolle darüber haben möchtest, wie die Eingabe zusammengesetzt wird.
Der Akkumulations-Vertrag:
content_block_start mit type: "tool_use" initialisiere einen leeren String: input_json = ""content_block_delta mit type: "input_json_delta" hänge an: input_json += event.delta.partial_jsoncontent_block_stop parse den akkumulierten StringSichere das Parsen ab, wie es die folgenden SDK-Beispiele tun. Eine Antwort kann auch bei max_tokens mitten in einem Parameter stoppen. Prüfe den Stop-Reason und entscheide, ob du die Anfrage mit einem höheren max_tokens wiederholst oder die partielle Eingabe reparierst.
Die Typ-Diskrepanz zwischen dem initialen input: {} (Objekt) und partial_json (String) ist beabsichtigt. Das leere Objekt markiert den Slot im Content-Array. Die Delta-Strings bauen den eigentlichen Wert auf.
client = anthropic.Anthropic()
tool_inputs: dict[int, str] = {} # index -> accumulated JSON string
with client.messages.stream(
model="claude-opus-4-8",
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:
# Der akkumulierte String ist nicht garantiert gültiges JSON.
# Siehe „Umgang mit ungültigem JSON in Tool-Antworten“ auf dieser Seite.
print(f"Invalid tool input: {raw_input}")
else:
print(f"Tool input: {parsed}")Auf Fragmente zu reagieren und sie zusammenzusetzen sind getrennte Anliegen. Das erste Beispiel reagiert auf jedes Fragment, sobald es ankommt, und überlässt das Zusammensetzen trotzdem dem SDK in den Tabs, die einen Akkumulator-Helper verwenden. Verwende das manuelle Muster, wenn du keinen Akkumulator-Helper verwendest oder wenn du volle Kontrolle über das Zusammensetzen haben möchtest.
Mit feingranularem Tool-Streaming kann die akkumulierte Eingabe für einen Tool-Aufruf ungültiges oder unvollständiges JSON sein. Wenn das der Fall ist, kannst du das Tool nicht ausführen – melde den Fehler stattdessen an Claude zurück. Der content eines Tool-Results muss kein JSON sein, aber das Einbetten des rohen Strings in ein JSON-Objekt unter einem einzelnen Key macht für Claude eindeutig, dass du ungültiges JSON erhalten hast, und bewahrt die ursprüngliche Eingabe für das Debugging:
{
"INVALID_JSON": "<the unparseable input you received>"
}Gib den Wrapper, serialisiert als String, als content eines Tool-Result-Content-Blocks zurück, bei dem is_error auf true gesetzt ist:
{
"type": "tool_result",
"tool_use_id": "toolu_01A09q90qw90lq917835lq9",
"is_error": true,
"content": "{\"INVALID_JSON\": \"<the unparseable input you received>\"}"
}Erstelle den Wrapper mit deiner JSON-Bibliothek statt durch String-Verkettung, damit Anführungszeichen und andere Sonderzeichen in der ungültigen Eingabe korrekt escaped werden.
Verstehe, wie das Kontextfenster funktioniert, wie erweitertes Denken und Tool-Nutzung darauf angerechnet werden und wie du den Kontext verwaltest, wenn Gespräche wachsen.
Streame Messages-API-Antworten inkrementell mit Server-Sent Events, einschließlich Text-, Tool-Nutzungs- und Deltas für erweitertes Denken.
Parse tool_use-Blöcke, formatiere tool_result-Antworten und behandle Fehler mit is_error.
Verzeichnis der von Anthropic bereitgestellten Tools und Referenz für optionale Eigenschaften von Tool-Definitionen.
Was this page helpful?