Files

10 KiB
Raw Permalink Blame History

Relay API Contract

The Relay server is an optional additive surface. It does not carry normal Hermes chat and is never required for the Vanilla Hermes path.

Base URL: ws(s)://<server>:8767 for the multiplexed connection, with the matching http(s):// origin for HTTP routes.

Authentication classes

Label Caller and credential
Public probe No credential; limited to health and initial pairing behavior
Loopback Hermes-host process from 127.0.0.1 or ::1 only
Paired Relay session bearer plus the required per-channel grant
API voice Valid Hermes API bearer, accepted only for documented /voice/* routes; HTTPS required remotely
Sideload Paired route additionally gated by the Android sideload capability

::: danger Relay bearer scope Never reuse a Relay session token against the upstream API Server or Dashboard. Never accept the Hermes API bearer on terminal, media, desktop, profile-write, phone-control or general Relay session routes. :::

Connection and pairing

Method Route Auth Purpose
GET upgrade /ws, / Pairing code or paired session Multiplexed phone connection
GET /health Public probe Version, readiness and connected-client summary
GET /secure-link/preflight Loopback Read-only setup report for the proposed host and port: prerequisites, certificate checks, startup settings, and restart impact. Never writes configuration, rotates keys, or restarts services.
POST /pairing Rate-limited public setup Create a relay-side pairing code
POST /pairing/register Loopback Register a host-minted code and policy metadata
POST /pairing/mint Loopback Mint a signed QR payload for dashboard/CLI pairing
POST /pairing/approve Loopback, reserved Future host-approval direction

Pairing codes are short-lived and one-shot. A successful pair produces the longer-lived Relay session and its clamped grants.

Paired sessions and channels

Method Route family Auth Purpose
GET/PATCH/DELETE /sessions, /sessions/{token_prefix} Paired Inspect, extend, re-grant or revoke paired devices
POST /clipboard/inbox Paired Clipboard rendezvous
GET upgrade WebSocket channel terminal terminal grant Remote shell stream
GET upgrade WebSocket channel tui tui grant TUI relay stream
multiplexed WebSocket channel bridge bridge grant Phone command and response envelopes

Media

Method Route Auth Purpose
POST /media/register Loopback Register an allowed host file and return an opaque token
POST /media/upload Paired Upload bounded phone-originated media
GET /media/{token} Paired Fetch registered media without exposing its host path
GET /media/by-path Paired Fetch a sandbox-approved absolute path emitted by Hermes
GET /media/inspect Loopback Operator inspection of the media registry

All file routes resolve real paths under configured allowed roots and reject symlink escapes.

Chat activity compatibility

Method Route Auth Purpose
GET /chat/image-activity Paired chat grant Read image-generation activity from the selected Hermes session when the upstream Gateway does not expose native tool progress

This optional route reports only image-generation lifecycle state. It does not proxy chat prompts, response text, tool results, or session control. Android uses native Gateway events when available and silently stops polling when an older Relay does not provide the route.

Relay voice

Every route below is Relay-owned. Vanilla Hermes voice uses Dashboard /api/audio/* instead.

Route family Methods Auth Stability
/voice/config GET Paired voice grant or API voice Stable discovery
/voice/transcribe POST Paired voice:stt or API voice Stable fallback STT
/voice/synthesize POST Paired voice:tts or API voice Stable fallback TTS
/voice/output/* GET/PATCH/POST/WS Paired voice grant or API voice Streaming output
/voice/realtime/* GET/PATCH/POST/WS Paired realtime grant or API voice Experimental provider lab
/voice/realtime-agent/* GET/PATCH/POST/WS Paired realtime grant or API voice Experimental broker

Streaming sessions upgrade at /voice/output/{session_id}, /voice/realtime/{session_id}, or /voice/realtime-agent/{session_id} after the matching session-creation route returns an id.

Non-loopback API-bearer calls require HTTPS unless the operator explicitly enables the temporary insecure-LAN escape hatch.

Desktop, notifications and phone messaging

Route family Auth Purpose
/desktop/_ping, /desktop/health, /desktop/{tool_name} Paired desktop grant Desktop CLI tool dispatch and readiness
/notifications/recent Loopback or paired Bounded recent notification companion state
/phone/message, /phone/replies Platform/paired path Agent-to-phone messages and phone replies
/phone/outbound, /phone/threads Paired Outbound queue and conversation state
/context/injected Paired Inspect bounded Relay-injected context

POST /phone/message always persists the message in Android's bounded Thread cache. Its optional surfacing hint controls the additional presentation:

surfacing Android behavior
omitted, null, default, or notification Persist and raise a system notification
inbox Persist silently
session Deliver to the available active session/Thread without a duplicate notification; notify only when no session destination is available

When no phone is subscribed, Relay retains the message in its bounded 24-hour queue. On the next subscription, flushed phone.message payloads include the optional queued_delivery: true marker and the batch ends with proactive.backlog.complete {count, ts}. Older clients safely ignore both.

Profiles and Relay-owned files

Routes on port 8767 under /api/profiles/{name}/* are Relay power surfaces, not the upstream Dashboard profile API:

Method Route Purpose
GET /api/profiles/{name}/config Relay-visible profile configuration
GET /api/profiles/{name}/avatar Profile avatar asset
GET /api/profiles/{name}/skills Profile skill inventory
GET/PUT /api/profiles/{name}/soul Paired profile SOUL access
GET /api/profiles/{name}/memory Profile memory inventory
PUT /api/profiles/{name}/memory/{filename} Paired profile memory-file write

Prefer upstream Dashboard routes for standard profile and Manage behavior.

Device Control

Device Control HTTP routes proxy through the connected phone's bridge channel. Every request requires a Relay session bearer with an active bridge grant (host tools read it from ANDROID_BRIDGE_TOKEN), plus a paired sideload phone reporting bridge.device_control_supported=true.

Group Representative routes Gate
Read /screen, /screenshot, /find_nodes, /screen_hash Sideload + enabled service
Gestures /tap, /tap_text, /swipe, /drag, /scroll Sideload + safety pipeline
Input and navigation /type, /press_key, /open_app, /return_to_hermes Sideload + safety pipeline
Phone utilities /location, /search_contacts, /call, /send_sms, /send_mms Sideload + capability permission
Events and media /events, /events/stream, /media, /share_media Route-specific gate

The Google Play build fails closed before AccessibilityService-dependent work. Direct commands return structured 403 responses instead of silently degrading.

Operator routes

Optional model capability overlay

POST /relay/model-capabilities refines reasoning-effort choices for exact provider/model pairs that the client already received from upstream Hermes. It does not list models, proxy chat, or replace upstream model.options.

{
  "schema_version": 1,
  "profile": "default",
  "refresh": false,
  "models": [
    {"provider": "example-provider", "model": "reasoner-v1"}
  ]
}

The response uses contract version 1.0 and returns one capability row per pair:

{
  "schema_version": 1,
  "contract_version": "1.0",
  "capabilities": [
    {
      "provider": "example-provider",
      "model": "reasoner-v1",
      "reasoning": true,
      "reasoning_efforts": ["low", "medium", "high"],
      "reasoning_efforts_exact": true,
      "source": "provider-adapter"
    }
  ]
}

An exact row is model-specific selectable truth. A non-exact row is advisory; clients should present standard choices without promising that every value is supported. Requests accept 1–64 pairs. Loopback callers may omit auth; remote callers need a paired bearer with an active chat grant. Credentials stay on the Hermes host, and cached/probed implementation details are not returned.

This route fails soft from the Android user's perspective: an absent or old Relay, missing pairing/grant, network error, or unsupported schema leaves the standard advisory choices available and never blocks model selection or chat.

Method Route Auth Purpose
GET /relay/info Loopback Relay build and capability summary
POST /relay/model-capabilities Loopback or paired bearer with chat grant Profile-aware reasoning-effort metadata for up to 64 provider/model pairs; credentials remain server-side
GET/PATCH /relay/security Loopback Runtime security toggles
GET /bridge/status Loopback Device, bridge and safety state
GET /bridge/activity Loopback Recent bridge activity
GET /bridge/devices Loopback Connected bridge-device inventory
POST /bridge/select-active Loopback Select the active bridge device
GET /relay/update-check Loopback Plugin update status

For deployment, environment variables, exact request shapes, the complete Device Control route table and troubleshooting, see Relay server operations.