Welcome to Raspberry Pi 5 repository
06. OpenClawGate Gateway User Manual
Gateway Runtime Manual
Last updated: 2025-12-09
What It Is
- A resident process with a single Baileys/Telegram connection and control/event plane.
- Replaces the old
gatewaycommand. CLI entry point:openclaw gateway. - Runs until stopped; exits with non-zero exit code on fatal errors so supervisor can restart it.
How to Run (Local)
openclaw gateway --port 18789# Get full debug/trace logs in stdio:openclaw gateway --port 18789 --verbose# If port is occupied, terminate listener then start:openclaw gateway --force# Development loop (auto-reload on TS changes):pnpm gateway:watchConfiguration hot reload watches ~/.openclaw/openclaw.json (or OPENCLAW_CONFIG_PATH).
- Default mode:
gateway.reload.mode="hybrid"(hot-applies safe changes, restarts on critical changes). - Hot reload uses SIGUSR1 for in-process restart when needed.
- Use
gateway.reload.mode="off"to disable.
- Default mode:
Binds WebSocket control plane to
127.0.0.1:<port>(default 18789).Same port also serves HTTP (control interface, hooks, A2UI). Single port multiplexing.
- OpenAI Chat Completions (HTTP):
/v1/chat/completions. - OpenResponses (HTTP):
/v1/responses. - Tools Invoke (HTTP):
/tools/invoke.
- OpenAI Chat Completions (HTTP):
By default starts Canvas file server on
canvasHost.port(default18793), servinghttp://<gateway-host>:18793/__openclaw__/canvas/from~/.openclaw/workspace/canvas. UsecanvasHost.enabled=falseorOPENCLAW_SKIP_CANVAS_HOST=1to disable.Logs to stdout; use launchd/systemd to keep running and rotate logs.
Pass
--verbosefor troubleshooting to mirror debug logs (handshakes, requests/responses, events) from log file to stdio.--forceuseslsofto find listener on selected port, sends SIGTERM, logs what it terminated, then starts Gateway (fails fast iflsofmissing).If you're running under a supervisor (launchd/systemd/mac app subprocess mode), stop/restart usually sends SIGTERM; old versions may show this as
pnpmELIFECYCLEexit code 143 (SIGTERM), which is normal shutdown, not a crash.SIGUSR1 triggers in-process restart when authorized (Gateway tools/config apply/update, or enable
commands.restartfor manual restart).By default requires Gateway authentication: set
gateway.auth.token(orOPENCLAW_GATEWAY_TOKEN) orgateway.auth.password. Clients must sendconnect.params.auth.token/passwordunless using Tailscale Serve identity.Wizard now generates tokens by default, even on loopback.
Port priority:
--port>OPENCLAW_GATEWAY_PORT>gateway.port> default18789.
Remote Access
Prefer Tailscale/VPN; otherwise use SSH tunnel:
xxxxxxxxxxssh -N -L 18789:127.0.0.1:18789 user@hostThen clients connect to
ws://127.0.0.1:18789through the tunnel.If token is configured, clients must include it in
connect.params.auth.tokeneven through tunnel.
Multiple Gateways (Same Host)
Usually not needed: one Gateway can serve multiple message channels and agents. Use multiple Gateways only when you need redundancy or strict isolation (e.g., rescue bot). Supported if you isolate state + configuration and use unique ports. Full guide: Multiple Gateways. Service names are profile-aware:
- macOS:
bot.molt.<profile>(legacycom.openclaw.*may still exist) - Linux:
openclaw-gateway-<profile>.service - Windows:
OpenClaw Gateway (<profile>)
Installation metadata is embedded in service configuration:
OPENCLAW_SERVICE_MARKER=openclawOPENCLAW_SERVICE_KIND=gatewayOPENCLAW_SERVICE_VERSION=<version>
Rescue bot mode: Keep a second Gateway isolated with its own profile, state directory, workspace, and base port offset. Full guide: Rescue Bot Guide.
Dev Profile (--dev)
Quick path: Run completely isolated dev instance (config/state/workspace) without touching your main setup.
xxxxxxxxxxopenclaw --dev setupopenclaw --dev gateway --allow-unconfigured# Then target dev instance:openclaw --dev statusopenclaw --dev healthDefaults (overridable via env/flags/config):
OPENCLAW_STATE_DIR=~/.openclaw-devOPENCLAW_CONFIG_PATH=~/.openclaw-dev/openclaw.jsonOPENCLAW_GATEWAY_PORT=19001(Gateway WS + HTTP)- Browser control service port =
19003(derived:gateway.port+2, loopback only) canvasHost.port=19005(derived:gateway.port+4)- When you run
setup/onboardunder--dev,agents.defaults.workspacedefaults to~/.openclaw/workspace-dev.
Derived ports (rule of thumb):
- Base port =
gateway.port(orOPENCLAW_GATEWAY_PORT/--port) - Browser control service port = base + 2 (loopback only)
canvasHost.port = base + 4(orOPENCLAW_CANVAS_HOST_PORT/ config override)- Browser profile CDP ports auto-allocated from
browser.controlPort + 9 .. + 108(persisted per profile).
Per-instance checklist:
- Unique
gateway.port - Unique
OPENCLAW_CONFIG_PATH - Unique
OPENCLAW_STATE_DIR - Unique
agents.defaults.workspace - Separate WhatsApp number (if using WA)
Install services by profile:
xxxxxxxxxxopenclaw --profile main gateway installopenclaw --profile rescue gateway installExample:
xxxxxxxxxxOPENCLAW_CONFIG_PATH=~/.openclaw/a.json OPENCLAW_STATE_DIR=~/.openclaw-a openclaw gateway --port 19001OPENCLAW_CONFIG_PATH=~/.openclaw/b.json OPENCLAW_STATE_DIR=~/.openclaw-b openclaw gateway --port 19002
Protocol (Operations View)
Full documentation: Gateway Protocol and Bridge Protocol (Legacy).
First frame clients must send:
req {type:"req", id, method:"connect", params:{minProtocol,maxProtocol,client:{id,displayName?,version,platform,deviceFamily?,modelIdentifier?,mode,instanceId?}, caps, auth?, locale?, userAgent? } }.Gateway replies
res {type:"res", id, ok:true, payload:hello-ok }(orok:falsewith error, then close).After handshake:
- Requests:
{type:"req", id, method, params}→{type:"res", id, ok, payload|error} - Events:
{type:"event", event, payload, seq?, stateVersion?}
- Requests:
Structured presence entries:
{host, ip, version, platform?, deviceFamily?, modelIdentifier?, mode, lastInputSeconds?, ts, reason?, tags?[], instanceId? }(for WS clients,instanceIdfromconnect.client.instanceId).agentresponses are two-phase: firstresacknowledges{runId,status:"accepted"}, then finalres{runId,status:"ok"|"error",summary}sent after run completes; streaming output arrives asevent:"agent".
Methods (Initial Set)
health— Full health snapshot (same shape asopenclaw health --json).status— Brief summary.system-presence— Current presence list.system-event— Publish presence/system annotation (structured).send— Send message via active channel.agent— Run agent turn (streams events back on same connection).node.list— List paired + currently connected nodes (includingcaps,deviceFamily,modelIdentifier,paired,connected, and broadcastedcommands).node.describe— Describe node (capabilities + supportednode.invokecommands; works for paired nodes and currently connected unpaired nodes).node.invoke— Invoke command on node (e.g.,canvas.*,camera.*).node.pair.*— Pairing lifecycle (request,list,approve,reject,verify).
See also: Presence for how presence is generated/deduplicated and why stable client.instanceId is important.
Events
agent— Streaming tool/output events from agent runs (with seq markers).presence— Presence updates (deltas with stateVersion) pushed to all connected clients.tick— Periodic keepalive/noop to confirm liveness.shutdown— Gateway is exiting; payload includesreasonand optionalrestartExpectedMs. Clients should reconnect.
WebChat Integration
- WebChat is native SwiftUI UI that talks directly to Gateway WebSocket for history, send, abort, and events.
- Remote use works through same SSH/Tailscale tunnel; if Gateway token is configured, client includes it during
connect. - macOS app uses single WS connection (shared connection); it populates presence from initial snapshot and listens to
presenceevents to update UI.
Types and Validation
Server validates each inbound frame using AJV against JSON Schema emitted from protocol definition.
Clients (TS/Swift) consume generated types (TS directly; Swift via repo's generator).
Protocol definition is source of truth; regenerate schema/models with:
pnpm protocol:genpnpm protocol:gen:swift
Connection Snapshot
hello-okcontainssnapshotwithpresence,health,stateVersion, anduptimeMs, pluspolicy {maxPayload,maxBufferedBytes,tickIntervalMs}, so clients can render immediately without extra requests.health/system-presencestill available for manual refresh but not required on connect.
Error Codes (res.error shape)
Errors use `{ code, message, details?, retryable?, retryAfterMs? }".
Standard codes:
NOT_LINKED— WhatsApp not authenticated.AGENT_TIMEOUT— Agent didn't respond within configured deadline.INVALID_REQUEST— schema/parameter validation failed.UNAVAILABLE— Gateway is shutting down or dependency unavailable.
Keepalive Behavior
tickevents (or WS ping/pong) are sent periodically so clients know Gateway is alive even when there's no traffic.- Send/agent acknowledgments remain separate responses; don't overload tick for sends.
Replay / Gaps
Events are not replayed. Clients detect seq gaps and should refresh (health + system-presence) before continuing. WebChat and macOS clients now auto-refresh on gaps.
Supervision (macOS Example)
Use launchd to keep service alive:
- Program: path to
openclaw - Arguments:
gateway - KeepAlive: true
- StandardOut/Err: file paths or
syslog
- Program: path to
On failure, launchd restarts; fatal configuration errors should stay exited so ops notice.
LaunchAgents are per-user and require logged-in session; for headless setups, use custom LaunchDaemon (not bundled).
openclaw gateway installwrites~/Library/LaunchAgents/bot.molt.gateway.plist(orbot.molt.<profile>.plist; legacycom.openclaw.*will be cleaned up).openclaw doctoraudits LaunchAgent config and can update it to current defaults.
Gateway Service Management (CLI)
Use Gateway CLI for install/start/stop/restart/status:
xxxxxxxxxxopenclaw gateway statusopenclaw gateway installopenclaw gateway stopopenclaw gateway restartopenclaw logs --follow
Notes:
gateway statusby default probes Gateway RPC using service-resolved port/config (override with--url).gateway status --deepadds system-level scan (LaunchDaemons/system units).gateway status --no-probeskips RPC probe (useful when network is down).gateway status --jsonis stable for scripting.gateway statusreports supervisor runtime (launchd/systemd running) separate from RPC reachability (WS connection + status RPC).gateway statusprints config path + probe target to avoid "localhost vs LAN bind" confusion and profile mismatches.gateway statusincludes last Gateway error line when service appears running but port is closed.logstails Gateway file logs via RPC (no manualtail/grepneeded).CLI warns if it detects other Gateway-like services, unless they are OpenClaw profile services. We still recommend most setups have one Gateway per machine; use isolated profiles/ports for redundancy or rescue bots. See Multiple Gateways.
- Cleanup:
openclaw gateway uninstall(current service) andopenclaw doctor(legacy migration).
- Cleanup:
gateway installis no-op when already installed; useopenclaw gateway install --forceto reinstall (profile/env/path changes).
Bundled mac app:
OpenClaw.app can bundle Node-based Gateway relay and install per-user LaunchAgent labeled
bot.molt.gateway(orbot.molt.<profile>; legacycom.openclaw.*labels still clean uninstall).To stop it cleanly, use
openclaw gateway stop(orlaunchctl bootout gui/$UID/bot.molt.gateway).To restart, use openclaw gateway restart (or launchctl kickstart -k gui/$UID/bot.molt.gateway).
launchctlonly works if LaunchAgent is installed; otherwise useopenclaw gateway installfirst.- When running named profile, replace label with
bot.molt.<profile>.
Supervision (systemd user units)
OpenClaw defaults to systemd user services on Linux/WSL2. We recommend user services for single-user machines (simpler env, per-user config). For multi-user or always-on servers use system services (no lingering needed, shared supervision). openclaw gateway install writes user unit. openclaw doctor audits unit and can update it to match current recommended defaults. Creates ~/.config/systemd/user/openclaw-gateway[-<profile>].service:
x[Unit]Description=OpenClaw Gateway (profile: <profile>, v<version>)After=network-online.targetWants=network-online.target[Service]ExecStart=/usr/local/bin/openclaw gateway --port 18789Restart=alwaysRestartSec=5Environment=OPENCLAW_GATEWAY_TOKEN=WorkingDirectory=/home/youruser[Install]WantedBy=default.target
Enable lingering (required for user services to survive logout/idle):
xxxxxxxxxxsudo loginctl enable-linger youruser
Onboarding runs this on Linux/WSL2 (may prompt for sudo; writes /var/lib/systemd/linger). Then enable service:
xxxxxxxxxxsystemctl --user enable --now openclaw-gateway[-<profile>].service
Alternative (system service) - For always-on or multi-user servers, you can install systemd system unit instead of user unit (no lingering needed). Create /etc/systemd/system/openclaw-gateway[-<profile>].service (copy unit above, switch WantedBy=multi-user.target, set User= + WorkingDirectory=), then:
xxxxxxxxxxsudo systemctl daemon-reloadsudo systemctl enable --now openclaw-gateway[-<profile>].service
Windows (WSL2)
Windows installations should use WSL2 and follow the Linux systemd section above.
Operations Checks
- Liveness check: Open WS and send
req:connect→ expectreswithpayload.type="hello-ok"(with snapshot). - Readiness check: Call
health→ expectok: trueand linked channel inlinkChannel(when applicable). - Debug: Subscribe to
tickandpresenceevents; ensurestatusshows linked/auth time; presence entries show Gateway host and connected clients.
Security Guarantees
- Default assumes one Gateway per host; if you run multiple profiles, isolate ports/state and target the correct instance.
- Won't fall back to direct Baileys connection; if Gateway is down, sends fail fast.
- Non-connect first frame or malformed JSON is rejected and socket closed.
- Graceful shutdown: emits
shutdownevent before close; clients must handle close + reconnect.
CLI Helpers
openclaw gateway health|status— Request health/status via Gateway WS.openclaw message send --target <num> --message "hi" [--media ...]— Send via Gateway (idempotent for WhatsApp).openclaw agent --message "hi" --to <num>— Run agent turn (waits for final result by default).openclaw gateway call <method> --params '{"k":"v"}'— Raw method invoker for debugging.openclaw gateway stop|restart— Stop/restart supervised Gateway service (launchd/systemd).- Gateway helper subcommands assume running Gateway on
--url; they no longer auto-spawn one.
Migration Guide
- Deprecate use of
openclaw gatewayand legacy TCP control port. - Update clients to use WS protocol with mandatory connect and structured presence.
For more Gateway content, refer to: Gateway Runtime Manual - OpenClaw