Streaming (setting "stream": true) delivers Claude's response as server-sent events, so users see text appear word by word instead of waiting for the whole answer. Tool use complicates this picture: the arguments Claude wants to pass to your function are a JSON object, and that object is streamed to you in pieces. Understanding how those pieces arrive — and when it is safe to parse them — is the difference between a robust agent loop and one that fails intermittently in production.
The event sequence for a tool call
Every streamed response follows the same skeleton: a message_start event, then for each content block a content_block_start, one or more content_block_delta events, and a content_block_stop; finally message_delta events with top-level changes (like the stop_reason and cumulative usage) and a closing message_stop. Each block carries an index matching its position in the final content array, which is how you keep parallel blocks separate.
For a tool call, the content_block_start announces a tool_use block with the tool's name and id but an empty input. The input then arrives via deltas of type input_json_delta, each carrying a partial_json string fragment. The fragments are not individually valid JSON — one event might contain {"locat and the next ion": "Par. Your job is simple: concatenate every partial_json string for that block index, in order, and parse the accumulated string only after the block's content_block_stop arrives.
json.loads() on a partial_json fragment. Buffer per block index, parse on content_block_stop, then dispatch to your function.from anthropic import AnthropicBedrockMantle
client = AnthropicBedrockMantle(aws_region="us-east-1")
buffers, tools_ready = {}, []
with client.messages.stream(model="anthropic.claude-sonnet-5",
max_tokens=1024, tools=tools,
messages=messages) as stream:
for event in stream:
if event.type == "content_block_start":
buffers[event.index] = ""
elif event.type == "content_block_delta" and \
event.delta.type == "input_json_delta":
buffers[event.index] += event.delta.partial_json
elif event.type == "content_block_stop" and buffers.get(event.index):
tools_ready.append(buffers[event.index]) # parse then execute
Timing quirks worth planning for
Deltas arrive in uneven bursts. Current models emit tool input roughly one complete key/value pair at a time, so there can be noticeable pauses between input_json_delta events while the model works out the next value. Do not treat a quiet stream as a stalled one; the API also sends ping events, which may appear anywhere and can be ignored.
Multiple tool calls interleave by index. When Claude requests several tools in one turn (see parallel tool calls), each tool_use block streams as its own start/delta/stop sequence with its own index. A per-index buffer dictionary, as above, handles this naturally.
Errors can arrive mid-stream. Because the HTTP status was already sent, a failure partway through generation appears as an in-stream error event — for example overloaded_error, the streaming equivalent of an HTTP 529. Treat a stream that ends on an error event as a failed request and retry it; do not dispatch tools based on a partially received input.
Usage numbers are cumulative. Token counts reported in message_delta events are running totals, not per-event increments — read the last one, don't sum them.
Fine-grained streaming and SDK helpers
By default, buffering means your application cannot act until a tool block completes. For tools with large inputs — say, a code-writing tool streaming a whole file — Anthropic offers fine-grained tool streaming, enabled per tool with eager_input_streaming, so parameter values stream out with less internal buffering. The official SDKs also do most of this assembly for you: the Python SDK's streaming helpers expose accumulated messages so you can read complete tool_use blocks at the end while still rendering text deltas live. Hand-rolled SSE parsing is only necessary if you are not using an SDK.
Platform notes
Streaming, tool use, and fine-grained tool streaming are generally available across the Claude API, Claude Platform on AWS, Amazon Bedrock, Google Vertex AI, and Microsoft Foundry, with the same event vocabulary. That makes the buffering logic above portable: only the client class and model ID change per platform.
Where to go next
For the transport layer underneath these events — connection handling, reconnection, and parsing — read Server-Sent Events. For what to do once a tool has run, including failures, see Tool Result Errors.