Skip to main content
POST

Streaming Chat Stable

Stream AI model responses token-by-token using . Ideal for real-time chat interfaces.

Authentication Required

Request Body

string
required
User message textValidation (Line 452):
string
Model name or "auto" for random selectionSelection Logic (Lines 468-470):
string
System prompt for chat contextDefault: Implementation-defined and not guaranteed (provider-specific)
integer
Maximum tokens in responseProvider Limits: Model-dependent
number
Sampling temperature (0.0-2.0)Default: Not specified by API contract (provider-defined)
string
Thread UUID (not persisted in streaming mode)Note: Streaming endpoints do NOT write to thread_messages table

Response

Content-Type: text/event-stream (Line 450) Headers (implicit in ASP.NET SSE):

Event Types

object
Incremental text chunk (Lines 486-502)Format:
Emitted: 0+ times during stream
object
Stream completionFormat:
Emitted: Once at end of successful stream
object
Stream error (Lines 456-463, 512-519)Format:
Error Codes:
  • INVALID_REQUEST: Prompt validation failed (Line 459)
  • STREAM_ERROR: Provider or network error (Line 515)

Side Effects

Database Mutations: NONE for streaming endpoints Logging: Internal only (not persisted to user-facing tables) Internal Audit: message_logs table write not enforced by server contract (implementation detail)

Behavior

SSE Implementation (Lines 450, 486-502):
Key Characteristics:
  1. Content-Type set immediately (Line 450)
  2. Each event written as data: {json}\n\n (Line 495)
  3. Immediate flush after each event (Line 496)
  4. Cancellation token monitors client disconnect (Line 504)
Provider Selection (Lines 472-484):
Client Disconnect Handling (Line 504):
  • Passed to provider’s StreamAsync method
  • Provider monitors token and terminates stream on cancellation
  • No error written to client (they already disconnected)
Error Handling (Lines 506-525):
Error Recovery:
  • If stream already started, error event written
  • If stream closed (client disconnect), write attempt silently fails
  • No 500 status code returned (SSE already in progress)
JSON Serialization (Lines 490-494):
  • Null values omitted
  • camelCase property names
  • Single-line JSON (no embedded newlines)

Event Lifecycle

Successful Stream:
Error During Stream:
Client Disconnect:

Constraints

No Dual-Chat Streaming: Only single-chat mode supports streaming No Database Write: Streaming responses NOT persisted to thread_messages table Reason: Partial streams cannot be meaningfully stored Workaround: Use non-streaming /api/arena/chat if persistence required UTF-8 Encoding: All events UTF-8 encoded (Line 464 decoder implicit) Single-Line JSON: Event payloads MUST NOT contain newlines (breaks SSE format) Provider Support: Only providers implementing StreamAsync method support streaming

SSE Format Specification

Event Format:
Field:
  • data: prefix (required)
  • Space after colon
  • JSON object (single line)
  • \n\n double newline (event terminator)
Client Parsing:
  1. Read lines until \n\n
  2. Extract line starting with data:
  3. Parse JSON from position 6 onward
  4. Handle event based on object field

Error Conditions

No HTTP Status Codes: Once SSE starts, errors communicated via events (status already 200)

Edge Cases

  1. Empty prompt: Error event written, stream terminates (Lines 452-463)
  2. Client disconnect mid-stream: Provider cancels, no error event
  3. Provider timeout: Exception caught, error event written if possible
  4. Invalid model name: Fallback to Groq provider (Lines 476-484)
  5. JSON serialization failure: Caught and logged, event skipped (Lines 498-501)
  6. Stream already flushed: Error write attempt fails silently (Lines 520-524)

Performance Characteristics

First Token Latency: Provider-dependent
  • Groq: 100-300ms typical
  • Bytez: Higher latency
Chunk Frequency: Provider-dependent
  • Groq: High frequency (near real-time)
  • Some providers: Batched chunks
Total Stream Time: No timeout enforced in controller
  • Provider-level timeouts apply
  • Client can cancel anytime

Rate Limits

No explicit rate limiting. Provider limits apply:
  • Groq free tier: 30 req/min
  • Streaming counts same as non-streaming
Streaming Advantage: User sees partial response even if rate-limited mid-stream

Client Implementation Notes

Fetch API Recommended: EventSource doesn’t support POST or custom headers Backpressure: Client must read stream continuously or buffer will fill Reconnection: Not automatic, client must implement retry logic Error Handling: Parse ai.error events and display to user