Overview
Knowledge Stack provides two real-time communication channels:- WebSocket — For receiving instant notifications about events in your tenant (e.g., document ingestion completed)
- Server-Sent Events (SSE) — For streaming AI assistant responses token-by-token
WebSocket Notifications
Connecting
Connect to the WebSocket endpoint at:ks_uat). On a successful connection, you will receive a confirmation message:
Subscribing to Channels
After connecting, subscribe to notification channels by sending JSON messages:Channel Security
Two security rules are enforced on all subscriptions:- The
tenant_idin the channel must match your authenticated tenant - For user channels, the
user_idmust match your authenticated user
Notification Events
| Event | Description | Key Fields |
|---|---|---|
document_ingestion_completed | A document has finished processing | document_id, document_version_id, workflow_id |
Server Messages
| Event | Description |
|---|---|
connection_established | Connection accepted, includes your connection_id |
subscribed | Successfully subscribed to a channel |
unsubscribed | Successfully unsubscribed from a channel |
error | An error occurred (includes code and message) |
Connection Close Codes
| Code | Meaning |
|---|---|
| 4401 | Unauthorized — invalid or missing session |
| 4403 | Forbidden — you are not a member of this tenant |
| 4503 | Service unavailable — real-time features are disabled |
| 1001 | Server shutting down |
Keepalive
The connection uses standard WebSocket ping/pong frames (RFC 6455) for keepalive. No application-level heartbeat is needed.SSE Thread Streaming
Endpoint
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
last_message_id | UUID | No | The ID of the last message you received. Used for reconnection. |
last_entry_id | string | No | The stream entry ID of the last event you received. Required when last_message_id is provided. |
Streaming Events
When the AI assistant generates a response, you receive a sequence of SSE events:| Event | Description |
|---|---|
message_start | A new assistant message is beginning |
text_start | A text segment is starting |
text_delta | A chunk of text content (the delta field contains the text) |
text_end | The current text segment is complete |
step | A tool call or processing step occurred |
citations | Source citations for the response |
message_end | The assistant message is complete |
done | The stream is finished (data: [DONE]) |
step events may be interleaved during processing.
SSE Event Format
Each event follows this format:Reconnection
If your connection drops while an assistant response is still streaming, you can reconnect with replay:replay_complete event when replay is finished:
message_not_streaming event instead. In that case, fetch the complete message via the REST API:
Best Practices for SSE
- Open a new SSE connection when you navigate to a thread
- For reconnection mid-stream, always include both
last_message_idandlast_entry_id - Do not rely on
EventSourceauto-reconnect — close the connection and open a new one with updated parameters - The stream self-terminates when done. Open a new connection for the next message.
SSE Keepalive
The server sends SSE comment pings (: ping) every 30 seconds to keep the connection alive.
Configuration
If you are self-hosting Knowledge Stack, these settings control the real-time notification system:| Setting | Default | Environment Variable | Description |
|---|---|---|---|
| Redis URL | DISABLED | REDIS_URL | Redis connection string. Set to DISABLED to turn off real-time features. |
| Max connections | 20 | REDIS_MAX_CONNECTIONS | Redis connection pool size |
| Stream TTL | 30 min | WS_STREAM_TTL_MINUTES | How long stream entries are retained |
| SSE buffer size | 1024 | SSE_QUEUE_SIZE | Maximum buffered events per subscriber |
Error Handling
| Scenario | What Happens |
|---|---|
| Redis is disabled | WebSocket returns close code 4503. SSE returns an error. |
| Redis goes down during use | The system automatically retries with exponential backoff |
| Your SSE client disconnects | Your subscription is cleaned up automatically |
| SSE buffer fills up | Your subscription is removed to prevent memory issues |
| Message is no longer streaming | SSE returns message_not_streaming — fetch the message via REST instead |
