Skip to main content
Praxis AI can stream model output token-by-token so your UI can render responses as they are generated. There are two mechanisms: HTTP Server-Sent Events (SSE) — the recommended, stateless approach for most integrations — and Socket.IO for persistent, bidirectional real-time connections (typically browser clients). Start with SSE unless you specifically need a live socket.

HTTP Streaming with Server-Sent Events (SSE)

Start here. SSE is the recommended way to stream responses for most integrations. It’s a pure HTTP, stateless endpoint with nothing to manage beyond a standard request — ideal for automation, SDKs, and server-side code. Reach for Socket.IO only when you specifically need a persistent, bidirectional real-time connection (typically a browser app).
Praxis AI offers a pure HTTP streaming endpoint using Server-Sent Events (SSE). This approach is ideal for:
  • Server-side applications (Node.js, Python, Go, etc.)
  • Automation, agents, and orchestration tools
  • Environments where WebSockets are restricted
  • Simpler integrations without persistent socket connections
  • SDK and CLI tool development
The SSE streaming endpoint uses the same JWT authentication as other REST endpoints. No Socket.IO connection is required.

Endpoint

Request Headers

Request Body

cURL Example

Use -s to suppress progress output and -N to disable buffering, so SSE chunks appear in real time.

Response Headers

Response Format

The endpoint returns text/event-stream; charset=utf-8 content type with SSE-formatted JSON chunks. Each line is prefixed with data: followed by a JSON object and two newlines. Example SSE Response:
The prompt field on stream events is cumulative (full response up to this point); the delta field contains only the new characters since the last event. Use delta for incremental UI rendering and prompt for the current full text.
thinking events are gated by an institution-level Display Thinking Details toggle (default on). When disabled, no thinking events fire and the underlying History record stores no thinking text. Personal users (no institution) always receive thinking events. Providers that do not expose thinking (Mistral) simply emit no thinking events. OpenAI emits summary-only thinking — OpenAI hides raw chain-of-thought by policy.
Bedrock Opus 4.6/4.7 reasoning is opaque. These models use Anthropic’s adaptive thinking mode, which emits an encrypted reasoning signature only — no plaintext. No thinking events fire and no lightbulb appears in the UI even when the toggle is on. To see plaintext reasoning on Bedrock, use Claude Sonnet 3.7+ or Opus 4.0/4.5 (standard thinking with budget_tokens). Plaintext reasoning is also available on Anthropic Direct API, Google Gemini 2.5+, xAI Grok 3-mini / 4.x, and OpenAI Responses API (summary-only).
Thinking is collected per tool round — each round of model output before/after a tool call gets its own entry, keyed by id (round-0, round-1, …). Intermediate frames within a round are append-only deltas; the round closes with a single done: true frame carrying the authoritative full text and (for Anthropic / Bedrock) a signature used for provider-side multi-step continuation.

Node.js Client Example

Using Fetch API (Browser/Node.js 18+)

Cancelling an HTTP Stream

To cancel an in-flight HTTP stream request, you can abort the fetch request:
The HTTP SSE endpoint is stateless - each request is independent. This makes it ideal for serverless functions, CLI tools, and microservices where maintaining WebSocket connections is impractical.

Comparing Socket.IO vs HTTP SSE


Streaming with Socket.IO

Socket.IO is an alternative to the HTTP SSE method above. Prefer it when you need a persistent, bidirectional real-time connection — for example, an interactive browser client. For automation, SDKs, CLIs, and most server-side integrations, use SSE instead.
You can connect to Praxis AI middleware to receive streaming events while REST requests are in-flight. The server emits stream chunks to your socket; you must include the current socket ID in Q&A requests to link streams to your session.

1 Install the Socket.IO Client

2 Connect and register your user

3 Listen for streaming and diagnostic events

These are typical events payload received from the stream
prompt: Contains the full response from the beginning of the interaction. delta Contains only the last text segment reported type: “STREAM” for messages streamed by the LLM
Note that the final response may differ from the prompt returned while streaming.

Event types

All RECEIVE_STREAM payloads carry a type field. Branch on it to handle each kind:
THINKING — model reasoning stream
THINKING events surface the model’s internal reasoning text (a.k.a. chain-of-thought / “thinking” mode) for the providers that expose it: Anthropic, AWS Bedrock, Google Gemini, OpenAI (summary only — OpenAI hides raw chain-of-thought by policy), and xAI. Mistral does not expose thinking at all and emits no THINKING events. Thinking is collected per tool round — each round of model output before/after a tool call gets its own entry, keyed by id of the form round-0, round-1, etc. Frames within a round are append-only deltas; the round closes with a single done: true frame carrying the authoritative full text and (for Anthropic / Bedrock) a signature for provider-side continuation.
The THINKING stream is gated by an institution-level Display Thinking Details toggle (default on). When the institution disables the toggle, no THINKING events fire and the underlying History record stores no thinking text. Personal users (no institution) always receive thinking events.
Render thinking deltas in a collapsible UI block separate from the main answer — users tend to find the chain-of-thought interesting as context, not as the answer itself. The Praxis UI shows thinking under a 💡 lightbulb <details> toggle.

4 Include socketId in your Q&A API requests

The server requires the active Socket.IO session ID to stream chunks to your client. Include socketId in requestArgs.
If you wrap Q&A calls, pass socketId from your Socket.IO context into the wrapper and expose a stream callback to consume RECEIVE_STREAM chunks.]

5 Manage reconnections

When the QANDA request response includes "streamingFailed": true, it indicates that the middleware has lost the backend Socket ID mapping (user email to client socket ID), preventing it from communicating response chunks back to the client. This typically occurs when multiple browser windows or tabs are open for the same user email, causing them to compete for the same backend session and overwriting each other’s socket registrations. To resolve this issue, you can re-establish the socket connection to re-register the most current client handle and restore proper communication between the middleware and the active client session.

6 Abort requests

To abort a request while executing, emit a cancel_request event:
The cancel_request message signals the controller API to interrupt the ongoing communication and attempt a graceful termination of the conversation. While the controller works to terminate resources cleanly, there may be a slight delay before the process completes. You will only be charged for any partial response generated up to the point of cancellation.

7 Stop streaming the current request

To stop streaming the current response without aborting the request itself, emit a cancel_streaming event:
cancel_streaming applies only to the current response stream and is cleared automatically before the next interaction.