Files
openclaw/docs/gateway/index.md
Peter Steinberger 5b56a1f664 feat(gateway): land remaining durable-approvals stack and repair main gates (#104837)
* feat(gateway): propagate approvals to ancestor sessions with replay

Squash-rebased #103921 segment onto the native-clients tip on current main.
Session-scoped approval events publish sanitized pending/terminal
transitions to opted-in session audiences, with authoritative pending
replay on stream subscribe and durable-expiry reconciliation through the
owning manager. SessionApprovalEvent/Replay wire types export from the
approvals owner module; Swift models regenerated.

(cherry picked from commit 2d1dcf9747044710111d0c730fc46ba6013a165c)
(cherry picked from commit ccf88efd56b513d07599ffcee997bf0cddaf9adc)
(cherry picked from commit 8eb33f59f00ec9ee4625259b76bd7ae60d2cd480)
(cherry picked from commit c297cbc93c8401e9c79c20f242245a194f5dd236)
(cherry picked from commit 93d68f28601ff37d863da4db009504993a22533a)
(cherry picked from commit d285ccd8b2f212bb57e814107e7709c896e96b7d)
(cherry picked from commit 5c536982231402b1b58d1683794ea9948b32d077)
(cherry picked from commit 1646e5b6dc4dd20de54e10f110a5909be18d7d50)
(cherry picked from commit 35cf1b705b247fb282f4d56ffe74bd2fb238221f)
(cherry picked from commit 4f8ef3699d)
(cherry picked from commit 74fbdcc99d5fff062d67760a51dba4ee9e84479b)
(cherry picked from commit 222b285502681d2be14b1819798e9ee5555f431e)
(cherry picked from commit b9e744951f676b600e7c5322bfd04b0e99797c07)
(cherry picked from commit 9e904efde5)
(cherry picked from commit 678f2384fa)
(cherry picked from commit 72842e5cf6)
(cherry picked from commit be74c25e80e84a1f065053766f23efb84822e811)
(cherry picked from commit 93ba8c4b09)
(cherry picked from commit 8f23761372)

* feat(gateway): fail-closed plugin and tool approval gates

Squash-rebased #103932 segment onto the ancestor-propagation tip on
current main. Plugin node.invoke approvals claim a one-shot allow-once
decision before handing execution authority to the policy, so observation
or retry cannot replay a consumed approval; sibling tool gates bind
approval ids to their originating reviewer identity.

(cherry picked from commit 122df0d75281f572c012b6484ed5daf085d1d577)
(cherry picked from commit f23d8ac240a8dcf2a42c4daaae962263975a0ae8)
(cherry picked from commit 8632fb6436a224dac7a9a9ef0216884530de2c24)
(cherry picked from commit d9fe2dd5c53665e5732f5f3da5ed1907a686ade8)
(cherry picked from commit bb139f2c8aa36ddad70413e1ef79ff491a6f2ecd)
(cherry picked from commit 9b3e056b68ea515c7d4baef269289b6670570480)
(cherry picked from commit b11e66b59a7af1f3b08712de06864aed64d349e4)
(cherry picked from commit a12916ee592d03dfa35e86a2aaede4476a5d4e5d)
(cherry picked from commit d699de840fc8346892b9ae244fe3c3e8c4413032)
(cherry picked from commit 9b7e5a9608)
(cherry picked from commit 4b507593f1b2f10b4496984c84a2803b853e5c5e)
(cherry picked from commit 56408a186733c4eeb5aa76bd5907cde7b0cd3d5b)
(cherry picked from commit a4051d6d8353d39d6fa0b5d69c36e06c3cd3e796)
(cherry picked from commit 76829805a7)
(cherry picked from commit a8b493f934)
(cherry picked from commit aceb990597)
(cherry picked from commit a29b0e75482470c53a9fb4fe3f204e14cf71868f)
(cherry picked from commit 2e3be08653)
(cherry picked from commit c9ae3d7202)

* fix: main-gate repairs for the durable-approvals stack

- android: capture createdAtMs on the pending exec-approval write at
  registration; canonical readback after a refresh that already replaced
  the visible rows was dropping the approval instead of surfacing the
  still-pending reconciliation message (#104913 merged without this)
- android: generous CI timeout ceilings in GatewayExecApprovalRuntimeTest
- agents: hermetic model-discovery test via the plugins/provider-runtime
  boundary (lazy plugin-runtime resolution hangs vitest workers since #104770)
- cli: usage-cost settle-budget test asserts the budget bound on every call
  instead of pinning the poll count (fast hosts fit a second poll in 50ms)
- protocol coverage: allowlist session.approval for ios/android (native
  review rides exec.approval push/nudge delivery)
- docs map, native i18n inventory, plugin-sdk api baseline regenerated
2026-07-12 10:51:38 +01:00

14 KiB

summary, read_when, title
summary read_when title
Runbook for the Gateway service, lifecycle, and operations
Running or debugging the gateway process
Gateway runbook

Use this page for day-1 startup and day-2 operations of the Gateway service.

Symptom-first diagnostics with exact command ladders and log signatures. Task-oriented setup guide + full configuration reference. SecretRef contract, runtime snapshot behavior, and migrate/reload operations. Exact `secrets apply` target/path rules and ref-only auth-profile behavior.

5-minute local startup

openclaw gateway --port 18789
# debug/trace mirrored to stdio
openclaw gateway --port 18789 --verbose
# force-kill listener on selected port, then start
openclaw gateway --force
openclaw gateway status
openclaw status
openclaw logs --follow

Healthy baseline: Runtime: running, Connectivity probe: ok, and a Capability line that matches what you expect. Use openclaw gateway status --require-rpc for read-scope RPC proof, not just reachability.

openclaw channels status --probe

With a reachable gateway this runs live per-account channel probes and optional audits. If the gateway is unreachable, the CLI falls back to config-only channel summaries.

Gateway config reload watches the active config file path (resolved from profile/state defaults, or `OPENCLAW_CONFIG_PATH` when set). Default mode is `gateway.reload.mode="hybrid"`. After the first successful load, the running process serves the active in-memory config snapshot; a successful reload swaps that snapshot atomically.

Runtime model

  • One always-on process for routing, control plane, and channel connections.
  • Single multiplexed port for:
    • WebSocket control/RPC
    • HTTP APIs (/v1/models, /v1/embeddings, /v1/chat/completions, /v1/responses, /tools/invoke)
    • Plugin HTTP routes, such as optional /api/v1/admin/rpc
    • Control UI and hooks
  • Default bind mode: loopback. Inside a detected container environment the effective default is auto (resolves to 0.0.0.0 for port-forwarding), unless Tailscale serve/funnel is active, which always forces loopback.
  • Auth is required by default. Shared-secret setups use gateway.auth.token / gateway.auth.password (or OPENCLAW_GATEWAY_TOKEN / OPENCLAW_GATEWAY_PASSWORD), and non-loopback reverse-proxy setups can use gateway.auth.mode: "trusted-proxy".

OpenAI-compatible endpoints

OpenClaw's highest-leverage compatibility surface:

  • GET /v1/models
  • GET /v1/models/{id}
  • POST /v1/embeddings
  • POST /v1/chat/completions
  • POST /v1/responses

Why this set matters:

  • Most Open WebUI, LobeChat, and LibreChat integrations probe /v1/models first.
  • Many RAG and memory pipelines expect /v1/embeddings.
  • Agent-native clients increasingly prefer /v1/responses.

/v1/models is agent-first: it returns openclaw, openclaw/default, and openclaw/<agentId> for every configured agent. openclaw/default is the stable alias that always maps to the configured default agent. Send x-openclaw-model when you want a backend provider/model override; otherwise the selected agent's normal model and embedding setup stays in control.

All of these run on the main Gateway port and use the same trusted operator auth boundary as the rest of the Gateway HTTP API.

Admin HTTP RPC (POST /api/v1/admin/rpc) is a separate, default-off plugin route for host tooling that cannot use WebSocket RPC. See Admin HTTP RPC.

Port and bind precedence

Setting Resolution order
Gateway port --portOPENCLAW_GATEWAY_PORTgateway.port18789
Bind mode CLI/override → gateway.bindloopback (or auto in containers)

Installed gateway services record the resolved --port in supervisor metadata. After changing gateway.port, run openclaw doctor --fix or openclaw gateway install --force so launchd/systemd/schtasks starts the process on the new port.

Gateway startup uses the same effective port and bind when it seeds local Control UI origins for non-loopback binds. For example, --bind lan --port 3000 seeds http://localhost:3000 and http://127.0.0.1:3000 before runtime validation runs. Add any remote browser origins, such as HTTPS proxy URLs, to gateway.controlUi.allowedOrigins explicitly.

Hot reload modes

gateway.reload.mode Behavior
off No config reload
hot Apply only hot-safe changes
restart Restart on reload-required changes
hybrid (default) Hot-apply when safe, restart when required

Operator command set

openclaw gateway status
openclaw gateway status --deep   # adds a system-level service scan
openclaw gateway status --json
openclaw gateway install
openclaw gateway restart
openclaw gateway stop
openclaw secrets reload
openclaw logs --follow
openclaw doctor

gateway status --deep is for extra service discovery (LaunchDaemons/systemd system units/schtasks), not a deeper RPC health probe.

Multiple gateways (same host)

Most installs should run one gateway per machine. A single gateway can host multiple agents and channels. You only need multiple gateways when you intentionally want isolation or a rescue bot.

Useful checks:

openclaw gateway status --deep
openclaw gateway probe

What to expect:

  • gateway status --deep can report Other gateway-like services detected (best effort) and print cleanup hints when stale launchd/systemd/schtasks installs are still around.
  • gateway probe can warn about multiple reachable gateway identities when distinct gateways answer, or when OpenClaw cannot prove reachable targets are the same gateway. An SSH tunnel, proxy URL, or configured remote URL to the same gateway is one gateway with multiple transports, even when transport ports differ.
  • If that is intentional, isolate ports, config/state, and workspace roots per gateway.

Checklist per instance:

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

Example:

OPENCLAW_CONFIG_PATH=~/.openclaw/a.json OPENCLAW_STATE_DIR=~/.openclaw-a openclaw gateway --port 19001
OPENCLAW_CONFIG_PATH=~/.openclaw/b.json OPENCLAW_STATE_DIR=~/.openclaw-b openclaw gateway --port 19002

Detailed setup: /gateway/multiple-gateways.

Remote access

Preferred: Tailscale/VPN. Fallback: SSH tunnel.

ssh -N -L 18789:127.0.0.1:18789 user@gateway-host

Then connect clients locally to ws://127.0.0.1:18789.

SSH tunnels do not bypass gateway auth. For shared-secret auth, clients still must send `token`/`password` even over the tunnel. For identity-bearing modes, the request still has to satisfy that auth path.

See: Remote Gateway, Authentication, Tailscale.

Supervision and service lifecycle

Use supervised runs for production-like reliability.

openclaw gateway install
openclaw gateway status
openclaw gateway restart
openclaw gateway stop

Use openclaw gateway restart for restarts. Do not chain openclaw gateway stop and openclaw gateway start as a restart substitute.

On macOS, gateway stop uses launchctl bootout by default. This removes the LaunchAgent from the current boot session without persisting a disable, so KeepAlive auto-recovery still works after unexpected crashes and gateway start re-enables cleanly. To persistently suppress auto-respawn across reboots, pass --disable: openclaw gateway stop --disable.

LaunchAgent labels are ai.openclaw.gateway (default) or ai.openclaw.<profile> (named profile). openclaw doctor audits and repairs service config drift.

openclaw gateway install
systemctl --user enable --now openclaw-gateway[-<profile>].service
openclaw gateway status

For persistence after logout, enable lingering:

sudo loginctl enable-linger $(whoami)

On a headless server without a desktop session, also make sure XDG_RUNTIME_DIR is set (export XDG_RUNTIME_DIR=/run/user/$(id -u)) before retrying systemctl --user commands.

Manual user-unit example when you need a custom install path:

[Unit]
Description=OpenClaw Gateway
After=network-online.target
Wants=network-online.target
StartLimitBurst=5
StartLimitIntervalSec=60

[Service]
ExecStart=/usr/local/bin/openclaw gateway --port 18789
Restart=always
RestartSec=5
RestartPreventExitStatus=78
TimeoutStopSec=30
TimeoutStartSec=30
SuccessExitStatus=0 143
OOMPolicy=continue
KillMode=control-group

[Install]
WantedBy=default.target
openclaw gateway install
openclaw gateway status --json
openclaw gateway restart
openclaw gateway stop

Native Windows managed startup uses a Scheduled Task named OpenClaw Gateway (or OpenClaw Gateway (<profile>) for named profiles). If Scheduled Task creation is denied, OpenClaw falls back to a per-user Startup-folder launcher that points at gateway.cmd inside the state directory.

Use a system unit for multi-user/always-on hosts.

sudo systemctl daemon-reload
sudo systemctl enable --now openclaw-gateway[-<profile>].service

Use the same service body as the user unit, but install it under /etc/systemd/system/openclaw-gateway[-<profile>].service and adjust ExecStart= if your openclaw binary lives elsewhere.

Do not also let openclaw doctor --fix install a user-level gateway service for the same profile/port. Doctor refuses that automatic install when it finds a system-level OpenClaw gateway service; use OPENCLAW_SERVICE_REPAIR_POLICY=external when the system unit owns the lifecycle.

Invalid configuration errors exit with code 78. Linux systemd units use RestartPreventExitStatus=78 to stop relaunching until the config is fixed. launchd and Windows Task Scheduler do not have an equivalent per-exit-code stop rule, so the Gateway also persists rapid unclean boot history and suppresses channel/provider account auto-start after repeated startup failures. In that safe mode the control plane still starts for inspection and repair, config hot reloads and secrets.reload refuse automatic channel restarts, and an explicit operator channels.start request can override the suppression.

Dev profile quick path

openclaw --dev setup
openclaw --dev gateway --allow-unconfigured
openclaw --dev status

Defaults include isolated state/config and base gateway port 19001.

Protocol quick reference (operator view)

  • First client frame must be connect.
  • Gateway returns a hello-ok frame with a snapshot (presence, health, stateVersion, uptimeMs) plus policy limits (maxPayload, maxBufferedBytes, tickIntervalMs).
  • hello-ok.features.methods / events are a conservative discovery list, not a generated dump of every callable helper route.
  • Requests: req(method, params)res(ok/payload|error).
  • Common events include connect.challenge, agent, chat, session.message, session.operation, session.tool, opt-in session.approval, sessions.changed, presence, tick, health, heartbeat, pairing/approval lifecycle events, and shutdown.

Agent runs are two-stage:

  1. Immediate accepted ack (status:"accepted")
  2. Final completion response (status:"ok"|"error"), with streamed agent events in between.

See full protocol docs: Gateway Protocol.

Operational checks

Liveness

  • Open WS and send connect.
  • Expect hello-ok response with snapshot.

Readiness

openclaw gateway status
openclaw channels status --probe
openclaw health

Gap recovery

Events are not replayed. On sequence gaps, refresh state (health, system-presence) before continuing.

Common failure signatures

Signature Likely issue
refusing to bind gateway ... without auth Non-loopback bind without a valid gateway auth path
another gateway instance is already listening / EADDRINUSE Port conflict
Gateway start blocked: set gateway.mode=local Config set to remote mode, or gateway.mode is missing from a damaged config
unauthorized during connect Auth mismatch between client and gateway

For full diagnosis ladders, use Gateway Troubleshooting.

Safety guarantees

  • Gateway protocol clients fail fast when Gateway is unavailable (no implicit direct-channel fallback).
  • Invalid/non-connect first frames are rejected and closed.
  • Graceful shutdown emits shutdown event before socket close.