The app talks to the hermes-dispatch-bridge
/v1 API (Bearer-token auth). The bridge in turn fronts
hermes-webui and holds runs
server-side. The app's networking layer is deliberately tolerant (unknown fields
ignored, unknown SSE events mapped to Unknown).
| App action | Bridge endpoint |
|---|---|
| Pair / verify | GET /v1/auth/check (Bearer) |
| List tasks | GET /v1/tasks → TaskDto[] |
| Start task | POST /v1/tasks {message, session_id?, model?} → {kind, session_id?, stream_id?, cron?} |
| Stream a run | GET /v1/tasks/{stream_id}/events (SSE) |
| Cancel / steer | POST /v1/tasks/{stream_id}/{cancel,steer} |
| Schedules | GET /v1/schedules; POST /v1/schedules/{id}/{pause,resume,run,delete} |
| MCP | GET /v1/mcp |
A POST /v1/tasks may return kind: "cron" (the bridge classified it as
recurring and created a schedule) instead of a streamable run.
| Capability | Endpoint | Notes |
|---|---|---|
| Login | POST /api/auth/login {password} |
Sets an HttpOnly session cookie (stored by the client cookie jar). |
| Auth status | GET /api/auth/status |
{authenticated} |
| List tasks | GET /api/sessions |
→ SessionDto[] |
| Start a run | POST /api/chat/start {session_id?, message, model?, workspace?} |
→ {stream_id} |
| Reply mid-run | POST /api/chat/steer |
Phase 2 |
| Cancel | POST /api/chat/cancel {stream_id} |
Phase 2 |
| Schedules | GET /api/crons |
→ CronDto[] |
| Schedule control | POST /api/crons/{pause,resume,run,delete} {id} |
|
| MCP servers | GET /api/mcp/servers |
→ McpServerDto[] |
| Models | GET /api/models |
Phase 5 |
Profile is sent as the X-Hermes-Profile request header (the bridge may also
honor a hermes_profile cookie).
Content-Type: text/event-stream. Frames use event: + data: (JSON). The
client maps them to StreamEvent (see data/remote/sse/). Observed event
vocabulary (from streaming.py):
| Event name(s) | → StreamEvent | Drives |
|---|---|---|
token, text, delta, message |
Token(text) |
chat pane |
tool, tool_use, tool_call |
Tool(name, preview) |
actions pane |
status, worker_started, assistant_started |
Status(text) |
status line |
reasoning, thinking |
Reasoning(text) |
(collapsed) |
approval |
Approval(command, description) |
approval prompt |
clarify |
Clarify(question) |
inline question |
completed, done, finished |
Completed |
finalize task |
interrupted, cancelled |
Interrupted |
finalize task |
error (+ subtypes: rate_limit, quota_exhausted, auth_mismatch, model_not_found, …) |
Error(message, type) |
error UI |
| anything else | Unknown(event, data) |
ignored safely |
Run hermes-webui locally and capture real payloads for each event
(curl -N the stream) to confirm exact field names, then tighten the DTOs and
add fixture-based parser tests.