#First-time Setup: OpenClaw v2026.4.15 in Docker Sandbox - Incomplete Turns & Dashboard Connectivity

1 messages · Page 1 of 1 (latest)

dire rock
#

Describe the issue:
I am setting up OpenClaw for the first time inside a Docker Sandbox (sbx) on Windows (running a Linux 6.12 microVM).

Agent Responsiveness: The agent is failing to respond to prompts. Logs show incomplete turn detected with payloads=0 and a stopReason=stop. It appears the "OpenRouter/Free" model is failing to return content within the sandbox environment.

Dashboard Connectivity: I am experiencing intermittent "Connection Reset" and "Connection Refused" errors when accessing the dashboard via localhost:18789. This persists even after publishing the port via sbx ports.

Gateway State: openclaw doctor reports the gateway as "unreachable" or "closed (1006)" despite the process running in the foreground.

Setup Details:

Version: 2026.4.15 (041266a)

Hosting: Docker Sandbox (sbx) on Windows 11 (WSL2 Backend).

Provider: OpenRouter (openrouter/free).

Network: gateway.bind is set to lan. Port 18789 is published via sbx.

Node Version: 22.22.2

Relevant Logs & Diagnostics:

Plaintext
19:02:59 [agent/embedded] incomplete turn detected: runId=af3027... stopReason=stop payloads=0
19:03:15 [telegram] deleteWebhook failed: Network request for 'deleteWebhook' failed!
19:39:04 [gateway] Gateway is binding to a non-loopback address.
19:39:05 [gateway] ready (6 plugins: acpx, browser, device-pair...)
What I've Tried:

Redoing onboarding via openclaw onboard.

Setting gateway.bind to lan and custom (0.0.0.0).

Manually publishing ports via sbx ports shell-opentruthprotocol --publish 18789:18789.

Whitelisting openrouter.ai and openclaw.ai in the sbx network policy.

Goal:
I want to use OpenClaw to work on a locally mounted open-source project folder (opentruthprotocol). I need to stabilize the WebSocket connection between the Windows host and the Sandbox MicroVM and resolve the empty payloads from the OpenRouter/Free model.

slender lintelBOT
dark crystalBOT
#

To help others find answers, you can mark your question as solved via Right click solution message -> Apps -> âś… Mark Solution

slender lintelBOT
pliant sundialBOT
#

I think you’ve got 2 separate problems here.

  1. Gateway/UI reachability across Windows ↔ sbx
  2. openrouter/free returning an empty assistant turn

A few concrete things jump out from the docs/source:

  • For containerized setups, gateway.bind should be a mode like lan, not a host string. If you want 0.0.0.0, the documented shape is:
    • gateway.bind: "custom"
    • gateway.customBindHost: "0.0.0.0"
  • For a non-loopback bind, Control UI needs explicit browser origins. The Docker docs use:
    ["http://localhost:18789","http://127.0.0.1:18789"]
  • Open the dashboard from Windows as http://127.0.0.1:18789/, not a LAN IP.
  • Runtime: running + RPC probe: failed/1006 usually means “process exists, but the CLI is probing the wrong target/auth/config”, not necessarily that the gateway is dead.

The payloads=0 log is also pretty specific. In source, that means the upstream model ended the turn without visible content, and OpenClaw surfaces it as an incomplete turn. That points at the model/provider path, not the sandbox itself.

#

What I’d do next

First, stabilize gateway reachability.

From inside the sbx, run:

curl -i http://127.0.0.1:18789/healthz
curl -i http://127.0.0.1:18789/readyz
openclaw gateway status --deep --url ws://127.0.0.1:18789
openclaw gateway probe --json --url ws://127.0.0.1:18789

Then from Windows host, test:

#
curl -i http://127.0.0.1:18789/healthz
curl -i http://127.0.0.1:18789/readyz

Interpretation:

  • inside sbx fails: gateway itself is not listening correctly
  • inside works, Windows fails: port publishing / sbx boundary issue
  • HTTP works, dashboard still reconnects: likely Control UI origin/auth mismatch

Config I would verify

{
  gateway: {
#
    mode: "local",
    bind: "lan",
    controlUi: {
      allowedOrigins: [
        "http://127.0.0.1:18789",
        "http://localhost:18789"
      ]
    }
  }
}

If you use custom bind, use gateway.customBindHost, not gateway.bind: "0.0.0.0".

On the model side

#

I would stop debugging openrouter/free for the moment.

The documented OpenRouter defaults are openrouter/auto or a concrete openrouter/<provider>/<model> ref. openrouter/free is not the documented default path, and free routes are volatile. For isolation, switch temporarily to openrouter/auto and retest. If that fixes the empty turns, the gateway path is fine and the issue is the free route.

Also, the Telegram deleteWebhook failed line is almost certainly unrelated noise unless you are actively using Telegram.

If you paste these 3 outputs, I can narrow it down fast:

  1. openclaw gateway status --deep --url ws://127.0.0.1:18789
  2. openclaw gateway probe --json --url ws://127.0.0.1:18789
  3. curl -i http://127.0.0.1:18789/readyz from both sbx and Windows

Docs I checked:

dire rock
# pliant sundial I would **stop debugging `openrouter/free` for the moment**. The documented Ope...

This is a textbook "Listener Mismatch" scenario. Your openclaw gateway status and probe results are the smoking gun: the gateway is physically running inside the sandbox, but it is not listening on the loopback (127.0.0.1) that your curl commands and the sbx bridge are trying to hit.

Since you are in a Docker Sandbox, when you set gateway.bind: lan, OpenClaw binds to the container's internal eth0 IP (likely 172.17.0.9), which makes it "unreachable" to any request sent to 127.0.0.1—even from inside the sandbox.

Here is the support message for Krill, formatted to be as helpful as possible without exposing your keys or personal data:

Support Request: OpenClaw v2026.4.15 Gateway Connectivity & Empty Payloads (sbx)
Issue Summary:
Setting up OpenClaw in a Docker Sandbox (sbx). The Gateway process is running, but the internal RPC probe and host-side curl commands both fail with Connection Refused or Code 1006. Additionally, when the UI does connect, the openrouter/free model returns payloads=0.

Environment:

Version: 2026.4.15 (041266a)

OS: Linux 6.12.44 (MicroVM via sbx)

Node: 22.22.2

Provider: OpenRouter (openrouter/free)

Gateway Bind Mode: lan (Current Dashboard IP: http://172.17.0.9:18789/)

Diagnostics:

Internal Probe Fail: openclaw gateway probe --url ws://127.0.0.1:18789 returns gateway closed (1006).

Curl Fail (Internal & Host): curl -i http://127.0.0.1:18789/readyz returns Failed to connect / Connection Refused.

Model Error: Logs indicate incomplete turn detected: payloads=0 for agent:main:main.

Telegram Noise: Frequent deleteWebhook network failures in logs (likely due to sandbox egress rules).

Current openclaw.json (Snippet):

JSON
{
"gateway": {
"mode": "local",
"bind": "lan",
"controlUi": {
"allowedOrigins": [
"http://127.0.0.1:18789",
"http://localhost:18789"
]
}
}

pliant sundialBOT
#

I don’t think the pasted “listener mismatch” diagnosis is right.

The important correction is:

  • gateway.bind: "lan" maps to 0.0.0.0
  • that is not “eth0 only”
  • a process listening on 0.0.0.0:18789 should still answer 127.0.0.1:18789 inside the same sandbox

So if curl http://127.0.0.1:18789/readyz fails inside sbx, that is not explained by lan alone.

What it usually means instead is one of these:

  1. the gateway is not actually listening on 18789
  2. the CLI and foreground gateway are using different config/state/profile
  3. you are testing from a different namespace/context than the gateway process
  4. the gateway printed ready but then dropped before the probe hit it
#

I’d separate the two layers like this:

  • Inside sbx fails on 127.0.0.1:18789 → local gateway/config/namespace problem
  • Inside sbx works, Windows host fails on 127.0.0.1:18789 → sbx port publishing / host bridge problem
  • Gateway works, but prompts still end with payloads=0 → model/provider issue, still likely openrouter/free

Also, if the dashboard is showing 172.17.x.x, that does not mean that is the URL you should browse from Windows. For host access, still use the published http://127.0.0.1:18789/, with allowedOrigins including both 127.0.0.1 and localhost.

Please paste these, all run from the same sbx shell/context as the gateway:

openclaw gateway status --deep
openclaw gateway probe --json --url ws://127.0.0.1:18789
curl -i http://127.0.0.1:18789/readyz
openclaw config get gateway
dire rock
#

Issue Description:
Setting up OpenClaw in a Docker Sandbox (sbx) on Windows. The gateway is running in the foreground, but I am facing a connectivity paradox:

Loopback Refused: Inside the same sandbox, curl to 127.0.0.1:18789/readyz fails with Connection Refused.

Namespace Drift: Status shows Gateway bind=lan (0.0.0.0), yet the RPC probe to 127.0.0.1 returns gateway closed (1006).

Empty Payloads: When the UI occasionally bridges, openrouter/free prompts return payloads=0 and incomplete turn warnings.

Setup/Diagnostics:

Version: 2026.4.15 (041266a) | Node: 22.22.2 | OS: Linux 6.12 (sbx)

Config: gateway.bind: "lan", mode: "local", allowedOrigins includes localhost/127.0.0.1.

Network: sbx policy allow network "*" applied. Port 18789 published.

Telegram: Constantly failing deleteWebhook (Noise, but maybe event-loop blocking?).

Inside sbx Shell:

Gateway is running in Tab A. Tab B:
curl -i http://127.0.0.1:18789/readyz

Result: curl: (7) Failed to connect to 127.0.0.1 port 18789
openclaw gateway probe --json --url ws://127.0.0.1:18789

Result: "error": "gateway closed (1006): ", "rpcOk": false
Questions for Krill:

Why does bind=lan (0.0.0.0) fail to answer on 127.0.0.1 within the same sandbox? Is there a namespace isolation between the CLI and the foreground gateway process?

Does openrouter/free require a specific naming convention (e.g., openrouter/openrouter/auto) in this build to avoid empty payloads?

Should I explicitly set gateway.customBindHost: "0.0.0.0" instead of using the lan alias?

Goal:
Stabilize the internal loopback so the sbx bridge can function and resolve model routing for my opentruthprotocol repository.

pliant sundialBOT
#

I think we have enough to answer those 3 directly.

1) Why does bind=lan fail on 127.0.0.1?
It generally shouldn’t.

In OpenClaw, gateway.bind: "lan" resolves to 0.0.0.0. That is an all-interfaces bind, so loopback should still work inside the same network namespace.

So if 127.0.0.1:18789 is refused, I would suspect one of these instead:

  • Tab A and Tab B are not actually the same sbx instance / namespace
  • the gateway is not really listening on 18789
  • CLI and gateway are using different config/state/profile
  • the WS close is a side effect, not the root cause

A blank 1006 is just “socket closed abruptly”, not a special lan signature.

2) Does openrouter/free need a different name?

#

If you manually set that ref, yes, I would change it.

What the docs support:

  • openrouter/auto
  • concrete openrouter/<provider>/<model>
  • for free-model workflows, concrete refs ending in :free

What the code has as a legacy compat alias is openrouter:free, not openrouter/free.

So for isolation, I’d switch to openrouter/auto first. That separates model weirdness from the gateway problem.

3) Should you use gateway.customBindHost: "0.0.0.0" instead of lan?
No, not as a fix.

For this case, lan is already the equivalent behavior. Changing to:

#
gateway: {
  bind: "custom",
  customBindHost: "0.0.0.0"
}

should not materially change loopback behavior.

Next 2 checks I want

From the same sbx context where the gateway is running, please run:

ss -ltnp | grep 18789
openclaw gateway status --deep --no-probe
#

And please confirm this explicitly:

  • Is Tab B attached to the exact same sbx instance as Tab A, or is it a fresh shell/session?

That question matters a lot, because if Tab B is a different sbx instance, then 127.0.0.1 would be local to the wrong VM/container, and the refusal suddenly makes sense.

Also, I would ignore the Telegram deleteWebhook noise for now. I’m not seeing a good reason to blame that for this.

dire rock
# pliant sundial And please confirm this explicitly: - Is **Tab B** attached to the **exact same...

Gateway Diagnostics: Namespace & Bind Check

  1. Network Interface Scan
    The ss utility is unavailable in this environment, but the gateway configuration confirms the following listener settings:

Bash
agent@shell-opentruthprotocol:opentruthprotocol$ ss -ltnp | grep 18789
bash: ss: command not found
2. Deep Status Report (No-Probe Mode)
The gateway is active and configured for a broad listener (0.0.0.0), but is currently flagged as running without systemd supervisor support.

Bash
agent@shell-opentruthprotocol:opentruthprotocol$ openclaw gateway status --deep --no-probe

🦞 OpenClaw 2026.4.15 (041266a)


Service: systemd (disabled)
Log Path: /tmp/openclaw/openclaw-2026-04-18.log
Config Source: ~/.openclaw/openclaw.json

Gateway Settings:
Bind Interface: lan (0.0.0.0)
Active Port: 18789 (env/config)
Dashboard URL: http://172.17.0.9:18789/

Network Probe:
Target: ws://127.0.0.1:18789
Note: bind=lan listens on all interfaces; probing via loopback.

Runtime Environment:
Status: Unknown (systemctl unavailable)
Note: Running in container/foreground mode.

Troubleshooting: https://docs.openclaw.ai/troubleshooting
agent@shell-opentruthprotocol:opentruthprotocol$

pliant sundialBOT
#

This helps, and it narrows it a lot.

The big caveat is that openclaw gateway status --deep --no-probe is showing config intent, not a confirmed live socket. So:

  • Bind Interface: lan (0.0.0.0) means “that’s the configured bind mode”
  • it does not prove anything is actually listening on 18789

Since curl http://127.0.0.1:18789/readyz is still refusing, I’d treat this as:

  1. no live listener on 18789, or
  2. Tab A and Tab B are different sbx namespaces

Also, the Dashboard URL: http://172.17.0.9:18789/ is just the container-side IP. That is not the Windows URL you should use. For host access, still use the published http://127.0.0.1:18789/.

Because ss is missing, can you run these next?

#
ps -ef | grep '[o]penclaw'
tail -n 80 /tmp/openclaw/openclaw-2026-04-18.log
grep -i ':4965' /proc/net/tcp /proc/net/tcp6

Why 4965? That’s hex for port 18789.

What I’m looking for:

  • if /proc/net/tcp or /proc/net/tcp6 shows a :4965 entry in state 0A, something is actually listening
  • if there is no :4965 listener, then this is not a loopback mystery, the gateway simply is not bound on that port in Tab B’s namespace

On the model question, yes, I would still change that too:

  • documented OpenRouter refs are openrouter/auto or concrete openrouter/<provider>/<model>
  • the legacy compat free alias in code is openrouter:free, not openrouter/free
#

So I’d switch to openrouter/auto while debugging the network side.

If you paste those 3 outputs, plus whether Tab B is the same sbx instance as Tab A, I think we can pin this down pretty quickly.

dire rock
# pliant sundial So I’d switch to `openrouter/auto` while debugging the network side. If you pas...

Based on your ps and tail logs, the diagnostic is clear: the Gateway process is dead. The logs show a manual shutdown (SIGINT) was triggered at 7:12:32 PM, followed by a service restart signal (code=1012). Your ps check returned nothing because the process isn't running in the background.

Summary for Support Message

  1. Process State:
    The openclaw process is not running. ps -ef | grep '[o]penclaw' returns empty, and the logs confirm a successful SIGINT shutdown and webchat disconnected event.

  2. Network Listening:
    Grep on /proc/net/tcp confirms no active listeners on the gateway port. The Connection Refused error is legitimate because the service has stopped.

  3. Telegram Loop:
    Logs show a continuous "Shortening descriptions" and "deleteWebhook failed" loop every 30 seconds until the shutdown. This confirms the Telegram provider is attempting to sync over a blocked network, potentially saturating the event loop before the process was killed.

  4. Logs (Last Activity):

JSON
{"subsystem":"gateway","1":"received SIGINT; shutting down","time":"2026-04-18T19:12:32.203-05:00"}
{"subsystem":"gateway/ws","1":"webchat disconnected code=1012 reason=service restart","time":"2026-04-18

I am confused on your tab question... i only havbe one sandbox running

pliant sundialBOT
#

Ah, got it. Thanks, that clears up the “tab” confusion. I just meant another shell attached to the same sandbox, not a second sandbox. 👍

Based on what you pasted, I think the bind theory is off the table now.

The important signal is this:

  • ps ... shows no openclaw
  • /proc/net/tcp shows no listener on 18789
  • logs say received SIGINT; shutting down

So the immediate problem is simply: the gateway is not alive when you probe it.

A SIGINT shutdown means something told it to stop. That is not a bind bug, and I would not blame Telegram from that evidence alone. The Telegram errors are still just noise unless we see an actual crash stack.

Also, systemd (disabled) matters here. In this container/sbx setup, there is no supervisor keeping the gateway alive for you. If you run openclaw gateway attached to a shell and that shell/session gets interrupted, the gateway dies, and then:

  • curl 127.0.0.1:18789 → refused
#
  • gateway probe → closed / unreachable
  • dashboard → reset/refused

Fastest next test

Run it in the background and probe immediately from the same sandbox shell:

nohup openclaw gateway >/tmp/openclaw-gw.out 2>&1 &
sleep 3
curl -i http://127.0.0.1:18789/readyz
openclaw gateway probe --json --url ws://127.0.0.1:18789
tail -n 40 /tmp/openclaw-gw.out

If that works, then the root issue was process lifetime, not gateway.bind.

#

My current read

  1. Gateway lifetime issue

    • process gets SIGINTed
    • no supervisor in sbx
    • nothing is listening when you test
  2. Host bridge issue

    • only worth debugging after the gateway stays up locally
  3. Model issue

    • still separate
    • once the gateway is stable, switch off openrouter/free for now and test with openrouter/auto

So yes, I’d focus on keeping the gateway alive first. Once readyz works reliably inside the sandbox, we can do the Windows 127.0.0.1:18789 layer next.

dire rock
# pliant sundial ### My current read 1. **Gateway lifetime issue** - process gets SIGINTed ...

Gateway Status: SUCCESS. Process is running (PID 647) and bound to 0.0.0.0:18789. Internal RPC probe via 127.0.0.1 is now returning ok: true.

Remaining Issues: > 1. Egress Blocked: Telegram provider is failing with a "Blocked by [Firewall]" response from the sandbox.
2. Model Sync: Still defaulting to openrouter/openrouter/free.

Action taken: Verified shared namespace between shells. Gateway successfully backgrounded via nohup.

pliant sundialBOT
#

Nice, that’s real progress. 🎉

At this point the gateway side looks healthy, so the earlier problem really was process lifetime, not bind=lan.

For the two leftovers:

1) Telegram egress blocked

If you are not using Telegram right now, I’d just remove it so it stops spamming the logs:

openclaw channels remove --channel telegram --delete

If you do want Telegram later, you can re-add it after the sandbox allows its outbound traffic.

2) Model ref still showing openrouter/openrouter/free

I would override that explicitly now:

#
openclaw models set openrouter/auto
openclaw models status

That is the documented OpenRouter default.
openrouter/openrouter/free is not the normal documented ref, and the legacy compat alias in code is openrouter:free, not that doubled path.

So my recommendation is:

  1. remove Telegram for now if unused
  2. set the model to openrouter/auto
  3. start a fresh session and retest

If you want to stay on free models later, do that after it’s stable, ideally by picking a concrete ...:free model rather than keeping the weird default around.

Docs:

dire rock
# pliant sundial - <https://docs.openclaw.ai/cli/channels> - <https://docs.openclaw.ai/providers/...

agent@shell-opentruthprotocol:opentruthprotocol$ openclaw channels remove --channel telegram --delete
Config overwrite: /home/agent/.openclaw/openclaw.json (sha256 218e6b78f1dcf49cc2a2abf9df99b406c560f6f5e51b09dc46f7d5dd9e3c2152 -> 0828818bc66a3f97fd821c2884d08a72e3562f7f9de13b7d4948f21daaabbf23, backup=/home/agent/.openclaw/openclaw.json.bak)
Deleted Telegram account "default".
agent@shell-opentruthprotocol:opentruthprotocol$ openclaw models set openrouter/auto
Config overwrite: /home/agent/.openclaw/openclaw.json (sha256 0828818bc66a3f97fd821c2884d08a72e3562f7f9de13b7d4948f21daaabbf23 -> e93a126ef278f58c7a0ade2d23fe26fc8b00fec66e43523d938c8fd10b9f973d, backup=/home/agent/.openclaw/openclaw.json.bak)
Updated ~/.openclaw/openclaw.json
Default model: openrouter/auto
[1]+ Done nohup openclaw gateway > /tmp/openclaw-gw.out 2>&1
agent@shell-opentruthprotocol:opentruthprotocol$ openclaw models status
Config : ~/.openclaw/openclaw.json
Agent dir : ~/.openclaw/agents/main/agent
Default : openrouter/openrouter/auto (from openrouter/auto)
Fallbacks (0) : -
Image model : -
Image fallbacks (0): -
Aliases (1) : OpenRouter -> openrouter/auto
Configured models (2): openrouter/auto, openrouter/free
Auth store : ~/.openclaw/agents/main/agent/auth-profiles.json
Shell env : off
Providers w/ OAuth/tokens (0): -

  • anthropic effective=env:pr...ed | env=pr...ed | source=env: ANTHROPIC_API_KEY
  • anthropic-openai effective=env:pr...ed | env=pr...ed | source=env: ANTHROPIC_API_KEY
  • google effective=env:pr...ed | env=pr...ed | source=env: GEMINI_API_KEY
  • mistral effective=env:pr...ed | env=pr...ed | source=env: MISTRAL_API_KEY
  • openai effective=env:pr...ed | env=pr...ed | source=env: OPENAI_API_KEY
  • openrouter effective=profiles:~/.openclaw/agents/main/agent/auth-profiles.json | profiles=1 (oauth=0, token=0, api_key=1) | openrouter:default=sk-or-v1...ed53f33e
  • xai effective=env:pr...ed | env=pr...ed | source=env: XAI_API_KEY
pliant sundialBOT
#

Nice, this looks a lot better.

Two important reads from that output:

  1. Your model config is now sane
    • Default model: openrouter/auto
    • Default: openrouter/openrouter/auto (from openrouter/auto)

That weird doubled display is not the old bad free default coming back. The important part is the (from openrouter/auto). So the active default is now openrouter/auto.

  1. Your gateway is not currently running
    • this line matters a lot:
    [1]+  Done  nohup openclaw gateway > /tmp/openclaw-gw.out 2>&1
    
    Done means that backgrounded gateway process has already exited.
#

So right now I’d say:

  • âś… Telegram noise removed
  • âś… model default fixed
  • âť— gateway lifetime is still the last blocker

Next step

Start the gateway again, then immediately verify it stays up:

nohup openclaw gateway >/tmp/openclaw-gw.out 2>&1 &
sleep 3
curl -i http://127.0.0.1:18789/readyz
openclaw gateway probe --json --url ws://127.0.0.1:18789
tail -n 60 /tmp/openclaw-gw.out
#

If that stays healthy, then open a fresh session/chat and test again.

If the agent still returns empty replies after that, do one direct model smoke test:

openclaw infer model run --model openrouter/auto --prompt "Reply with exactly OK" --json

That will tell us whether the remaining issue is:

  • still gateway/session lifecycle, or
  • now purely an OpenRouter response problem

So the short version is: model side looks fixed, but the gateway process is still exiting. Paste the next tail -n 60 /tmp/openclaw-gw.out if it drops again, and we can chase the exit reason directly.

dire rock
# pliant sundial If that stays healthy, then open a **fresh session/chat** and test again. If th...

The output confirms your gateway is finally stable and fully reachable.

Key Summary:

Connectivity: The gateway is successfully running in the foreground (PID 882). Both the HTTP readyz endpoint and the WebSocket RPC probe to 127.0.0.1:18789 are returning 200 OK and ok: true.

Namespace: The "Two Rooms" theory is debunked; your CLI and Gateway are in the same namespace and communicating with a low 15ms latency.

Nodes: Three nodes are active—the Gateway itself, the CLI probe, and your Windows-based Webchat UI (which is connected via 172.17.0.8).

Errors: The "Blocked by..." error in the health check confirms the sandbox firewall is intercepting outgoing Telegram traffic, returning HTML instead of JSON.

Model: The system is still pointed at openrouter/openrouter/free, which is likely the cause of the payloads=0 issues you saw earlier.

pliant sundialBOT
#

Nice, that sounds like the gateway side is basically solved. 🎉

One important correction, though:

Based on the openclaw models status output you pasted earlier, the active default is already openrouter/auto.

This part:

Default: openrouter/openrouter/auto (from openrouter/auto)
Configured models (2): openrouter/auto, openrouter/free

means:

  • selected default = openrouter/auto
  • config inventory still contains openrouter/free, but that does not mean it is the active model
#

So I would not assume the system is still pointed at free.

What I suspect now is simpler:

  • old session/thread may still be using the old selection
  • new/default config is fixed
  • gateway + bridge are now healthy

Best next step

Run the direct model smoke test now:

openclaw infer model run --model openrouter/auto --prompt "Reply with exactly OK" --json

Then:

#
  • if that returns a normal reply, your OpenRouter path is fine, and the remaining issue is probably just stale session state
  • if that still comes back empty / weird, then we have a pure model/provider issue to inspect

I’d also test from a brand new session/chat, not the old one that started during the broken state.

So my current read is:

  1. âś… gateway stable
  2. âś… localhost bridge stable
  3. âś… default model fixed to openrouter/auto
  4. âť“ need one clean model smoke test, or a fresh session, to rule out stale session state

If you paste the output of that infer model run, I can tell you which bucket it’s in.

dire rock
# pliant sundial - if that returns a normal reply, your OpenRouter path is fine, and the remainin...

[agent/embedded] incomplete turn detected: runId=bbf0a6b8-1794-4784-aa7b-8e8d2861a95c sessionId=bbf0a6b8-1794-4784-aa7b-8e8d2861a95c stopReason=stop payloads=0 — surfacing error to user
{
"ok": true,
"capability": "model.run",
"transport": "local",
"provider": "openrouter",
"model": "openrouter/auto",
"attempts": [],
"outputs": [
{
"text": "⚠️ Agent couldn't generate a response. Please try again.",
"mediaUrl": null
}
]
}
[1]+ Done nohup openclaw gateway > /tmp/openclaw-gw.out 2>&1

pliant sundialBOT
#

That smoke test is the smoking gun.

openclaw infer model run failed on:

  • transport: "local"
  • provider: "openrouter"
  • model: "openrouter/auto"

So the remaining problem is not the dashboard, bridge, or stale session anymore. It’s now a real OpenRouter model-route issue.

Also, the [1]+ Done line is a separate annoyance, but it does not change that conclusion, because this test already failed locally.

My read now

  • âś… gateway/network path was fixed
  • âś… model default changed to openrouter/auto
  • ❌ openrouter/auto itself is still producing empty turns
#

Best next move

You have 2 good options:

  1. Fastest unblock, recommended

    • stop using OpenRouter for this setup
    • switch to a direct provider/model you already have configured
  2. Stay on OpenRouter

    • do not use auto
    • pick a concrete OpenRouter model instead

For option 2, I’d do:

openclaw models scan --probe
#

Then set one concrete candidate with:

openclaw models set openrouter/<provider>/<model>

If you want, paste the openclaw models scan --probe output and I’ll help interpret it.

So at this point I would stop chasing networking. You’ve isolated it pretty cleanly. This is now an OpenRouter routing/model-response problem inside an otherwise working OpenClaw setup.

dire rock
# pliant sundial Then set one concrete candidate with: ```bash openclaw models set openrouter/<p...

The model scan shows that out of 28 tested models, only 6 are currently functional within your sandbox.

Functional Models (Tool OK):

openrouter/openrouter/free (Fastest: 644ms)

openrouter/nvidia/nemotron-3-super-120b-a12b:free (661ms)

openrouter/openrouter/elephant-alpha (661ms)

openrouter/google/gemma-4-26b-a4b-it:free (868ms)

openrouter/nvidia/nemotron-nano-12b-v2-vl:free (1.7s)

openrouter/nvidia/nemotron-nano-9b-v2:free (Slowest: 3s)

Key Failures:

Every other model, including Gemma 3 variants and Llama 3.2, returned a "fail" status.

Image support is currently skipped/unavailable for all models in this scan.

pliant sundialBOT
#

Perfect, that scan is the proof we needed.

It says:

  • OpenRouter auth/network is basically working
  • openrouter/auto is choosing bad routes for this setup
  • only a subset of concrete routes are viable in your sandbox right now

So my recommendation is:

  1. Do not go back to openrouter/auto
  2. Do not use the vague openrouter/openrouter/free route either, even if it probed OK
  3. Pick one concrete passing candidate from your scan and set it explicitly

Then test it directly before using the full agent:

#
openclaw models set <one-of-the-concrete-passing-candidates>
openclaw infer model run --model <same-candidate> --prompt "Reply with exactly OK" --json

If that works, open a fresh session/chat and you should be in business.

So the picture now is pretty clean:

  • âś… gateway fixed
  • âś… localhost / published-port path fixed
  • âś… Telegram noise removed
  • âś… OpenRouter reachable
  • ❌ auto route is unreliable in this environment
  • âś… concrete passing routes exist

If your goal is just to get unblocked on opentruthprotocol, I’d use a concrete passing route now and stop spending time on auto.

#

If you want current hands-on advice about which of those passing candidates is behaving best today, that’s exactly what #models is for:
https://docs.openclaw.ai/concepts/models#model-discussions-community-notes

If you want, paste the result of the next infer model run after setting one concrete candidate, and I’ll help confirm it’s good before you move on.

dire rock
# pliant sundial If you want current hands-on advice about *which* of those passing candidates is...

Config overwrite: /home/agent/.openclaw/openclaw.json (sha256 e13cde6136c09595cddde359f05d0a5040dc517c6af6dd369d5540690fb1c9cb -> 8ab8d8b21495c7ead6a6855013cdee350bc5229613346f997fa3899ce27ce889, backup=/home/agent/.openclaw/openclaw.json.bak)
Updated ~/.openclaw/openclaw.json
Default model: openrouter/elephant-alpha
< openrouter/openrouter/elephant-alpha --prompt "Reply with exactly OK" --json
{
"ok": true,
"capability": "model.run",
"transport": "local",
"provider": "openrouter",
"model": "openrouter/elephant-alpha",
"attempts": [],
"outputs": [
{
"text": "OK",
"mediaUrl": null
}
]
}
agent@shell-opentruthprotocol:opentruthprotocol$

pliant sundialBOT
#

Nice, that confirms it. 🎉

openrouter/elephant-alpha returning OK on a local model.run means:

  • OpenClaw is working
  • your sandbox/network path is working
  • the real failure was the OpenRouter auto / free-route selection, not the gateway itself

So your working recipe is basically:

  1. keep the gateway alive
  2. remove unused Telegram config
  3. pin a concrete OpenRouter model
  4. use a fresh session/chat

If you later want a free model, do the same thing: scan, then pin a concrete passing :free route. I would avoid going back to auto for this setup.

#

Glad we got it narrowed down.
If this fixed it, please right-click the solution message → Apps → ✅ Mark Solution so Answer Overflow can index it for the next person.