Real-Time Agent Updates with Server-Sent Events
Real-Time Agent Updates with Server-Sent Events
When an AI agent is working on your codebase, you want to see what it's doing right now — not what it did five seconds ago. Real-time visibility is essential for trust. If you can watch the agent work and see SafeClaw's decisions as they happen, you're far more comfortable letting it operate autonomously.
We built SafeClaw's real-time update system on Server-Sent Events (SSE), and it's been one of the best technical decisions we've made.
Why SSE Over WebSockets
The obvious choice for real-time communication is WebSockets. They're bidirectional, widely supported, and well-understood. We considered them seriously and chose SSE instead for several reasons.
Unidirectional fits our use case. The dashboard needs to receive updates from SafeClaw's daemon, but it rarely needs to send data back. The few interactions that do go from dashboard to daemon (approving escalations, changing settings) are standard HTTP requests. SSE handles the server-to-client stream; REST handles the client-to-server commands. Clean separation. Automatic reconnection. The SSE specification includes built-in reconnection with last-event-ID tracking. If the dashboard's connection drops (laptop sleep, network blip, tab backgrounding), the browser automatically reconnects and requests events from where it left off. With WebSockets, we'd have to implement this ourselves. HTTP semantics. SSE runs over standard HTTP. It works through proxies, load balancers, and firewalls without special configuration. It respects HTTP caching headers. It's trivially debuggable with curl. WebSockets require an upgrade handshake that some infrastructure doesn't handle well. Simplicity. Our SSE server is about 80 lines of code. A WebSocket implementation with equivalent reliability (heartbeats, reconnection, message ordering) would be significantly more complex.The Event Stream
SafeClaw's SSE endpoint streams several event types:
- action — An agent attempted an action. Includes the action type, parameters, and timestamp.
- decision — The classifier made a decision. Includes the action reference, the decision (allow/deny/escalate), and the policy rule that matched.
- risk — A risk signal was detected. Includes the signal category, weight, and cumulative session score.
- escalation — An action was escalated for human review. Includes the full action details and the reason for escalation.
- budget — A budget update. Includes the current spend, remaining budget, and the action that triggered the update.
- session — Session lifecycle events: started, paused, resumed, ended.
Each event is a compact JSON payload with a monotonically increasing ID. The IDs enable resumption after disconnection — the client sends Last-Event-ID on reconnect, and the server replays missed events from its buffer.
Event Buffering
Not every consumer of the event stream processes events at the same speed. The dashboard might be in a background tab, throttled by the browser. A webhook consumer might have intermittent connectivity. The CLI might be piped through a slow terminal.
We maintain a ring buffer of recent events in memory. The buffer holds the last 1,000 events (configurable), which at typical agent activity rates covers several minutes. Events older than the buffer are available from the session log on disk, but the fast path through the ring buffer handles the vast majority of reconnection scenarios.
Dashboard Integration
The SafeClaw dashboard connects to the SSE endpoint on load and renders events as they arrive. The activity feed, the risk score gauge, the budget meter, and the escalation queue are all driven by the same event stream. There's no polling, no periodic refresh, and no stale data.
When the connection drops, a subtle indicator appears in the dashboard header. When it reconnects, missed events are replayed and the UI catches up seamlessly. Users have told us they didn't even realize they'd been briefly disconnected until they noticed the indicator flash.
Try It
You can connect to SafeClaw's SSE endpoint directly with curl for debugging and scripting:
``bash
curl -N http://localhost:3827/events
``Full API documentation is on our docs site, and the SSE implementation is open source on GitHub.
Real-time visibility transforms the experience of working with AI agents. SSE gave us the perfect primitive to build it on — simple, reliable, and universally supported.