Summary
Add a Server-Sent Events (SSE) endpoint that lets any client subscribe to the app state machine events for a given workspace and app. This is the primary mechanism by which all Traverse clients (web, mobile, desktop, CLI) receive state updates from the runtime.
Depends on: #525 (app state machine spec)
Why SSE over WebSocket
- SSE is unidirectional (server → client), which matches the state machine model: the runtime pushes state, clients pull UI from it
- Native browser support with
EventSource — no library needed in web clients
- Works over standard HTTP/1.1 — simpler to implement than WebSocket upgrade
- WebSocket can be added later for bidirectional use cases
Proposed endpoint
GET /v1/workspaces/{workspace_id}/apps/{app_id}/events
Response: Content-Type: text/event-stream
Event types
state_changed
event: state_changed
data: {
"app_id": "traverse-starter",
"session_id": "sess_abc123",
"state": "processing",
"previous_state": "idle",
"timestamp": "2026-07-03T12:00:00Z",
"context": {
"command": "submit",
"payload": { "note": "..." }
}
}
capability_invoked
event: capability_invoked
data: {
"capability_id": "traverse-starter.process",
"execution_id": "exec_xyz789",
"state": "processing"
}
capability_result
event: capability_result
data: {
"execution_id": "exec_xyz789",
"state": "results",
"output": {
"title": "...",
"tags": ["..."],
"noteType": "fleeting",
"suggestedNextAction": "review",
"status": "complete"
}
}
error
event: error
data: {
"state": "error",
"error_code": "CAPABILITY_TIMEOUT",
"message": "..."
}
heartbeat (every 30s to keep connection alive)
event: heartbeat
data: { "timestamp": "..." }
Definition of Done
Client implementation pattern
// web-react (after this ticket ships)
const es = new EventSource(
`${BASE_URL}/v1/workspaces/${workspace}/apps/traverse-starter/events`
)
es.addEventListener('state_changed', e => {
const { state, context } = JSON.parse(e.data)
dispatch({ type: 'STATE_CHANGED', state, context })
})
// ios-swift
URLSession.shared.dataTask(with: eventsURL) { ... } // URLSessionDataDelegate streaming
Downstream unblocked
- App-References: web-react SSE hook
- App-References: ios-swift state subscription
- App-References: all other platform clients
Summary
Add a Server-Sent Events (SSE) endpoint that lets any client subscribe to the app state machine events for a given workspace and app. This is the primary mechanism by which all Traverse clients (web, mobile, desktop, CLI) receive state updates from the runtime.
Depends on: #525 (app state machine spec)
Why SSE over WebSocket
EventSource— no library needed in web clientsProposed endpoint
Response:
Content-Type: text/event-streamEvent types
state_changed
capability_invoked
capability_result
error
heartbeat (every 30s to keep connection alive)
Definition of Done
GET /v1/workspaces/{workspace_id}/apps/{app_id}/eventsreturnstext/event-streamstate_changed,capability_invoked,capability_result,error,heartbeateventsLast-Event-IDheader, runtime replays the current statestate_changedwhen a command is dispatchedEventSourcewithout CORS issues (see CORS: add Access-Control-Allow-Origin headers to runtime HTTP server #522)Client implementation pattern
Downstream unblocked