WebSocket
Connect to the incubator WebSocket at ws://localhost:8080/ws for real-time event push.
Connection
Section titled “Connection”const ws = new WebSocket('ws://localhost:8080/ws');
ws.onopen = () => console.log('Connected');ws.onmessage = (e) => { const msg = JSON.parse(e.data); handleMessage(msg);};Inbound messages (server → client)
Section titled “Inbound messages (server → client)”Published events from any agent.
{ "type": "event", "id": 42, "event_type": "task.complete", "data": { "task": "auth-module" }, "agent_id": "worker-1", "timestamp": "2026-02-15T10:30:00Z"}State changed
Section titled “State changed”{ "type": "state_changed", "key": "current_phase", "value": "review", "agent_id": "worker-1"}Dance result
Section titled “Dance result”Response to a dance_call.
{ "type": "dance_result", "callId": "call-123", "result": { "success": true, "move": "e2-e4" }}Metrics
Section titled “Metrics”Pushed every 10 seconds with telemetry snapshot.
{ "type": "metrics", "data": { "totalTokens": 15000, "totalCost": 0.45, "agentCount": 3, "eventCounts": { "llm_call": 42, "tool_call": 18, "guard_scan": 60 } }}Replay done
Section titled “Replay done”Sent after initial event replay completes on connection.
{ "type": "replay_done" }Control
Section titled “Control”Control state changes (halt, pause, resume).
{ "type": "control", "command": "halt", "reason": "Budget exceeded"}Outbound messages (client → server)
Section titled “Outbound messages (client → server)”Publish event
Section titled “Publish event”{ "type": "publish", "event": "task.started", "data": { "task": "auth-module" }}Dance call
Section titled “Dance call”Call a dance tool handler.
{ "type": "dance_call", "tool": "make_move", "args": { "from": "e2", "to": "e4" }, "agentId": "player-1", "role": "white", "callId": "call-123"}The callId is returned in the dance_result response for correlation.
Clear all state, events, and claims. Used to restart games/protocols.
{ "type": "reset" }Event replay
Section titled “Event replay”On connection, the server replays all events since since=0 (configurable). After replay, a replay_done message is sent. Register your message handler before the WebSocket open event resolves to avoid missing events.
const ws = new WebSocket('ws://localhost:8080/ws');
// Register handler BEFORE open firesws.onmessage = (e) => { const msg = JSON.parse(e.data); if (msg.type === 'replay_done') { console.log('Caught up with all events'); }};Best practices
Section titled “Best practices”- Drive UI state from WS events, not REST polling. Polling re-renders destroy active DOM elements.
- Use per-agent event types like
turn.player_2so only the relevant agent wakes. - Register handlers before connection to catch replay events.
- Poll REST as backup only (30s+ interval, silent updates).