Stream responses without corrupting them.

1. Set stream true and expect SSE. The response is a stream of server-sent events. If you do not need to process text as it arrives, use the SDK's stream helper that returns the complete Message object identical to a non-streaming create: less code, fewer bugs.
2. Handle events in order per content block. Track message_start, then per block: content_block_start, a series of content_block_delta events, then content_block_stop. Deltas include text deltas, thinking deltas, input_json deltas for tool use, and citations_delta for citations. Accumulate each delta type into its block; never render a delta before its block started.
3. Reassemble tool calls from input_json deltas. Tool use streams the arguments as partial JSON across many input_json_delta events. Concatenate the partial_json strings for the block and parse only at content_block_stop. Parsing mid-stream is the classic bug.
4. Accumulate citations_delta per text block. Each citations_delta carries one citation appended to the current text block's citations list. Only render the citation UI once the block stops.
5. Detect the real end. message_delta carries the stop_reason and final usage; message_stop ends the stream. A stream that ends without message_stop was cut: treat the response as incomplete and retry or resume, do not present a truncated answer as final.
6. Reconnect safely. On a dropped connection, you cannot resume a stream mid-block: start a new request. If the request is expensive, consider whether the non-streaming call plus polling fits better than a fragile long-lived stream.