SPB Git forge

spb/doc-api

Public
2commits 1branches 0releases
15.7 MBsize
maindefault branch
13 days agolast push
Python 88.3% TypeScript 7.6% Shell 4.1%
3.1 KB

# Streaming tool calls and fine-grained tool streaming

Status: DOCUMENTED · LIVE_VERIFIED 2026-09-18 (b1 buffered, b2 eager_input_streaming:true, b3 legacy header; claude-haiku-4-5-20251001). Sources: Fine-grained tool streaming · Streaming messages · Server tools — streaming. Last verified: 2026-09-18.

# Event sequence for a tool_use block (live b1, tool_choice: any)

text
message_start            usage.input_tokens=676
content_block_start [0]  {"type":"tool_use","id":"toolu_01VJ5…","name":"get_weather","input":{},"caller":{"type":"direct"}}
ping
content_block_delta [0]  {"type":"input_json_delta","partial_json":""}
content_block_delta [0]  {"type":"input_json_delta","partial_json":"{\"locat"}
content_block_delta [0]  {"type":"input_json_delta","partial_json":"ion\": \""}
content_block_delta [0]  {"type":"input_json_delta","partial_json":"San Fra"}
content_block_delta [0]  {"type":"input_json_delta","partial_json":"ncisco,"}
content_block_delta [0]  {"type":"input_json_delta","partial_json":" CA\"}"}
content_block_stop  [0]
message_delta            {"stop_reason":"tool_use","stop_sequence":null,"stop_details":null,"container":null} usage.output_tokens=41
message_stop

Accumulate partial_json strings and json.loads at content_block_stop. input: {} in content_block_start is a placeholder. message_delta.delta carries stop_details and container fields (live; container is set when code execution ran).

# Fine-grained (eager) streaming

Set "eager_input_streaming": true on a custom tool (per tool; false keeps buffered streaming even when the legacy header is present). No beta header needed since 2026-02-05; the legacy anthropic-beta: fine-grained-tool-streaming-2025-05-14 still works and enables it for tools that leave the field unset (b3 produced the same fragments as b2). The header is rejected together with computer_toolset_20260801 / browser_toolset_20260801 entries.

Mode Fragments seen live (same prompt) Guarantees
buffered (default) 6 short chunks, each key/value validated before emission; delays between events accumulated string is valid JSON
eager 4 longer chunks ({"location": "San, Francisco, CA, "}) no server-side buffering or validation → may be partial/invalid JSON, especially at stop_reason: max_tokens; guard the parse and return {"INVALID_JSON": raw} as an is_error tool_result

Server tools stream the same way: server_tool_use gets input_json_deltas, the *_tool_result block arrives whole in a single content_block_start (no deltas; pause while the tool runs, ping keepalives ~30 s). Toolset members always arrive as one complete input_json_delta.

Examples: examples/anthropic/tools/fine-grained-streaming/basic.{sh,py}. Test: tests/anthropic/test_tools.py::test_streaming_input_json_delta.