Feingranulares Tool-Streaming
Streame Tool-Eingaben ohne serverseitige JSON-Pufferung für latenzempfindliche Anwendungen.
„Fine-grained tool streaming“ (feingranulares Tool-Streaming) liefert die Eingabe eines Tools an deinen Client, während Claude sie generiert, ohne serverseitige Pufferung oder JSON-Validierung. Das Überspringen des Pufferungsschritts verkürzt die Zeit bis zum ersten Fragment eines großen Parameters, etwa eines Dokuments oder eines Codeblocks, und die Fragmente kommen über dieselben Streaming-Nachrichten-Events an wie bei der standardmäßigen Tool-Nutzung.
So verwendest du feingranulares Tool-Streaming
Alle Modelle unterstützen feingranulares Tool-Streaming auf der Claude API, Amazon Bedrock, Claude Platform on AWS, 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; lässt du es weg, erhältst du standardmäßiges gepuffertes Streaming, bei dem die API jeden Parameterwert puffert und validiert, bevor sie ihn zurückstreamt. Die Ausnahme ist eine Anfrage, die noch den veralteten Beta-Header fine-grained-tool-streaming-2025-05-14 sendet, der feingranulares Streaming für Tools aktiviert, bei denen das Feld nicht gesetzt ist. Das Feld pro Tool ersetzt diesen Header, und ein explizites false behält gepuffertes Streaming für ein Tool bei, selbst wenn eine Anfrage den Header noch sendet. Der veraltete Header kann nicht mit einem Toolset-Eintrag für Computer Use oder Browser Use kombiniert werden: Die API lehnt eine Anfrage ab, die beides sendet. Entferne daher den Header und setze eager_input_streaming bei den benutzerdefinierten Tools, die es benötigen. 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 sie beim Hereinstreamen zu beobachten:
client = anthropic.Anthropic()
with client.messages.stream(
max_tokens=65536,
model="claude-opus-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}")Jeder Tab aktiviert feingranulares Streaming für das make_file-Tool. Die SDK-Tabs geben jedes Eingabefragment in dem Moment aus, in dem es ankommt, und geben dann die vollständige gesammelte 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 für einen 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 und enthalten weniger Umbrüche mitten im Wort.
Sammeln von Tool-Eingabe-Deltas
Der Sammelvertrag ist derselbe wie beim standardmäßigen Tool-Use-Streaming, daher gilt dieser Abschnitt mit und ohne eager_input_streaming. Siehe Input JSON delta in Streaming-Nachrichten 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 gesammelte String möglicherweise kein gültiges JSON ist.
Wenn ein tool_use-Content-Block gestreamt wird, enthält das anfängliche content_block_start-Event input: {} (ein leeres Objekt). Dies ist ein Platzhalter. Die eigentliche Eingabe kommt als 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-Helfer 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 Helfer gedacht oder für den Fall, dass du volle Kontrolle darüber haben möchtest, wie die Eingabe zusammengesetzt wird.
Der Sammelvertrag:
- Bei
content_block_startmittype: "tool_use"initialisiere einen leeren String:input_json = "" - Für jedes
content_block_deltamittype: "input_json_delta"hänge an:input_json += event.delta.partial_json - Bei
content_block_stopparse den gesammelten String
Sichere 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 unvollständige Eingabe reparierst.
Die Typabweichung zwischen dem anfänglichen input: {} (Objekt) und partial_json (String) ist beabsichtigt. Das leere Objekt markiert den Platz 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-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:
# 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}")Umgang mit ungültigem JSON in Tool-Antworten
Beim feingranularen Tool-Streaming kann die gesammelte 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, also melde den Fehler stattdessen an Claude zurück. Der content eines Tool-Ergebnisses muss kein JSON sein, aber wenn du den rohen String in ein JSON-Objekt unter einem einzelnen Schlüssel verpackst, ist für Claude eindeutig, dass du ungültiges JSON erhalten hast, und die ursprüngliche Eingabe bleibt für das Debugging erhalten:
{
"INVALID_JSON": "<the unparseable input you received>"
}Gib den Wrapper, zu einem String serialisiert, als content eines Tool-Ergebnis-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>\"}"
}Nächste Schritte
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-Use- und Extended-Thinking-Deltas.
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?