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:
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)data: {"type":"response.created", ...}
data: {"type":"response.output_text.delta","delta":"Once"}
data: {"type":"response.output_text.delta","delta":" upon"}
data: {"type":"response.completed","response":{..., "usage":{...}}}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.
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).
curl "https://api.soleapi.com/v1beta/models/gemini-2.5-pro: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.