New request
#272: Real-time bidirectional sync between Gateway sessions and WebUI
We'll provision a sandbox, run an agent against the issue, and open a draft PR. You can pull the branch and iterate from there.
Real-time bidirectional sync between Gateway sessions and WebUI
Problem
When Hermes Agent runs with a gateway (Telegram, Discord, etc.), the WebUI currently offers read-only snapshot access to gateway sessions via the CLI session bridge. There is no real-time synchronization between the two:
- Messages sent via Telegram don't appear live in the WebUI
- Replying from the WebUI to a gateway session is not possible
- The CLI bridge imports a static snapshot that never refreshes
This means users who primarily interact via messaging platforms can't use the WebUI as a full interface to participate in those same conversations.
Current Architecture
Gateway side (hermes-agent):
- Dual-layer storage: in-memory
SessionStore+ SQLitestate.db(WAL mode) state.dbhassessionsandmessagestables with FTS5- Gateway API server on port 8642 (aiohttp)
- Sessions tagged with
sourcefield: 'telegram', 'discord', 'cli', etc. - Session keys:
agent:main:telegram:dm:<chat_id>
WebUI side (hermes-webui):
- Own session store: JSON files in
~/.hermes/webui/sessions/ - CLI bridge in
api/models.py:get_cli_sessions()reads metadata fromstate.db,get_cli_session_messages()reads messages api/state_sync.py: WebUI → agent direction only (for /insights cost tracking)- SSE streaming for agent responses (per-stream queue, not persistent)
Proposed Approach
Phase 1: Gateway → WebUI (read-only live view)
- Add a background watcher in the WebUI (
api/session_watcher.py) that pollsstate.dbevery 2-3 seconds for new messages/sessions - Push detected changes to the browser via a persistent SSE endpoint (
/api/gateway/stream) - Gateway sessions appear live in the sidebar with real-time message updates (similar to how Telegram works in the WebUI)
This requires no changes to hermes-agent — the WebUI already has read access to state.db and the gateway uses WAL mode so reads are non-blocking.
Phase 2: WebUI → Gateway (bidirectional)
- WebUI connects to the gateway's API (port 8642) as a client
- When replying to a gateway session in the WebUI, the message is forwarded to the gateway for processing
- The gateway streams the response back to the WebUI via the existing API
- Gateway sessions become fully interactive in the WebUI — not just viewable, but usable
This requires gateway API changes to support an external client sending messages to existing sessions.
Benefits
- Full parity: the WebUI becomes a true universal interface for all Hermes conversations
- Phone users on Telegram and desktop users on WebUI can participate in the same session
- No duplicate sessions — one conversation, multiple interfaces
- Leverages the existing shared
~/.hermes/filesystem
Complexity Estimate
- Phase 1: ~200-300 lines of Python in the WebUI, low risk, can be done in one sprint
- Phase 2: ~150-200 lines in both WebUI and gateway, medium risk, requires coordination with hermes-agent
Open Questions
- Should gateway sessions be editable (rename, delete, archive) from the WebUI?
- How to handle concurrent access (reply from Telegram + WebUI at the same time)?
- Should the gateway expose an SSE/WebSocket events endpoint instead of having the WebUI poll
state.db?
Happy to discuss the approach and contribute implementation. I've explored both codebases in detail and can submit a PR for Phase 1 if there's interest.
Architectural overhaul to enable persistent bidirectional synchronization between gateway runtimes and the WebUI session store.
- api/state_sync.py
- api/models.py
- api/streaming.py
- api/gateway_client.py
- static/js/sidebar/sync.js
- api/routes/sessions.py
- tests/test_gateway_sync.py