Diagnostics and fixes for OpenClaw agents that die halfway through a task when running against a local model, plus the serving recipe that goes with it on a DGX Spark (GB10).
Nothing here is specific to one machine — every script detects ports, hosts and paths at runtime.
You ask the agent to do something real. It thinks, calls a couple of tools, and then just… stops. No answer, no error worth reading. It feels like the model ran out of context, or crashed, or the box is too small.
Usually it is none of those. The harness aborted the task on a timeout.
The default agent timeout is fine for a fast hosted model and far too short for a local one generating ~20 tokens/second. A multi-step agent turn overruns it, OpenClaw gives up, and you are left blaming the GPU.
./scripts/diagnose.shRead-only. It puts the two candidate culprits side by side:
restarts=0 oom_killed=false all requests 200 KV usage 3%
-> the model server is healthy; the harness killed your task
restarts>0 / oom_killed=true / 400s / KV usage ~100%
-> the model server really is the problem
A server that has been up for hours with zero non-200 responses did not kill your task. Fix the harness, not the GPU.
# --context must match your server's real max_model_len
./scripts/openclaw-tune.sh --context 262144
./scripts/openclaw-tune.sh --context 1000000 --dry-run # preview firstGet the right number from the server itself:
curl -s http://127.0.0.1:PORT/v1/models | grep -o '"max_model_len":[0-9]*'This does three things: sets a realistic agent timeout, writes that context window onto the provider's model entry so the harness and server agree, and applies a compaction profile scaled to it. Two of the compaction settings are off by default and matter most:
midTurnPrecheck— checks context pressure between tool calls, which is where long tasks actually diememoryFlush— persists salient context before heavy trimming
There is no on/off switch for summarisation; it always runs. What you are tuning is how much history survives and when it fires. See reference/compaction-options.md.
| Script | What it does |
|---|---|
scripts/diagnose.sh |
Read-only. Decides whether the server or the harness is at fault. Start here. |
scripts/openclaw-tune.sh |
Applies the timeout + compaction profile via openclaw config patch. |
scripts/openclaw-url.sh |
Prints a working dashboard URL. Discovers gateway port, token, LAN address and TLS front at runtime. |
scripts/openclaw-token.sh |
Prints the gateway token (the CLI redacts it — see below). |
scripts/serve-qwen38-4bit.sh |
Serves 4-bit Qwen3.8-27B on a DGX Spark, optionally at 1M context via YaRN. |
All are plain bash, no dependencies beyond curl, python3 (or jq), and
docker for the serving script.
The gateway token is redacted. openclaw config get gateway.auth.token
returns a placeholder, not the token, and there is no --reveal flag. Build a
URL from it and you get an authentication failure that looks like a hang.
Read the config file instead — scripts/openclaw-token.sh does.
The origin allow-list fails silently. If your browsing origin is not in
gateway.controlUi.allowedOrigins, the UI loads, accepts your message, and
never replies. It looks exactly like a stuck model. Fix:
./scripts/openclaw-url.sh --fix-origin, then restart the gateway.
4-bit on GB10 can be silently wrong. VLLM_MARLIN_USE_ATOMIC_ADD=1 is
mandatory on SM121; without it a Marlin race produces incorrect output with no
error at all. Full list in reference/gotchas.md.
Only worth doing if diagnose.sh shows genuine context overflow — a timeout
does not get better with a bigger window.
MAX_LEN=1000000 ./scripts/serve-qwen38-4bit.sh # YaRN
MAX_LEN=262144 ./scripts/serve-qwen38-4bit.sh # native, no YaRNQwen3.8-27B is 262144 natively and extends to 1M through static YaRN, which
applies at all input lengths and can degrade short-prompt quality. Use
YARN_FACTOR=2.0 (~524288) if you want a smaller dose.
Check the arithmetic the server prints on boot:
GPU KV cache size: 1,348,160 tokens
Maximum concurrency for 1,000,000 tokens per request: 1.35x
Below 1.0x means one full-length request does not fit and the server will not
start. Dense models cost roughly 65 KB/token of KV versus ~7 KB/token for MLA
architectures, so context that was cheap on one model may not be on another.
Keep the harness and server in agreement. If the harness contextWindow
exceeds the server max_model_len, long sessions start failing. openclaw-tune.sh
sets the harness side; restarting the server with a larger --max-model-len is
the only way to raise the server side. Raising one does not raise the other.
| Where | Why |
|---|---|
--context on openclaw-tune.sh |
Must equal your server's real max_model_len. It is written to the model entry, not just used for scaling. |
--provider on openclaw-tune.sh |
Defaults to the provider in agents.defaults.model.primary. Set it if you have several. |
--no-context-write |
Tune timeouts/compaction only, leave contextWindow alone. |
MODEL / IMAGE in serve-qwen38-4bit.sh |
Different checkpoint or vLLM build. |
GMU (default 0.85) |
Lower if the box shares memory with other services. |
BIND (default 0.0.0.0) |
Set 127.0.0.1 to keep the model off the network. |
SPEC=off |
Disables speculative decoding if your checkpoint has no drafter. |
| Provider name in tune output | Examples assume a provider called inference; use your own. |
The serving script is DGX Spark specific. The OpenClaw scripts are not — they work against any OpenAI-compatible backend.
The 4-bit serving recipe and the SM121 findings come from 0xBakeer/Qwen3.8-27B-4-bit-on-a-single-DGX-Spark. That repo measures throughput, not quality; run your own representative task before trusting any 4-bit checkpoint.
MIT licensed. No warranty — read the scripts before running them.