Skip to content

Streaming & SSE

Soxom supports Server-Sent Events (SSE) for real-time data streaming, ideal for AI/LLM applications and live updates.

streaming:
sse:
enabled: true
# Hide sentinel/termination events from SDK users
sentinel_events:
- "[DONE]"
- "END"

Many streaming APIs use sentinel events to signal end of stream:

data: {"content": "Hello"}
data: {"content": " world"}
data: [DONE]

Configure sentinel_events to automatically filter these out.

Define streaming endpoints with text/event-stream content type:

paths:
/chat/completions:
post:
operationId: createChatCompletion
summary: Create a chat completion
description: |
When stream: true, returns Server-Sent Events.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ChatCompletionRequest'
responses:
"200":
description: Chat completion response
content:
# Non-streaming response
application/json:
schema:
$ref: '#/components/schemas/ChatCompletion'
# Streaming response
text/event-stream:
schema:
$ref: '#/components/schemas/ChatCompletionChunk'
components:
schemas:
ChatCompletionRequest:
type: object
required:
- model
- messages
properties:
model:
type: string
messages:
type: array
items:
$ref: '#/components/schemas/ChatMessage'
stream:
type: boolean
default: false
ChatCompletionChunk:
type: object
properties:
id:
type: string
choices:
type: array
items:
type: object
properties:
delta:
type: object
properties:
content:
type: string
finish_reason:
type: string
nullable: true
// Enable streaming with stream: true
const stream = await client.chat.completions.create({
model: "gpt-4",
messages: [
{ role: "user", content: "Write a haiku about coding" }
],
stream: true
});
// Iterate over chunks
for await (const chunk of stream) {
// Each chunk contains incremental content
const content = chunk.choices[0]?.delta?.content;
if (content) {
process.stdout.write(content);
}
}

Same endpoint without streaming:

// Non-streaming (default)
const completion = await client.chat.completions.create({
model: "gpt-4",
messages: [
{ role: "user", content: "Write a haiku about coding" }
]
});
console.log(completion.choices[0].message.content);

Soxom supports all standard SSE fields:

FieldDescription
idEvent identifier
eventEvent type
dataEvent payload (JSON parsed automatically)
retryReconnection time
id: 1
event: message
data: {"content": "Hello"}
id: 2
event: message
data: {"content": " world"}
event: done
data: [DONE]
const stream = await client.events.subscribe();
for await (const event of stream) {
switch (event.type) {
case 'message':
console.log('Message:', event.data);
break;
case 'error':
console.error('Error:', event.data);
break;
case 'heartbeat':
// Ignore heartbeats
break;
}
}
const stream = await client.chat.completions.create({
model: "gpt-4",
messages: [...],
stream: true
});
// Collect all content
let fullContent = "";
for await (const chunk of stream) {
fullContent += chunk.choices[0]?.delta?.content ?? "";
}
console.log(fullContent);
try {
const stream = await client.chat.completions.create({
model: "gpt-4",
messages: [...],
stream: true
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}
} catch (error) {
if (error instanceof StreamError) {
console.error("Stream error:", error.message);
}
}
  1. Use streaming for large responses - AI completions, file processing
  2. Handle partial data - Process chunks as they arrive
  3. Implement cancellation - Allow users to abort long streams
  4. Set appropriate timeouts - Streaming may need longer timeouts
  5. Filter sentinel events - Configure sentinel_events to hide them