Skip to content

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

LabelCaller and credential
Public probeNo credential; limited to health and initial pairing behavior
LoopbackHermes-host process from 127.0.0.1 or ::1 only
PairedRelay session bearer plus the required per-channel grant
API voiceValid Hermes API bearer, accepted only for documented /voice/* routes; HTTPS required remotely
SideloadPaired route additionally gated by the Android sideload capability

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

MethodRouteAuthPurpose
GET upgrade/ws, /Pairing code or paired sessionMultiplexed phone connection
GET/healthPublic probeVersion, readiness and connected-client summary
POST/pairingRate-limited public setupCreate a relay-side pairing code
POST/pairing/registerLoopbackRegister a host-minted code and policy metadata
POST/pairing/mintLoopbackMint a signed QR payload for dashboard/CLI pairing
POST/pairing/approveLoopback, reservedFuture 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

MethodRoute familyAuthPurpose
GET/PATCH/DELETE/sessions, /sessions/{token_prefix}PairedInspect, extend, re-grant or revoke paired devices
POST/clipboard/inboxPairedClipboard rendezvous
GET upgradeWebSocket channel terminalterminal grantRemote shell stream
GET upgradeWebSocket channel tuitui grantTUI relay stream
multiplexedWebSocket channel bridgebridge grantPhone command and response envelopes

Media

MethodRouteAuthPurpose
POST/media/registerLoopbackRegister an allowed host file and return an opaque token
POST/media/uploadPairedUpload bounded phone-originated media
GET/media/{token}PairedFetch registered media without exposing its host path
GET/media/by-pathPairedFetch a sandbox-approved absolute path emitted by Hermes
GET/media/inspectLoopbackOperator inspection of the media registry

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

Chat activity compatibility

MethodRouteAuthPurpose
GET/chat/image-activityPaired chat grantRead 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 familyMethodsAuthStability
/voice/configGETPaired voice grant or API voiceStable discovery
/voice/transcribePOSTPaired voice:stt or API voiceStable fallback STT
/voice/synthesizePOSTPaired voice:tts or API voiceStable fallback TTS
/voice/output/*GET/PATCH/POST/WSPaired voice grant or API voiceStreaming output
/voice/realtime/*GET/PATCH/POST/WSPaired realtime grant or API voiceExperimental provider lab
/voice/realtime-agent/*GET/PATCH/POST/WSPaired realtime grant or API voiceExperimental 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 familyAuthPurpose
/desktop/_ping, /desktop/health, /desktop/{tool_name}Paired desktop grantDesktop CLI tool dispatch and readiness
/notifications/recentLoopback or pairedBounded recent notification companion state
/phone/message, /phone/repliesPlatform/paired pathAgent-to-phone messages and phone replies
/phone/outbound, /phone/threadsPairedOutbound queue and conversation state
/context/injectedPairedInspect 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:

surfacingAndroid behavior
omitted, null, default, or notificationPersist and raise a system notification
inboxPersist silently
sessionDeliver 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:

MethodRoutePurpose
GET/api/profiles/{name}/configRelay-visible profile configuration
GET/api/profiles/{name}/avatarProfile avatar asset
GET/api/profiles/{name}/skillsProfile skill inventory
GET/PUT/api/profiles/{name}/soulPaired profile SOUL access
GET/api/profiles/{name}/memoryProfile 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.

GroupRepresentative routesGate
Read/screen, /screenshot, /find_nodes, /screen_hashSideload + enabled service
Gestures/tap, /tap_text, /swipe, /drag, /scrollSideload + safety pipeline
Input and navigation/type, /press_key, /open_app, /return_to_hermesSideload + safety pipeline
Phone utilities/location, /search_contacts, /call, /send_sms, /send_mmsSideload + capability permission
Events and media/events, /events/stream, /media, /share_mediaRoute-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.

json
{
  "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:

json
{
  "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.

MethodRouteAuthPurpose
GET/relay/infoLoopbackRelay build and capability summary
POST/relay/model-capabilitiesLoopback or paired bearer with chat grantProfile-aware reasoning-effort metadata for up to 64 provider/model pairs; credentials remain server-side
GET/PATCH/relay/securityLoopbackRuntime security toggles
GET/bridge/statusLoopbackDevice, bridge and safety state
GET/bridge/activityLoopbackRecent bridge activity
GET/bridge/devicesLoopbackConnected bridge-device inventory
POST/bridge/select-activeLoopbackSelect the active bridge device
GET/relay/update-checkLoopbackPlugin update status

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