Skip to content

Streaming replies ​

Follow a run live with Server-Sent Events:

GET /agent-runs/{runId}/events

In a browser, use EventSource with credentials:

ts
const es = new EventSource(`https://api.lexcetha.com/api/v1/agent-runs/${runId}/events`, { withCredentials: true });
let reply = '';
es.addEventListener('assistant.delta', (e) => { reply += JSON.parse(e.data).text; render(reply); });
es.addEventListener('approval.required', (e) => askUser(JSON.parse(e.data)));
es.addEventListener('run.completed', (e) => { render(JSON.parse(e.data).output); es.close(); });
es.addEventListener('run.failed', (e) => { showError(JSON.parse(e.data).message); es.close(); });
es.addEventListener('run.cancelled', () => es.close());

From a server, read the stream with any SSE client and the Authorization: Bearer header.

Events ​

Each event has an increasing id, a name and a JSON data payload.

EventDataWhen
run.started{ mode, botId }The run begins
assistant.delta{ text }The next piece of the reply. Append it.
tool.proposed{ callId, toolSlug, arguments }The bot wants to use a tool (arguments are redacted)
approval.required{ approvalId, callId, toolSlug, risk, summary, expiresAt }The tool needs your approval, see Approvals
run.waiting{ approvals: [approvalId] }The run is paused until those are decided
tool.started{ callId, toolSlug }The tool is running
tool.completed{ callId, toolSlug, status, result? }status is succeeded (with result), failed, denied, rejected, expired, connection_required or duplicate
run.completed{ output, stopReason }Done. output is the full reply.
run.failed{ code, message }Stopped with an error
run.cancelled{}Cancelled

run.completed, run.failed and run.cancelled are final: close the stream after them.

stopReason is needs_setup when the bot is asking you to connect or install something you tagged; see Attachments & tags.

Reconnecting ​

Connections drop. Reconnect with the last event id and the stream continues from there, without repeating or losing anything:

  • EventSource sends Last-Event-ID for you automatically.
  • Other clients can send the Last-Event-ID header, or ?after={id}.

The server sends a comment every 15 seconds to keep the connection alive, and closes a stream after 30 minutes; reconnecting picks up where it left off.

Lex by Gavalytics AI