DocsGuidesStreaming

Streaming

SSE event formats in all three dialects, plus parsing tips.

All three dialects support streaming over Server-Sent Events (SSE): deltas are pushed as the model generates, so you don't wait for the full response. Event formats differ per dialect and match the official APIs.

OpenAI format (Responses)

Set "stream": true in the request body. Events carry a type field such as response.created, response.output_text.delta, response.completed:

python
stream = client.responses.create(
    model="claude-fable-5",
    input="Tell me a story",
    stream=True,
)
for event in stream:
    if event.type == "response.output_text.delta":
        print(event.delta, end="", flush=True)

Anthropic format (Messages)

Also "stream": true, but events use SSE named events (event: + data: lines): message_start → content_block_start → repeated content_block_delta → content_block_stop → message_delta → message_stop.

SSE
event: message_start
data: {"type":"message_start","message":{...}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Once"}}

event: message_stop
data: {"type":"message_stop"}

Gemini format

Call the :streamGenerateContent action with ?alt=sse; each data: line is a GenerateContentResponse fragment with delta text in candidates[].content.parts[].text. Without alt=sse, you get one complete JSON array (non-streaming).

stream.sh
curl "https://soleapi.com/v1beta/models/gemini-3.7-flash:streamGenerateContent?alt=sse" \
  -H "x-goog-api-key: $SOLEAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"contents": [{"parts": [{"text": "Tell me a story"}]}]}'

Parsing tips

  • SSE events are delimited by blank lines, but TCP segmentation can split one event across reads — buffer input and parse only complete frames. This is the most common pitfall in hand-written parsers.
  • For long generations, raise your read timeout to 5+ minutes so reasoning models with long silent stretches aren't cut off client-side.
  • Treat reconnects as new requests (streams cannot resume mid-way), and consider falling back to a non-streaming call.
  • When rendering UI, batch deltas with throttling so each tiny delta doesn't trigger a separate repaint.
  • Token usage for streamed requests arrives in the final event; billing settles when the stream ends.