docs/concepts/architecture.md
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
127.0.0.1:18789).
Nodes (macOS/iOS/Android/headless) also connect over WebSocket, but
declare role: node 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:
/__openclaw__/canvas/ (agent-editable HTML/CSS/JS)/__openclaw__/a2ui/ (A2UI host)It uses the same port as the Gateway (default 18789).
agent, chat, presence, health, heartbeat, cron.health, status, send, agent, system-presence).tick, agent, presence, shutdown).role: node.connect; pairing is device-based (role node) and
approval lives in the device pairing store.canvas.*, camera.*, screen.record, location.get.Protocol details: Gateway protocol
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
snapshot: presence + health
Gateway-->>Client: event:presence
Gateway-->>Client: event:tick
Client->>Gateway: req:agent
Gateway-->>Client: res:agent
ack {runId, status:"accepted"}
Gateway-->>Client: event:agent
(streaming)
Gateway-->>Client: res:agent
final {runId, status, summary}
connect.{type:"req", id, method, params} → {type:"res", id, ok, payload|error}{type:"event", event, payload, seq?, stateVersion?}hello-ok.features.methods / events are discovery metadata, not a
generated dump of every callable helper route.connect.params.auth.token or
connect.params.auth.password, depending on the configured gateway auth mode.gateway.auth.allowTailscale: true) or non-loopback
gateway.auth.mode: "trusted-proxy" satisfy auth from request headers
instead of connect.params.auth.*.gateway.auth.mode: "none" disables shared-secret auth
entirely; keep that mode off public/untrusted ingress.send, agent) to
safely retry; the server keeps a short-lived dedupe cache.role: "node" plus caps/commands/permissions in connect.connect.connect.challenge nonce. Signature payload v3
also binds platform and deviceFamily; the gateway pins paired metadata on
reconnect and requires repair pairing for metadata changes.gateway.auth.*) still applies to all connections, local or
remote.Details: Gateway protocol, Pairing, Security.
Preferred: Tailscale or VPN.
Alternative: SSH tunnel
ssh -N -L 18789:127.0.0.1:18789 user@gateway-host
The same handshake + auth token apply over the tunnel.
TLS + optional pinning can be enabled for WS in remote setups.
openclaw gateway (foreground, logs to stdout).health over WS (also included in hello-ok).