Skip to content

Gateway Runbook

Last updated: 2025-12-09

  • The always-on process that owns the single Baileys/Telegram connection and the control/event plane.
  • Replaces the legacy gateway command. CLI entry point: openclaw gateway.
  • Runs until stopped; exits non-zero on fatal errors so the supervisor restarts it.
Terminal window
openclaw gateway --port 18789
# for full debug/trace logs in stdio:
openclaw gateway --port 18789 --verbose
# if the port is busy, terminate listeners then start:
openclaw gateway --force
# dev loop (auto-reload on TS changes):
pnpm gateway:watch
  • Config hot reload watches ~/.openclaw/openclaw.json (or OPENCLAW_CONFIG_PATH).
    • Default mode: gateway.reload.mode="hybrid" (hot-apply safe changes, restart on critical).
    • Hot reload uses in-process restart via SIGUSR1 when needed.
    • Disable with gateway.reload.mode="off".
  • Binds WebSocket control plane to 127.0.0.1:<port> (default 18789).
  • The same port also serves HTTP (control UI, hooks, A2UI). Single-port multiplex.
  • Starts a Canvas file server by default on canvasHost.port (default 18793), serving http://<gateway-host>:18793/__openclaw__/canvas/ from ~/.openclaw/workspace/canvas. Disable with canvasHost.enabled=false or OPENCLAW_SKIP_CANVAS_HOST=1.
  • Logs to stdout; use launchd/systemd to keep it alive and rotate logs.
  • Pass --verbose to mirror debug logging (handshakes, req/res, events) from the log file into stdio when troubleshooting.
  • --force uses lsof to find listeners on the chosen port, sends SIGTERM, logs what it killed, then starts the gateway (fails fast if lsof is missing).
  • If you run under a supervisor (launchd/systemd/mac app child-process mode), a stop/restart typically sends SIGTERM; older builds may surface this as pnpm ELIFECYCLE exit code 143 (SIGTERM), which is a normal shutdown, not a crash.
  • SIGUSR1 triggers an in-process restart when authorized (gateway tool/config apply/update, or enable commands.restart for manual restarts).
  • Gateway auth is required by default: set gateway.auth.token (or OPENCLAW_GATEWAY_TOKEN) or gateway.auth.password. Clients must send connect.params.auth.token/password unless using Tailscale Serve identity.
  • The wizard now generates a token by default, even on loopback.
  • Port precedence: --port > OPENCLAW_GATEWAY_PORT > gateway.port > default 18789.
  • Tailscale/VPN preferred; otherwise SSH tunnel:
    Terminal window
    ssh -N -L 18789:127.0.0.1:18789 user@host
  • Clients then connect to ws://127.0.0.1:18789 through the tunnel.
  • If a token is configured, clients must include it in connect.params.auth.token even over the tunnel.

Usually unnecessary: one Gateway can serve multiple messaging channels and agents. Use multiple Gateways only for redundancy or strict isolation (ex: rescue bot).

Supported if you isolate state + config and use unique ports. Full guide: Multiple gateways.

Service names are profile-aware:

  • macOS: bot.molt.<profile> (legacy com.openclaw.* may still exist)
  • Linux: openclaw-gateway-<profile>.service
  • Windows: OpenClaw Gateway (<profile>)

Install metadata is embedded in the service config:

  • OPENCLAW_SERVICE_MARKER=openclaw
  • OPENCLAW_SERVICE_KIND=gateway
  • OPENCLAW_SERVICE_VERSION=<version>

Rescue-Bot Pattern: keep a second Gateway isolated with its own profile, state dir, workspace, and base port spacing. Full guide: Rescue-bot guide.

Fast path: run a fully-isolated dev instance (config/state/workspace) without touching your primary setup.

Terminal window
openclaw --dev setup
openclaw --dev gateway --allow-unconfigured
# then target the dev instance:
openclaw --dev status
openclaw --dev health

Defaults (can be overridden via env/flags/config):

  • OPENCLAW_STATE_DIR=~/.openclaw-dev
  • OPENCLAW_CONFIG_PATH=~/.openclaw-dev/openclaw.json
  • OPENCLAW_GATEWAY_PORT=19001 (Gateway WS + HTTP)
  • browser control service port = 19003 (derived: gateway.port+2, loopback only)
  • canvasHost.port=19005 (derived: gateway.port+4)
  • agents.defaults.workspace default becomes ~/.openclaw/workspace-dev when you run setup/onboard under --dev.

Derived ports (rules of thumb):

  • Base port = gateway.port (or OPENCLAW_GATEWAY_PORT / --port)
  • browser control service port = base + 2 (loopback only)
  • canvasHost.port = base + 4 (or OPENCLAW_CANVAS_HOST_PORT / config override)
  • Browser profile CDP ports auto-allocate from browser.controlPort + 9 .. + 108 (persisted per profile).

Checklist per instance:

  • unique gateway.port
  • unique OPENCLAW_CONFIG_PATH
  • unique OPENCLAW_STATE_DIR
  • unique agents.defaults.workspace