#How to spawn subagents

1 messages · Page 1 of 1 (latest)

vestal raft
#

Curently my main agent can't spawn other sub agents

#

@cobalt mountain

cobalt mountainBOT
#

If you just want to use sub-agents, you don’t need any special command — just tell your agent:

  • “Spawn a sub-agent to research X”
  • “Spawn a sub-agent to analyze Y. Use gpt-5.2 and set a 5-minute timeout.”

OpenClaw will call the sessions_spawn tool behind the scenes; the sub-agent runs in the background and then announces the result back into this chat when it’s done.

To manage them from the chat, use the slash commands:

  • /subagents list
  • /subagents log <id|#> [limit] [tools]
  • /subagents stop <id|#|all>
  • /subagents send <id|#> <message>

Docs (full details + config like default subagent model / maxConcurrent):
https://docs.openclaw.ai/tools/subagents

vestal raft
#

ok, how to fix error
Gateway Error — the config token does not match the service token.

#

@cobalt mountain

cobalt mountainBOT
#

That error means the Gateway background service is running with a different auth token than what your current config says.

In practice it happens when you changed gateway.auth.token (or OPENCLAW_GATEWAY_TOKEN) but the installed service (systemd/launchd) is still using the old token / old service metadata.

Fix (safe default)

On the machine that runs the Gateway service:

  1. Check what’s running / what config it’s using:
openclaw --version
openclaw gateway status
openclaw config get gateway.auth.token
  1. Reinstall service metadata (this usually resolves “config vs service” mismatches), then restart:
#

I’m here — what are you stuck on now?

If it’s still the “config token does not match the service token” issue, paste the output of:

openclaw gateway status

(and tell me macOS vs Linux).

#
openclaw gateway install --force
openclaw gateway restart

If you’re using token auth and want to be explicit, you can also reinstall with the token you intend to use:

openclaw gateway install --force --token "<your gateway.auth.token>"
openclaw gateway restart

(Do not paste the token into Discord.)

If you’re on macOS (common gotcha)

If you ever set a launchctl override, it can “win” over your config. Check/unset it:

launchctl getenv OPENCLAW_GATEWAY_TOKEN
vestal raft
#

how to fix error OpenClaw ("pairing required") when bot trying to spawn other agents

#

@cobalt mountain

cobalt mountainBOT
#

pairing required means the Gateway is refusing the request until you approve the sender/device. It’s not a “subagent spawning” error by itself — spawning just triggers some action that needs an approved device/sender.

1) If you see this in the Control UI / Dashboard

Typical message: disconnected (1008): pairing required.

Fix (approve the browser/device):

openclaw devices list
openclaw devices approve <requestId>

Notes:

2) If this happens for Discord DMs (DM policy = pairing)

Approve the DM pairing code:

#
openclaw pairing list discord
openclaw pairing approve discord <CODE>

Docs: https://docs.openclaw.ai/channels/pairing and https://docs.openclaw.ai/channels/discord

3) If the bot is trying to use a node (system.run/canvas/camera/screen) and fails

Nodes also require device pairing:

openclaw devices list
openclaw devices approve <requestId>
openclaw nodes status

Docs: https://docs.openclaw.ai/nodes/index

If you paste where you see pairing required (Control UI vs Discord DM vs node tool output) + the exact line, I can point you to the exact approval flow.

#

domalex — that ping doesn’t include details, but pairing required always means “this sender/device hasn’t been approved yet” (it’s an auth gate, not a subagent/spawn permission).

Most common fixes:

A) It’s your browser / Control UI (WS disconnect 1008)

Approve the device:

openclaw devices list
openclaw devices approve <requestId>

Docs: https://docs.openclaw.ai/web/control-ui

B) It’s Discord DM pairing

Approve the DM code:

openclaw pairing list discord
#
openclaw pairing approve discord <CODE>

Docs: https://docs.openclaw.ai/channels/pairing

C) It’s a node host trying to connect (often confused with “subagents”)

Node connections also require device approval:

openclaw devices list
openclaw devices approve <requestId>
openclaw nodes status

Docs: https://docs.openclaw.ai/nodes/index

If you paste the exact line where you see pairing required (Control UI? gateway logs? node logs?) + openclaw --version, I can tell you which of A/B/C applies.

vestal raft
#

OpenClaw Gateway is running but sessions_spawn fails with "pairing required" error.

Environment:
macOS 15.1.1 (arm64)
OpenClaw 2026.2.19-2
Node 22.21.1

Error:
gateway closed (1008): pairing required
Gateway target: ws://127.0.0.1:18789

Steps taken:
openclaw gateway restart — Gateway runs, RPC probe: ok
openclaw pairing list — command hangs/exits with signal 9
openclaw pairing approve — no pairing codes to approve
Cleared session locks: rm -rf ~/.openclaw/agents//sessions/.lock
Reinstalled Gateway: openclaw gateway install --force

Current state:
Gateway: running (pid varies)
RPC probe: ok
sessions_spawn: fails with "pairing required"
CLI pairing commands: unresponsive or fail

Expected: sessions_spawn should work without manual pairing (as per docs for local loopback).

Question: How to complete pairing or bypass it for local agent-to-agent spawn?

cobalt mountainBOT
#

That specific error (gateway closed (1008): pairing required) is Gateway WebSocket device pairing (operator/device identity), not “subagent spawning permission” and not openclaw pairing … (that one is DM pairing codes).

So the fix path is:

1) Approve the pending device (operator) pairing

Run this on the machine that’s running the Gateway:

openclaw devices list --json --timeout 5000

If you see a pending request, approve it:

openclaw devices approve <requestId>
#

Docs: https://docs.openclaw.ai/web/control-ui (device pairing) and https://docs.openclaw.ai/cli/devices

2) If devices list doesn’t show anything / still fails

Then we need to figure out why the Gateway thinks the client is “non-local” (because loopback should auto-approve).

Do these checks:

openclaw config get gateway.trustedProxies
openclaw logs --follow

Then reproduce the sessions_spawn failure and look in the logs for the pairing line (it usually includes the connecting device id / role / client ip). That tells us which client is getting blocked (CLI vs Control UI vs some other worker) and what IP the Gateway is using for its “local auto-approve” check.

3) About “bypassing pairing”

There isn’t a supported “bypass pairing for sessions_spawn” knob—sessions_spawn doesn’t require pairing; your client can’t even stay connected to the Gateway WS right now, so the spawn call never gets through. Once the device pairing is approved (or the “why are you not local?” issue is fixed), spawning works normally.

#

If you paste:

  • the output of openclaw devices list --json (redact any tokens if present), and
  • the single relevant log line around “pairing required”

…I can tell you exactly what’s being blocked.

high gazelle
#

Gateway service check failed: Error: systemctl --user unavailable: Failed to connect to bus: No such file or directory

I get this error

cobalt mountainBOT
#

That error just means: OpenClaw tried to query the “Gateway service” via systemctl --user, but your environment doesn’t have a working systemd user bus (so the service check can’t run). It’s common in:

  • WSL2 (systemd not enabled)
  • Docker / containers (no systemd)
  • SSH/non-login contexts where the user manager isn’t running
  • Running the check under sudo (don’t use sudo systemctl --user …)

Quick workaround (still lets you use OpenClaw)

Run the gateway in the foreground:

openclaw gateway
# or: openclaw gateway run

To check if the gateway is actually up (without service manager):

#
openclaw gateway health --url ws://127.0.0.1:18789

If you’re on WSL2 (most common)

You need systemd enabled (docs): https://docs.openclaw.ai/platforms/windows

sudo tee /etc/wsl.conf >/dev/null <<'EOF'
[boot]
systemd=true
EOF

Then in PowerShell:

#
wsl --shutdown

Re-open WSL and verify:

systemctl --user status

If you’re on Linux with systemd, but user bus isn’t running

Try enabling lingering (keeps the user systemd instance alive):

sudo loginctl enable-linger $USER

Then log out/in (or reboot), and re-test:

#
systemctl --user status

If you tell me your environment (WSL? Docker? “real” Linux?) + openclaw --version, I can point you to the right “daemon install” path.

high gazelle
#

WSL

cobalt mountainBOT
#

Yep — in WSL that error almost always means systemd isn’t enabled, so systemctl --user … can’t connect to the user bus.

Fix (enable systemd in WSL2)

In your WSL distro (Ubuntu, etc.):

sudo tee /etc/wsl.conf >/dev/null <<'EOF'
[boot]
systemd=true
EOF

Then from PowerShell (Windows side):

wsl --shutdown
#

Re-open your WSL terminal and verify:

ps -p 1 -o comm=
systemctl --user status
  • ps … should show systemd
  • systemctl --user status should no longer error

Now you can use the gateway service flow again, e.g.:

openclaw gateway install
systemctl --user enable --now openclaw-gateway.service
openclaw gateway status
#

If you’re on WSL1 (or old WSL)

Systemd won’t work properly. Check:

wsl -l -v

If it shows version 1, convert to WSL2.

If you paste the output of wsl -l -v and your distro name (Ubuntu/Debian/etc.), I’ll give you the exact commands.

high gazelle
#

/root/.zshrc:4: parse error near `fi'
Nelson# ps -p 1 -o comm=
systemctl --user status
systemd
Failed to connect to bus: No such file or directory

cobalt mountainBOT
#

That combo usually means you’ve got systemd as PID 1, but you don’t have a user D‑Bus session, so systemctl --user … has nothing to talk to.

Two common causes in WSL:

1) You’re running as root (your log shows /root/.zshrc…)

systemctl --user expects a per-user runtime dir like /run/user/<uid>/bus. For root in WSL that often isn’t created.

Check:

whoami
id -u
echo $XDG_RUNTIME_DIR
ls -ld /run/user/$(id -u) /run/user/$(id -u)/bus

If whoami is root: exit and re-open WSL as your normal user (or sudo -iu <youruser>). Then try:

#
systemctl --user status

2) Missing dbus-user-session (common in minimal distros)

Install it, then restart WSL:

sudo apt update
sudo apt install -y dbus-user-session

Then from PowerShell:

wsl --shutdown

Re-open WSL and run:

#
systemctl --user status

About /root/.zshrc: parse error near fi

That’s separate (a broken if … fi in root’s zshrc). It’s another hint you’re landing in a root shell. Switching to a normal user usually avoids that too.

If you paste the outputs of the 5-line “check” block above (whoami/id/XDG_RUNTIME_DIR/ls), I can tell you exactly which of the two is biting you.

high gazelle
#

thanks -
Though I got an issue now on vscode Failed to connect to the remote extension host server (Error: WebSocket close with status code 1006)

cobalt mountainBOT
#

That VS Code error is from Remote‑WSL itself (not OpenClaw): the VS Code “server/extension host” in WSL drops the connection, so the client sees WebSocket close 1006.

The two most common causes match what you saw earlier:

1) Your shell startup is erroring (your …/.zshrc: parse error near 'fi')

If your default shell is zsh, a broken ~/.zshrc can crash the remote server bootstrap.

Fix options:

  • Fast test: switch to bash in WSL and try again
chsh -s /bin/bash

then restart WSL (see step 2 below) and reconnect from VS Code.

  • Or actually fix the broken ~/.zshrc (there’s an if missing a matching then/fi or similar).

2) Corrupted VS Code Server install in WSL

Resetting it is usually safe (it will re-download on next connect):

#
  1. Close VS Code.
  2. In PowerShell:
wsl --shutdown
  1. Open WSL and run:
rm -rf ~/.vscode-server ~/.vscode-server-insiders
  1. Re-open VS Code and “Reopen Folder in WSL”.

Quick check: are you accidentally running as root?

VS Code Remote works best as a normal Linux user.

whoami

If it says root, switch to your normal user and reconnect.

#

If this still fails: in VS Code open View → Output → “Remote - WSL” and paste the last ~30 lines here—those logs usually point straight at the exact rc file / missing dependency / permission issue.

high gazelle
#

System Node 12.22.9 at /usr/bin/node is below the required Node 22+. Using /home/nelson/.nvm/versions/node/v24.13.0/bin/node for the daemon. Install Node 22+ from nodejs.org or Homebrew.

cobalt mountainBOT
#

That message is basically a warning about your “system” Node:

  • /usr/bin/node = 12.22.9 (too old)
  • but OpenClaw found a good Node via nvm (~/.nvm/.../node v24.13.0) and says it will use that for the daemon.

So: if OpenClaw is indeed using the nvm Node for the service, you’re fine.

Recommended fix (WSL): make your default Node 22+ and reinstall service

In WSL as your normal user (not root):

node -v
which node

If that still shows Node 12, set a modern default in nvm:

#
nvm install 22
nvm alias default 22
nvm use 22
node -v

Then reinstall OpenClaw under that Node and reinstall the service:

npm i -g openclaw@latest
openclaw gateway install --force

If you want to eliminate Node 12 entirely (optional)

That old /usr/bin/node usually came from the Ubuntu/Debian nodejs package. You can upgrade via NodeSource or remove it, but I’d only do that if you’re comfortable changing system packages.

#

Quick sanity check: what Node is the service actually using?

Once systemctl --user works, check the unit:

systemctl --user cat openclaw-gateway.service

If you paste the ExecStart= line, I can tell you whether it’s guaranteed to run with the nvm Node or if it might still be picking up /usr/bin/node in some cases.

high gazelle
#

.nvm/versions/node/v24.13.0/bin/node"

cobalt mountainBOT
#

Good — ~/.nvm/versions/node/v24.13.0/bin/node is a perfectly fine Node (22+ required, 24 is OK). The warning you saw was just because your system Node at /usr/bin/node is still 12.

To make things stable (especially for the systemd user service + VS Code Remote), do this in WSL as your normal user:

# make sure your interactive shell uses the right node
which node
node -v

# set a default node for nvm (pick one)
nvm alias default 24.13.0
nvm use default

Then reinstall the gateway service so it captures the right runtime:

#
openclaw gateway install --force

If systemctl --user is working for you now, confirm what the service will run:

systemctl --user cat openclaw-gateway.service

Paste the ExecStart= line here — that will tell us whether it’s pinned to the nvm node path or still depends on PATH (which could fall back to /usr/bin/node).

If VS Code Remote is still flaky: also fix that .zshrc parse error (or temporarily switch default shell to bash), because a broken shell rc can break the remote extension host bootstrap.

high gazelle
#

Thanks, that worked

cobalt mountainBOT
#

Nice.

If this fixed it, please right-click the solution message → Apps → ✅ Mark Solution so Answer Overflow indexes it for the next person.

high gazelle
#

I jumped into someones chat. I had the same issue, not sure they solved theirs yet

cobalt mountainBOT
#

If you want to help them quickly, paste a short “here’s what fixed it for me” in their thread. Two common “same symptoms” cases:

If they see gateway closed (1008): pairing required when spawning

That’s device pairing (Gateway WS), not DM pairing codes:

openclaw devices list
openclaw devices approve <requestId>

openclaw pairing … is for DM pairing codes and won’t fix this.
Docs: https://docs.openclaw.ai/web/control-ui (Device pairing section)

If they’re on WSL and get systemctl --user unavailable / Failed to connect to bus

Enable systemd (WSL2):

#
sudo tee /etc/wsl.conf >/dev/null <<'EOF'
[boot]
systemd=true
EOF

Then in PowerShell:

wsl --shutdown

And make sure they’re not running as root, and ideally install:

sudo apt install -y dbus-user-session
#

If they get “System Node 12 is below required Node 22+”

Set an nvm default Node 22+ and reinstall the gateway service:

nvm install 22
nvm alias default 22
openclaw gateway install --force

If you link me the exact error line they posted, I can tell you which of these applies.

high gazelle
cobalt mountainBOT
#

Enabling systemd in WSL2 doesn’t inherently switch your default login to root — if you’re landing in a root shell after that, it’s almost always one of these:

1) Your distro’s default user isn’t set (so it falls back to root)

Permanent fix: set the default user in /etc/wsl.conf.

In WSL (even if you’re currently root), edit /etc/wsl.conf to include:

[boot]
systemd=true

[user]
default=nelson

Then from PowerShell:

#
wsl --shutdown

Re-open WSL and you should land as nelson.

2) Your Windows Terminal / VS Code profile is explicitly launching WSL as root

Check your profile commandline. If it looks like any of these, it will always open root:

  • wsl.exe -u root …
  • wsl.exe -d <DistroName> -u root …

Fix: remove -u root, or set it to your user.

3) You’re actually still in a root shell because of sudo -i / sudo su

sudo tee … only runs that one command as root. It won’t flip your user.
If your prompt is root because you ran sudo -i, just exit back to your normal user.

#

If you paste:

  • wsl -l -v (PowerShell), and
  • the first line of your Windows Terminal profile command (or tell me if you’re opening via VS Code)

…I can point to the exact cause in your setup.

high gazelle
# cobalt mountain Enabling systemd in WSL2 **doesn’t inherently switch your default login to root*...

root@Nelson:~# [boot]
systemd=true

[user]
default=nelson
[boot]: command not found
[user]: command not found
root@Nelson:~# su - nelson
/home/nelson
❯ [boot]
systemd=true

[user]
default=nelson
zsh: no matches found: [boot]
[WARN] - (starship::context): Scanning current directory timed out.
[WARN] - (starship::context): You can set scan_timeout in your config to a higher value to allow longer-running scans to keep executing.
/home/nelson
❯ [boot]
systemd=true

[user]
default=nelson
zsh: no matches found: [boot]
/home/nelson
❯

cobalt mountainBOT
#

You’re literally running the text as shell commands right now. Lines like [boot] are INI file sections for /etc/wsl.conf — they are not commands, so bash/zsh will error ([boot]: command not found / zsh: no matches found: [boot]).

Do this instead (this writes the file):

sudo tee /etc/wsl.conf >/dev/null <<'EOF'
[boot]
systemd=true

[user]
default=nelson
EOF

cat /etc/wsl.conf

Then restart WSL from PowerShell:

#
wsl --shutdown

Re-open WSL and verify:

whoami

If it still opens as root after that

Then your Windows Terminal / VS Code profile is probably launching WSL with -u root.

Check your launch command and remove the root flag (examples that force root):

  • wsl.exe -u root …
  • wsl.exe -d <DistroName> -u root …
#

If you paste your Windows Terminal “command line” for that profile (or tell me if you only open via VS Code), I’ll tell you exactly where to change it.

vestal raft
#

Config path not found: gateway.trustedProxies

cobalt mountainBOT
#

That one is expected: openclaw config get <path> errors if the key isn’t set in your config. It doesn’t mean the key is invalid/missing from OpenClaw.

To see what is set, do:

openclaw config get gateway

If you are running the Gateway behind a reverse proxy (nginx/Caddy/Tailscale Serve proxy/etc.) and you want forwarded client IPs to be trusted for “local client” checks, you can set it explicitly, e.g. same-host proxy:

openclaw config set gateway.trustedProxies '["127.0.0.1"]' --json
openclaw gateway restart

Only set this if you’re actually proxying the Gateway; otherwise you can ignore it. Docs: https://docs.openclaw.ai/gateway/security (reverse proxy + gateway.trustedProxies)

vestal raft
#

how to fix that error when bot trying to spawn agents

│ Gateway │ local · ws://127.0.0.1:18789 (local loopback) · unreachable (connect failed: pairing required) │
│ Gateway service │ LaunchAgent installed · loaded · running (pid 52429) │

cobalt mountainBOT
#

That line:

unreachable (connect failed: pairing required) (even though it’s ws://127.0.0.1:18789)

means the Gateway is rejecting the operator WebSocket client (your CLI / some worker) because its device identity isn’t approved yet. This is device pairing, not DM pairing.

Fix: approve the pending device

Run on the same machine/user that runs the LaunchAgent:

openclaw devices list --json
openclaw devices approve <requestId>

After approval, retry your spawn / openclaw gateway status.

Docs: https://docs.openclaw.ai/web/control-ui#device-pairing-first-connection and https://docs.openclaw.ai/cli/devices

vestal raft
#

gateway connect failed: Error: pairing required
[openclaw] Failed to start CLI: Error: gateway closed (1008): pairing required
Gateway target: ws://127.0.0.1:18789
Source: local loopback

Bind: loopback
at Object.onClose (file:///opt/homebrew/lib/node_modules/openclaw/dist/call-DZzTR0NL.js:438:10)
at WebSocket.<anonymous> (file:///opt/homebrew/lib/node_modules/openclaw/dist/client-DoSZFvf3.js:1538:23)
at WebSocket.emit (node:events:519:28)
at WebSocket.emitClose (/opt/homebrew/lib/node_modules/openclaw/node_modules/ws/lib/websocket.js:273:10)
at Socket.socketOnClose (/opt/homebrew/lib/node_modules/openclaw/node_modules/ws/lib/websocket.js:1346:15)
at Socket.emit (node:events:519:28)
at TCP.<anonymous> (node:net:346:12)

cobalt mountainBOT
#

If openclaw devices list also fails with the same “pairing required”

Then the Gateway does not consider this connection “local” (most common causes):

  1. You’re running the CLI from WSL/Docker/VM (so 127.0.0.1 is not actually the gateway host).
    → Run the CLI directly on the gateway host, or point --url at the real host IP/tailnet address.

  2. You’re going through a reverse proxy that adds X-Forwarded-For / X-Real-IP, and the Gateway won’t treat it as local unless proxy trust is configured.
    → Connect directly to the Gateway (bypass proxy), or configure gateway.trustedProxies (only if you actually proxy).

If you paste:

  • what OS you’re on (macOS/WSL/Docker/etc), and
  • whether openclaw devices list --json works or errors

…I’ll tell you which branch you’re in and the exact next step.

vestal raft
#

macOS
This is the output of openclaw devices list --json

gateway connect failed: Error: pairing required
[openclaw] Failed to start CLI: Error: gateway closed (1008): pairing required
Gateway target: ws://127.0.0.1:18789
Source: local loopback

Bind: loopback
at Object.onClose (file:///opt/homebrew/lib/node_modules/openclaw/dist/call-DZzTR0NL.js:438:10)
at WebSocket.<anonymous> (file:///opt/homebrew/lib/node_modules/openclaw/dist/client-DoSZFvf3.js:1538:23)
at WebSocket.emit (node:events:519:28)
at WebSocket.emitClose (/opt/homebrew/lib/node_modules/openclaw/node_modules/ws/lib/websocket.js:273:10)
at Socket.socketOnClose (/opt/homebrew/lib/node_modules/openclaw/node_modules/ws/lib/websocket.js:1346:15)
at Socket.emit (node:events:519:28)
at TCP.<anonymous> (node:net:346:12)

cobalt mountainBOT
#

That error is device pairing for operator clients (CLI / Control UI). It’s not a “subagents permission” issue.

On true localhost (ws://127.0.0.1:18789) this usually only happens if either:

  1. you’re not actually connecting directly (reverse proxy / port-forward in the middle), or
  2. that particular device identity got into a “needs approval” state and now the Gateway won’t auto-approve it.

Fastest fix: approve the device from the Control UI

  1. Open the dashboard in a browser on the same Mac:
  • http://127.0.0.1:18789/
  • (or run openclaw dashboard --no-open to print the URL)
  1. Connect with your Gateway token (don’t paste it here).

  2. In the Control UI, go to the Devices / Pairing area and approve the pending operator device request.

After that, openclaw gateway status and spawning should work.

#

If the Control UI itself can’t connect (also says pairing required)

Temporarily allow token-only auth for the UI (break-glass), restart, approve, then turn it back off:

openclaw config set gateway.controlUi.allowInsecureAuth true --json
openclaw gateway restart
# approve device in the UI
openclaw config unset gateway.controlUi.allowInsecureAuth
openclaw gateway restart

If you’re using a reverse proxy in front of the Gateway

Then you must set trusted proxies, otherwise the gateway will refuse to treat it as “local”:

openclaw config set gateway.trustedProxies '["127.0.0.1"]' --json
#
openclaw gateway restart

If you tell me whether you have nginx/Caddy/Tailscale Serve/etc. in front of port 18789, I can tell you which branch you’re in.

vestal raft
#

its on local

cobalt mountainBOT
#

You’re hitting device pairing, and the important clue is:

Source: local loopback but still pairing required

In the Gateway code, local clients are supposed to be silent/auto‑approved. If you’re seeing “pairing required”, the Gateway has decided your connection is not local.

On macOS that almost always happens when the Gateway thinks there are reverse‑proxy headers involved (e.g. X-Forwarded-For / X-Real-IP) coming from an address that is not in gateway.trustedProxies. In that case it intentionally disables “local trust” (so you don’t accidentally bypass auth via a proxy).

Fix (most common): trust localhost as a proxy

Even if config get says “path not found”, you can still set it:

openclaw config set gateway.trustedProxies '["127.0.0.1"]' --json
openclaw gateway restart

Then retry:

#
openclaw devices list --json

If the local classification was the issue, this should stop the 1008 pairing close.

Docs context: https://docs.openclaw.ai/gateway/security#reverse-proxy-configuration

Quick sanity check: are you really connecting to the Gateway on 18789?

Run:

sudo lsof -nP -iTCP:18789 -sTCP:LISTEN
  • If it’s not the OpenClaw gateway process (node/openclaw), you’re connecting to some proxy/other service on that port.
#

If it still fails after setting trustedProxies

Paste:

  • output of the lsof command above, and
  • the last ~30 lines of ~/.openclaw/logs/gateway.err.log (redact secrets)

…and we can pinpoint what is making it “non-local”.

vestal raft
#

127.0.0.1:18789 (LISTEN)
[::1]:18789 (LISTEN)

cobalt mountainBOT
#

Even if the Gateway is “local”, it will still refuse to treat the connection as local (and therefore won’t auto-approve pairing) if it thinks you’re coming through a proxy.

In the gateway code there are two telltale cases that make 127.0.0.1 not count as local:

  • Proxy headers present (X-Forwarded-For / X-Real-IP) from an address that is not in gateway.trustedProxies
  • Loopback connection but Host header is not local (e.g. you connect through a local reverse proxy / custom hostname)

Step 1: check the real reason in the gateway log (macOS LaunchAgent)

Run:

tail -n 200 ~/.openclaw/logs/gateway.err.log

Look for either of these warnings:

  • Proxy headers detected from untrusted address... Configure gateway.trustedProxies...
  • Loopback connection with non-local Host header. Treating it as remote...
#

Step 2: if you see proxy header warning → set trustedProxies

Most common fix on macOS (local proxy runs on localhost):

openclaw config set gateway.trustedProxies '["127.0.0.1","::1"]' --json
openclaw gateway restart

Then retry openclaw devices list --json.

Step 3 (break-glass if you’re totally stuck): use Control UI to approve the pending device

If no operator client can connect to approve pairing, temporarily allow the Control UI to connect without device identity, approve the pending device, then revert:

openclaw config set gateway.controlUi.allowInsecureAuth true --json
openclaw gateway restart
#

Open http://127.0.0.1:18789/, connect with your token, go to Devices/Pairing, approve the pending request(s).

Then revert:

openclaw config unset gateway.controlUi.allowInsecureAuth
openclaw gateway restart

If you paste the 5–10 log lines around the warning from gateway.err.log, I can tell you exactly which branch you’re in.

#

Those LISTEN lines confirm the Gateway really is on loopback — so the only remaining explanation for “pairing required” is: the gateway has a non‑silent pending device pairing request for your CLI device (often created when it previously thought the client was remote/proxied). Once such a pending request exists, local auto-approve won’t override it.

Since you can’t connect with the CLI to approve it, do a quick “reset pairing state” on disk:

1) Find the state dir the LaunchAgent is using

Usually ~/.openclaw (or ~/.openclaw-<profile>):

ls -d ~/.openclaw* 2>/dev/null
ls ~/.openclaw*/devices/pending.json 2>/dev/null
ls ~/.openclaw*/logs/gateway.err.log 2>/dev/null

2) Stop gateway, back up the pending pairing file, restart

(doesn’t delete your whole config; just clears pending device requests)

#
openclaw gateway stop

mv ~/.openclaw/devices/pending.json ~/.openclaw/devices/pending.json.bak.$(date +%s) 2>/dev/null || true

openclaw gateway start # or: openclaw gateway restart

3) Retry

openclaw devices list --json

If it still says pairing required

Then your CLI device identity might be “stuck”; reset it:

#
mv ~/.openclaw/identity/device.json ~/.openclaw/identity/device.json.bak.$(date +%s) 2>/dev/null || true
mv ~/.openclaw/identity/device-auth.json ~/.openclaw/identity/device-auth.json.bak.$(date +%s) 2>/dev/null || true
openclaw gateway restart

If you paste the last ~20 lines of ~/.openclaw/logs/gateway.err.log after a failed connect, I can tell you exactly which of the two (stale pending vs identity mismatch) it is.

vestal raft
#

The sessions_spawn Problem:

When I run sessions_spawn, it creates a sub-agent as a node and tries to connect to the Gateway via WebSocket. The Gateway requires pairing (manual approval) for all node connections.

The Deadlock:

sessions_spawn → creates sub-agent with new deviceId → tries to connect to Gateway
Gateway → rejects with "pairing required" (code 1008)
To approve pairing → need to call nodes pending or devices approve
But these commands themselves require Gateway connection → which requires pairing
Why settings don't work:

auth.mode: none — only works for webchat, not for nodes
insecureLocal: true, allowUnpaired — ignored for node role
Gateway always requires pairing for connections with role: node / clientMode: backend
Why openclaw agent --local works:

Runs agent embedded, without connecting to Gateway
No pairing required, but not integrated with your chat
The Core Issue: sessions_spawn doesn't work without approved pairing, but pairing cannot be approved without access to Gateway API.

Any ideas how to bypass this? 🌍