Skip to main content

Overview

Shannon provides real-time event streaming through Server-Sent Events (SSE) and WebSocket protocols. Use streaming to monitor task execution, display progress, and receive results as they’re generated.
Authentication: Streaming endpoints require the same headers as other APIs. Browsers cannot send custom headers with EventSource.
  • Development: set GATEWAY_SKIP_AUTH=1.
  • Production: proxy SSE via your backend and inject X-API-Key or Bearer headers. For SSE endpoints, the api_key query parameter is supported as a fallback (e.g., ?api_key=sk_...). For all other endpoints, use headers exclusively.
Streaming Limits:
  • Timeout: Streams automatically close after 5 minutes of inactivity
  • Buffer Size: Maximum 1MB buffered data per connection
  • Usage Metadata: Token counts and costs now available for all LLM providers (OpenAI, Anthropic, Google, Groq, xAI)

Endpoints

POST /api/v1/tasks/stream

The easiest way to submit a task and immediately start streaming its events. This endpoint combines task submission with streaming setup in one call.
Best for frontend applications: This endpoint is perfect for real-time UIs where you want to show progress immediately after submitting a task.

Authentication

Required: Yes
Or:

Request Body

Response

Status: 201 Created Body:

Response Fields

Example: JavaScript/TypeScript

Example: React Hook

Example: Vue 3 Composition API

Example: Python

Why use this endpoint? The unified endpoint ensures you start streaming immediately after submission, preventing any missed events that could occur if you submit and then connect separately.

Server-Sent Events (SSE)

GET /api/v1/stream/sse

Real-time event streaming using Server-Sent Events.

Authentication

Required: Yes

Query Parameters

Event Format

Each event follows SSE specification:

Example Request

Example Response

Event ID format: The id field uses Redis stream IDs (e.g., 1719000000000-0), NOT simple integers. You must use these exact IDs when reconnecting with last_event_id. See Reconnection below.

WebSocket

GET /api/v1/stream/ws

Bidirectional streaming via WebSocket.

Authentication

The gateway authenticates WebSocket connections via headers only (X-API-Key or Authorization). Browsers cannot set custom headers during the WebSocket handshake. For browser usage:
  • Run locally with GATEWAY_SKIP_AUTH=1, or
  • Use a reverse proxy that injects the header before forwarding to the gateway.
Header-based examples for server environments: Node (ws):
Python (websockets):
Passing the API key in the query string or via an “auth” message after connect is not supported by the gateway.

Message Types

Client → Server:
Server → Client:

OpenAI-Compatible Streaming

Shannon also provides an OpenAI-compatible streaming endpoint at /v1/chat/completions that translates Shannon events into the standard OpenAI chat.completion.chunk format. This allows you to use OpenAI SDKs directly with Shannon. For complete documentation on the OpenAI-compatible API, including request/response schemas, available models, Shannon-specific extensions (shannon_events), and SDK usage examples, see the OpenAI-Compatible API Reference.

Event Types

Core Events

Agent Events

Tool Events

LLM Events

For most integrations, listen to thread.message.delta (streaming text) and thread.message.completed (final result with usage metadata) rather than LLM_PARTIAL/LLM_OUTPUT.

Progress & System Events

Stream Lifecycle Events

Over SSE, the STREAM_END lifecycle event is delivered as an SSE event named done with data: [DONE] (plain text, not JSON). Over WebSocket, it appears as a normal JSON event with "type": "STREAM_END".

Team & Approvals

Code Examples

Python with httpx (SSE)

Python - Stream with Event Filtering

JavaScript/Node.js (SSE)

JavaScript/Node.js - WebSocket (ws)

Go (SSE)

Bash/curl (SSE)

Use Cases

1. Real-Time Progress Display

2. Log All Events to File

3. Collect Tool Usage Metrics

4. React UI Integration

Deep Research Streaming

Deep Research tasks take 2-10 minutes. Use context.force_research to trigger Deep Research through the Task API:
Control research depth with context.research_strategy:
Chat API vs Task API for Deep Research: The Chat API (/v1/chat/completions with model: "shannon-deep-research") can also trigger Deep Research, but its streaming format does not include SSE event IDs — so reconnection is impossible. If your platform has connection time limits (e.g., Vercel 5-min limit) or you need to survive page refreshes, use the Task API.

Heartbeat

The server sends a : ping SSE comment every 10 seconds to keep connections alive through proxies and load balancers:
This is an SSE comment (not a JSON message). If you stop receiving pings, the connection is dead — reconnect immediately.

Reconnection

SSE connections may drop due to network issues, proxy timeouts, or platform limits (e.g., Vercel hobby plan: 5-minute connection limit). Shannon supports resuming from where you left off. How it works:
  1. Track the id field of each received SSE event
  2. When disconnected, reconnect with last_event_id parameter
  3. The server replays all events after that ID (buffered ~256 events, 24h TTL)
For platforms with connection time limits, proactively disconnect before the limit:

Page Refresh / Fallback

If the user refreshes the page and you still have the workflow_id:
  1. Check task status: GET /api/v1/tasks/{workflow_id}
  2. If TASK_STATUS_RUNNING → reconnect to SSE
  3. If TASK_STATUS_COMPLETED → display the result from the response
  4. If TASK_STATUS_FAILED → display the error

Python with Reconnection

Best Practices

2. Implement Timeout

3. Filter Events Client-Side

4. Resume from Last Event

Note: last_event_id accepts either a Redis stream ID (e.g., 1700000000000-0) or a numeric sequence (e.g., 42). When numeric, replay includes events with seq > last_event_id.

Comparison: SSE vs WebSocket vs Polling

When to Use Each

  • SSE: Most use cases, real-time monitoring, progress display
  • WebSocket: Interactive applications, bidirectional communication needed
  • Polling (GET /api/v1/tasks/): Legacy systems, no streaming support

Submit Task

POST /api/v1/tasks

Get Status

GET /api/v1/tasks/

Python SDK

Use client.stream()

Notes

Event Retention:
  • Redis: All events stored for 24 hours (real-time streaming)
  • PostgreSQL: Critical events stored for 90 days (historical queries)
  • Use last_event_id to resume streaming if connection drops
Connection Limits:
  • Maximum 100 concurrent streaming connections per API key
  • 5-minute inactivity timeout (automatic connection close)
  • 1MB buffer size limit per connection
  • Consider multiplexing multiple workflows over a single WebSocket