Use this file to discover all available pages before exploring further.
Gateway architecture
Overview
- A single long‑lived Gateway owns all messaging surfaces (WhatsApp via
Baileys, Telegram via grammY, Slack, Discord, Signal, iMessage, WebChat).
- Control-plane clients (macOS app, CLI, web UI, automations) connect to the
Gateway over WebSocket on the configured bind host (default
).
- Nodes (macOS/iOS/Android/headless) also connect over WebSocket, but
declare with explicit caps/commands.
- One Gateway per host; it is the only place that opens a WhatsApp session.
- The canvas host is served by the Gateway HTTP server under:
- (agent-editable HTML/CSS/JS)
- (A2UI host)
It uses the same port as the Gateway (default ).
Components and flows
Gateway (daemon)
- Maintains provider connections.
- Exposes a typed WS API (requests, responses, server‑push events).
- Validates inbound frames against JSON Schema.
- Emits events like , , , , , .
Clients (mac app / CLI / web admin)
- One WS connection per client.
- Send requests (, , , , ).
- Subscribe to events (, , , ).
Nodes (macOS / iOS / Android / headless)
- Connect to the same WS server with .
- Provide a device identity in ; pairing is device‑based (role ) and
approval lives in the device pairing store.
- Expose commands like , , , .
Protocol details:
WebChat
- Static UI that uses the Gateway WS API for chat history and sends.
- In remote setups, connects through the same SSH/Tailscale tunnel as other
clients.
Connection lifecycle (single client)
sequenceDiagram
participant Client
participant Gateway
Client->>Gateway: req:connect
Gateway-->>Client: res (ok)
Note right of Gateway: or res error + close
Note left of Client: payload=hello-ok<br>snapshot: presence + health
Gateway-->>Client: event:presence
Gateway-->>Client: event:tick
Client->>Gateway: req:agent
Gateway-->>Client: res:agent<br>ack {runId, status:"accepted"}
Gateway-->>Client: event:agent<br>(streaming)
Gateway-->>Client: res:agent<br>final {runId, status, summary}
Wire protocol (summary)
- Transport: WebSocket, text frames with JSON payloads.
- First frame must be .
- After handshake:
- Requests:
{type:"req", id, method, params}
→ {type:"res", id, ok, payload|error}
- Events:
{type:"event", event, payload, seq?, stateVersion?}
hello-ok.features.methods
/ are discovery metadata, not a
generated dump of every callable helper route.
- Shared-secret auth uses
connect.params.auth.token
or
connect.params.auth.password
, depending on the configured gateway auth mode.
- Identity-bearing modes such as Tailscale Serve
(
gateway.auth.allowTailscale: true
) or non-loopback
gateway.auth.mode: "trusted-proxy"
satisfy auth from request headers
instead of .
- Private-ingress
gateway.auth.mode: "none"
disables shared-secret auth
entirely; keep that mode off public/untrusted ingress.
- Idempotency keys are required for side‑effecting methods (, ) to
safely retry; the server keeps a short‑lived dedupe cache.
- Nodes must include plus caps/commands/permissions in .
Pairing + local trust
- All WS clients (operators + nodes) include a device identity on .
- New device IDs require pairing approval; the Gateway issues a device token
for subsequent connects.
- Direct local loopback connects can be auto-approved to keep same-host UX
smooth.
- OpenClaw also has a narrow backend/container-local self-connect path for
trusted shared-secret helper flows.
- Tailnet and LAN connects, including same-host tailnet binds, still require
explicit pairing approval.
- All connects must sign the nonce.
- Signature payload also binds + ; the gateway
pins paired metadata on reconnect and requires repair pairing for metadata
changes.
- Non‑local connects still require explicit approval.
- Gateway auth () still applies to all connections, local or
remote.
Details: Gateway protocol, Pairing,
Security.
Protocol typing and codegen
- TypeBox schemas define the protocol.
- JSON Schema is generated from those schemas.
- Swift models are generated from the JSON Schema.
Remote access
-
Preferred: Tailscale or VPN.
-
Alternative: SSH tunnel
ssh -N -L 18789:127.0.0.1:18789 user@host
-
The same handshake + auth token apply over the tunnel.
-
TLS + optional pinning can be enabled for WS in remote setups.
Operations snapshot
- Start: (foreground, logs to stdout).
- Health: over WS (also included in ).
- Supervision: launchd/systemd for auto‑restart.
Invariants
- Exactly one Gateway controls a single Baileys session per host.
- Handshake is mandatory; any non‑JSON or non‑connect first frame is a hard close.
- Events are not replayed; clients must refresh on gaps.
Related