Runtime Event Bus
The runtime publishes session changes, store writes, bundle reloads, messaging-channel activity, and tool-call activity through GET /api/events. Use these events to refresh data in your application.
Chat responses use a separate POST stream with text_delta, tool_call_start, and done messages. See Runtime Server. The event bus reports state changes across sessions; it does not replace authenticated data queries.
Subscribe
This browser example uses the current origin and its hosted session. A cross-origin or bearer-authenticated client needs an appropriate authenticated connection; native EventSource cannot set an Authorization header.
const events = new EventSource('/api/events');
events.addEventListener('session_created', (message: MessageEvent<string>) => {
const event = JSON.parse(message.data);
console.log('Session created:', event.sessionId);
});Each frame carries an event: line with the event type, so register a named listener for each type the view uses. An onmessage handler receives nothing.
Call events.close() when the view is disposed. The server sends a comment heartbeat every 15 seconds. amodal dev and hosted deployments both serve this route.
A hosted event stream carries every session's events. Operator credentials, such as the agent's API key, Studio, or a runtime token without a scope_id claim or the user role, receive full events. Every other subscriber, including the hosted browser session and the React SDK's useAgentEvents, receives each event without its content fields: title, message, error, channelUserId, messagePreview, replyPreview, argsSummary, and targetUrl. amodal dev sends full events to every subscriber.
Reconnect-and-resume
EventSource saves the SSE id and sends it as Last-Event-ID on reconnect. Treat this ID as an opaque cursor:
amodal devuses a process-local sequence and retains the latest 200 events. Its cursor and buffer reset when the process restarts.- Hosted deployments routed through the event service use Redis stream IDs, with retention configured by the platform. Do not substitute the event payload's
seqfor this cursor.
The server replays retained events after the cursor, then streams live events. Missing events outside retention cannot be recovered from this subscription. Refresh the underlying data after a reconnect if your view needs a complete state. A gap in numeric seq can also come from filtered event types, so it is not proof of data loss.
Event catalog
Session events
| Type | Fields | When |
|---|---|---|
session_created | sessionId, agentId | A new session was created (chat, admin, automation). |
session_updated | sessionId, agentId, title?, status?, answeredBy? | A session was persisted after a message, title change, or metadata update. |
session_deleted | sessionId | A session was deleted via the API. |
Store events
| Type | Fields | When |
|---|---|---|
store_updated | storeName, operation, count? | A document was written or deleted. operation is "put" or "delete". A purge of expired documents emits "delete" with count set to the number purged, and storeName is "*" when the purge covers every store. |
Config events
| Type | Fields | When |
|---|---|---|
manifest_changed | None | The agent manifest (connections, skills, automations) was reloaded after a source or deploy change. |
reload_failed | message | A local development bundle reload failed; the server keeps serving the previous bundle. |
Channel events
| Type | When |
|---|---|
channel_message_received | An inbound message arrived on a messaging channel. |
channel_reply_sent | The agent's reply was delivered back to the channel. |
channel_session_created | A channel conversation started a new session. |
channel_auth_rejected | A channel webhook failed authentication. |
Tool-call events
tool_call_started, tool_call_completed, and tool_call_failed report execution activity. amodal dev excludes them by default; add ?include=tool_calls or individual type names to include them. Hosted routes ignore include and send every event type.
Types
All events carry seq, timestamp, and type fields plus the event-specific payload. The React SDK exports AgentEvent, which accepts runtime event fields as unknown values. Narrow those fields before using them:
import type { AgentEvent } from '@amodalai/react';
function handleEvent(event: AgentEvent) {
if (event.type === 'session_updated' && typeof event['sessionId'] === 'string') {
console.log(event['sessionId'], event['status']);
}
}Events and data access
Use events to know when to refresh a session list, automation status, or store-backed view, then fetch the current data through the corresponding HTTP API. Receiving an event is not permission to read the referenced session or store.