Skip to content

Events API

The Events API provides a persistent SSE connection for workspace-level events. Use it to react to bundle lifecycle changes, data mutations, and connection health in real time.

Open a persistent SSE connection. The server sends events as they occur and a heartbeat every 30 seconds to keep the connection alive.

Response headers:

Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive

Example:

Terminal window
curl http://localhost:27247/v1/events \
-H "Authorization: Bearer your-secret-key" \
--no-buffer

A new bundle was installed and started.

event: bundle.installed
data: {"name":"weather","bundleName":"@nimblebraininc/weather","status":"running","ui":null}
FieldTypeDescription
namestringShort server name
bundleNamestringScoped manifest name
statusstringLifecycle state after installation
uiobject | nullUI metadata, or null

A bundle was removed.

event: bundle.uninstalled
data: {"name":"weather"}
FieldTypeDescription
namestringShort server name of the removed bundle

A bundle’s MCP server process crashed. The runtime will attempt to restart it.

event: bundle.crashed
data: {"name":"weather","restartAttempt":1}
FieldTypeDescription
namestringShort server name
restartAttemptnumberWhich restart attempt this is (1-based)

A previously crashed bundle was successfully restarted.

event: bundle.recovered
data: {"name":"weather"}
FieldTypeDescription
namestringShort server name

A bundle exhausted all restart attempts and is permanently stopped. Manual intervention is needed to restart it.

event: bundle.dead
data: {"name":"weather","message":"Exceeded maximum restart attempts (3)"}
FieldTypeDescription
namestringShort server name
messagestringReason the bundle was marked dead

An agent-initiated tool call completed successfully, which may have mutated data in the tool’s backing service. Use this event to refresh UI components that display data from the affected server.

event: data.changed
data: {"server":"tasks","tool":"create_task","timestamp":"2025-10-15T10:31:15.000Z"}
FieldTypeDescription
serverstringMCP server that owns the tool
toolstringTool name that was called
timestampstringISO 8601 timestamp

A runtime configuration change occurred (e.g., model update, preferences change).

event: config.changed
data: {"key":"defaultModel","timestamp":"2026-04-13T10:30:00.000Z"}
FieldTypeDescription
keystringConfiguration key that changed
timestampstringISO 8601 timestamp

skill.created / skill.updated / skill.deleted

Section titled “skill.created / skill.updated / skill.deleted”

A user skill was created, modified, or removed.

event: skill.created
data: {"name":"my-skill","timestamp":"2026-04-13T10:30:00.000Z"}
FieldTypeDescription
namestringSkill name
timestampstringISO 8601 timestamp

A file was uploaded or removed from the workspace.

event: file.created
data: {"fileId":"file_abc123","name":"report.pdf","timestamp":"2026-04-13T10:30:00.000Z"}
FieldTypeDescription
fileIdstringFile identifier
namestringOriginal filename
timestampstringISO 8601 timestamp

An MCP App Bridge tool call started or completed. Used by the web client to show tool call activity from app iframes.

event: bridge.tool.call
data: {"server":"tasks","tool":"create_task","timestamp":"2026-04-13T10:30:00.000Z"}
FieldTypeDescription
serverstringMCP server name
toolstringTool name
timestampstringISO 8601 timestamp

Sent every 30 seconds to keep the connection alive and allow clients to detect stale connections.

event: heartbeat
data: {"timestamp":"2025-10-15T10:30:30.000Z"}
FieldTypeDescription
timestampstringISO 8601 timestamp

Open a persistent SSE connection for a specific conversation. Only authorized participants receive events. Use this to build multi-participant chat — when one user sends a message, other participants watching the same conversation receive the assistant’s response in real time.

Authentication: Required. The server validates workspace membership and conversation access (canAccess()) on every connection. Unauthorized requests receive 404 (to avoid leaking conversation existence).

Response headers:

Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive

Example:

Terminal window
curl http://localhost:27247/v1/conversations/conv_a1b2c3d4e5f67890/events \
-H "Authorization: Bearer your-secret-key" \
-H "X-Workspace-Id: ws_engineering" \
--no-buffer
EventDescription
user.messageAnother participant sent a message. Contains userId, displayName, content, timestamp.
text.deltaStreaming text chunk from the assistant response.
tool.startA tool call began.
tool.doneA tool call completed.
llm.doneLLM response finished (contains token counts).
doneFull assistant response complete. Contains response, conversationId, stopReason, usage.
heartbeatKeep-alive, sent every 30 seconds.

When a participant is removed from a conversation (via manage_conversation tool) or a conversation is unshared, their SSE connection is closed immediately server-side. On reconnect, they receive 404 and should stop retrying.

  • The server supports multiple concurrent SSE clients. Each client receives all events.
  • If a client disconnects, the server cleans up the connection automatically on the next broadcast.
  • There is no reconnection protocol built into the stream. If the connection drops, open a new GET /v1/events request.
  • The server sets idleTimeout to 255 seconds (the maximum Bun allows) to prevent premature connection closures.

The server maintains an in-memory buffer of the 500 most recent events. This buffer is used internally by components like the Home dashboard. It is not exposed through the HTTP API.