Realtime
A stream holds one connection open and pushes Events as they happen; a client that drops resumes from the last sequence number it saw.
A stream holds one connection open and pushes Events the moment they happen. A client that drops reconnects with the last sequence number it saw and misses nothing.
Three ways to hear an Event
Every Event reaches code in one of three ways. They read the same Events, with the same selectors, under the same Permissions.
| Way | Use it when | Survives a restart |
|---|---|---|
| Watch | A server with a public URL must hear every Event | Yes: the platform retries for three days |
| Stream | A browser, an App, a Dashboard or an agent session wants Events live | Yes: the client resumes from its cursor |
$.on | A script or a long-running worker wants Events in process | No: it hears Events while it runs |
Realtime is the capability behind streams. A stream is a read: it creates no Action and emits no Events of its own.
Open a stream
answerdesk.ai is an Agent as a Service that answers support email for small software companies. Its operator Dashboard shows each Conversation the moment it opens or closes:
Show me each conversation as it happens.Over HTTP the stream is server-sent events. Each frame carries the Event's sequence number as its id, its name as event, and the Event in the delivery shape as data:
id: 40211
event: Conversation.answered
data: {"$id": "https: //api.sb/ answerdesk.ai/ events/ event_40211", "name": "Conversation.answered", "seq": 40211, "data": {"conversation": {"$id": "https: //api.sb/ answerdesk.ai/ conversations/ conversation_9"}}}A stream is the Event list held open: Accept: on GET /events. where takes the filter grammar lists and Watches share: name = Conversation.* and channel = channel_4. A caller sees only the Events its key may read, so a Customer's stream carries only its own Tenant.
An Agent connected over MCP subscribes to the same URL as a resource. The client receives an update notification per Event and reads it in the agent's context.
Resume from a cursor
seq increases by one per Event in a namespace, and Events are kept forever. Any seq is therefore a cursor into the full history.
A browser's EventSource reconnects by itself and sends the last id it saw as Last-Event-ID. The stream continues from the next Event, in order, with nothing skipped. Any other client passes cursor= and gets the same result.
To load history and then go live, open the stream with an old cursor. It replays every matching Event since then at full speed, then keeps the connection open for new ones.
The server sends a comment line every 15 seconds. A client that hears nothing for 45 seconds reconnects with its cursor.
Two-way streams
Web sockets carry the same Events at wss:, with the same select and cursor parameters. Use them when the client also talks back.
A web socket client changes its selection without reconnecting, and it sends presence and typing to a Channel's members. Presence and typing reach the Channel live and are never stored.
Stream a result token by token
A Verb whose result is generated text can stream it. answerdesk.ai drafts each help article with Content.draft, and its App shows the draft as it is written:
const call = $.Content.draft({ kind: 'article', brief: 'How to reset a password from the sign-in page' })
const editor = document.querySelector('#draft')!
for await (const chunk of call.stream()) {
editor.append(chunk.delta)
}
const action = await call.settledOver HTTP, send Accept: with the call. Frames named delta carry the text as it is generated, and a last frame named action carries the finished Action.
The streamed text is a preview of the result, not a second result. The Action records the final text once, and only that version emits Events or reaches a Watch.
Limits
Open connections count against a Limit per Tenant, set by the Startup's plan. One Channel carries 1,000 Messages a second, then shards by Thread. A stream over its rate closes with a rate-limited frame and a retry hint, and the client resumes from its cursor.
Next
- Webhooks: the same Events, delivered to a server and retried.
- Pagination and filtering: the
wheregrammar every selector shares. - Debugging: follow one Event back to the request that caused it.