Fluxio
← 返回博客

Anthropic Streams: message_start to message_stop

SSE 与接口EN

§1 Step 1: Enable the Anthropic Message Stream

An Anthropic message stream is a structured sequence, not simply a string arriving in pieces. Enable streaming by setting stream to true in your Messages API request. The response uses server-sent events, or SSE. Anthropic's SDK streaming helpers can handle event iteration and message accumulation for you. ([platform.claude.com](https://platform.claude.com/docs/en/build-with-claude/streaming?trk=article-ssr-frontend-pulse_little-text-block&utm_source=openai))

For your first implementation, request a short greeting from Claude Opus 5.5. Keep the prompt simple so you can inspect the lifecycle before adding tools. Design your application around three responsibilities: decoding events, assembling message state, and updating the interface.

§2 Step 2: Decode SSE Before Reading JSON

SSE uses UTF-8 text, with blank lines separating events. An event can contain an event name and multiple data lines. Network reads do not define these boundaries, so buffer incoming text until a complete event is available, then parse its assembled data as JSON. ([html.spec.whatwg.org](https://html.spec.whatwg.org/multipage/server-sent-events.html))

Keep transport parsing separate from application behavior. Test your parser with one event split across several reads and several events delivered together. Neither case should duplicate text, lose characters, or trigger premature JSON parsing.

§3 Step 3: Initialize State at message_start

The message_start event supplies the initial message object, including its identifier and an empty content array. Create your message accumulator here, rather than treating this event as visible answer text. ([platform.claude.com](https://platform.claude.com/docs/en/build-with-claude/streaming?trk=article-ssr-frontend-pulse_little-text-block&utm_source=openai))

Give each request its own accumulator. Store lifecycle status separately from displayed text, and associate diagnostics with the message identifier. This makes overlapping requests easier to debug without accidentally appending one response to another.

§4 Step 4: Assemble Indexed Content Blocks

Each content block opens with content_block_start, receives updates through content_block_delta, and closes with content_block_stop. Its index identifies its position in the final content array. For text_delta updates, append delta.text to the matching block. ([platform.claude.com](https://platform.claude.com/docs/en/build-with-claude/streaming?trk=article-ssr-frontend-pulse_little-text-block&utm_source=openai))

For example, two text updates containing Hello and a following exclamation mark should produce one continuous greeting. Treat each update as a fragment, not an entire answer or a guaranteed single token.

  • – Maintain separate buffers for each block index.
  • – Dispatch updates according to their delta type.
  • – Render accumulated text without replacing unrelated blocks.
  • – Keep block completion distinct from message completion.

§5 Step 5: Buffer Tool Inputs Before Execution

Tool inputs require a different assembly path. Accumulate the partial_json strings from input_json_delta updates, then parse and validate the completed input before executing a tool. Fine-grained tool streaming can deliver invalid or incomplete JSON, particularly when generation reaches its token limit. ([platform.claude.com](https://platform.claude.com/docs/en/agents-and-tools/tool-use/fine-grained-tool-streaming))

Make validation an explicit execution gate. Check the tool name, required arguments, and application permissions before allowing side effects. Never interpret the arrival of an opening brace as permission to run an operation.

§6 Step 6: Apply message_delta Before message_stop

The message_delta event updates message-level information, including the stop reason and usage. Streamed usage counts are cumulative, so do not add successive totals together. The final message_stop event closes the message lifecycle. ([platform.claude.com](https://platform.claude.com/docs/en/build-with-claude/streaming?trk=article-ssr-frontend-pulse_little-text-block&utm_source=openai))

Read the stop reason before deciding what happens next. An end_turn value indicates a natural finish, max_tokens signals the configured output limit, and tool_use requires tool handling rather than treating the response as an ordinary completed answer. ([platform.claude.com](https://platform.claude.com/docs/en/build-with-claude/handling-stop-reasons))

§7 Step 7: Handle Interruptions and Relay Boundaries

Streams can contain ping events, in-stream errors, and unfamiliar event types. Handle these without appending them to answer text. ([platform.claude.com](https://platform.claude.com/docs/en/build-with-claude/streaming?trk=article-ssr-frontend-pulse_little-text-block&utm_source=openai)) If the connection disappears before message_stop, mark your local result incomplete instead of presenting transport closure as successful completion.

For a streaming-first, pay-per-token relay, consider Fluxio when you want one key across providers. Its OpenAI SDK compatibility fits applications already using that client interface. Keep protocol-specific decoding behind an adapter: do not assume an OpenAI-style stream exposes Anthropic's native event names. Confirm the selected endpoint's format before reusing this walkthrough's dispatcher.

Sign up for Fluxio.

创建 Fluxio 账号 →

顺流再读几篇