Superseded by ADR-0007. This record was inaccurate when written: on the date below,
chat-stream.tsalready used WebSocket. It describes the decision ARES inherited from upstream Hermes WebUI, not what ARES implemented. Retained unedited as history; do not cite it as current architecture.
Status: Superseded (was: Accepted (inherited)) Date: 2026-07-22 (recorded retroactively)
ARES inherited SSE streaming from Hermes WebUI, whose own ADR-004 chose SSE over WebSockets. ARES never recorded the reasoning, so the choice has periodically looked arbitrary.
Chat streaming is one-directional: the server pushes tokens, tool activity, and completion events. The client’s only upstream actions — send, cancel, approve — are ordinary HTTP requests.
Keep SSE. POST /api/chat/start returns a stream_id; the browser opens
EventSource('/api/chat/stream?stream_id=…') and consumes typed events until
done or error.
Good:
Costs:
fastapi_app/routers/realtime.py also exposes a WebSocket route for session
streams. SSE remains the path used by the Chat surface; the WebSocket route is
not the default and should not be treated as a second parallel implementation
without a product decision.
Streaming becomes genuinely bidirectional and latency-sensitive — for example live voice, where round-trip audio would justify a persistent duplex channel.