* 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 commit4f8ef3699d) (cherry picked from commit 74fbdcc99d5fff062d67760a51dba4ee9e84479b) (cherry picked from commit 222b285502681d2be14b1819798e9ee5555f431e) (cherry picked from commit b9e744951f676b600e7c5322bfd04b0e99797c07) (cherry picked from commit9e904efde5) (cherry picked from commit678f2384fa) (cherry picked from commit72842e5cf6) (cherry picked from commit be74c25e80e84a1f065053766f23efb84822e811) (cherry picked from commit93ba8c4b09) (cherry picked from commit8f23761372) * 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 commit9b7e5a9608) (cherry picked from commit 4b507593f1b2f10b4496984c84a2803b853e5c5e) (cherry picked from commit 56408a186733c4eeb5aa76bd5907cde7b0cd3d5b) (cherry picked from commit a4051d6d8353d39d6fa0b5d69c36e06c3cd3e796) (cherry picked from commit76829805a7) (cherry picked from commita8b493f934) (cherry picked from commitaceb990597) (cherry picked from commit a29b0e75482470c53a9fb4fe3f204e14cf71868f) (cherry picked from commit2e3be08653) (cherry picked from commitc9ae3d7202) * 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
14 KiB
summary, read_when, title
| summary | read_when | title | |
|---|---|---|---|
| Runbook for the Gateway service, lifecycle, and operations |
|
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 isauto(resolves to0.0.0.0for port-forwarding), unless Tailscale serve/funnel is active, which always forcesloopback. - Auth is required by default. Shared-secret setups use
gateway.auth.token/gateway.auth.password(orOPENCLAW_GATEWAY_TOKEN/OPENCLAW_GATEWAY_PASSWORD), and non-loopback reverse-proxy setups can usegateway.auth.mode: "trusted-proxy".
OpenAI-compatible endpoints
OpenClaw's highest-leverage compatibility surface:
GET /v1/modelsGET /v1/models/{id}POST /v1/embeddingsPOST /v1/chat/completionsPOST /v1/responses
Why this set matters:
- Most Open WebUI, LobeChat, and LibreChat integrations probe
/v1/modelsfirst. - 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 | --port → OPENCLAW_GATEWAY_PORT → gateway.port → 18789 |
| Bind mode | CLI/override → gateway.bind → loopback (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 --deepcan reportOther gateway-like services detected (best effort)and print cleanup hints when stale launchd/systemd/schtasks installs are still around.gateway probecan warn aboutmultiple reachable gateway identitieswhen 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.
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-okframe with asnapshot(presence,health,stateVersion,uptimeMs) pluspolicylimits (maxPayload,maxBufferedBytes,tickIntervalMs). hello-ok.features.methods/eventsare 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-insession.approval,sessions.changed,presence,tick,health,heartbeat, pairing/approval lifecycle events, andshutdown.
Agent runs are two-stage:
- Immediate accepted ack (
status:"accepted") - Final completion response (
status:"ok"|"error"), with streamedagentevents in between.
See full protocol docs: Gateway Protocol.
Operational checks
Liveness
- Open WS and send
connect. - Expect
hello-okresponse 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
shutdownevent before socket close.