Field notes · 2026-08-25 · RunVouch

OpenClaw stuck in a polling loop: $150, a crash, and no alert — detect it in 60 seconds

An OpenClaw agent called the same tool 1,535 times in two hours. Every call looked fine. How a retry-storm rule and a daily cap catch this before the bill.

In February 2026 an OpenClaw user filed issue #16808: their agent called process(action:log, sessionId:X) 1,535 times in about two hours. Every call returned the same "no new output". Cost about $150, memory from 800 MB to 3 GB, then a crash. The watchdog they had checked that the process existed. It did exist. It was just busy doing nothing, expensively.

I know that shape. My trading bot once retried the same order payload 400 times against an exchange whose per-request logs showed nothing but 200s. RunVouch is a dead man's switch, cost cap and outcome check for unattended AI agents: it expects a heartbeat per run, alerts when a run or a day crosses a dollar cap, and tells you when a run is missed, stalled, looping or produced no evidence.

Why "is the process alive" is the wrong question for an agent

Process-level watchdogs answer one question: is the PID there. A polling loop passes that check perfectly. So does a hung tool call, and so does an agent that finished its task an hour ago and is now re-reading the same file because its stop condition never fired.

The loop in #16808 is invisible per call because each call is identical and each call succeeds. It is only visible as a pattern: same tool, same input, again and again, inside one run. That is the unit a watchdog for agents has to reason about — the run, not the process and not the call.

The 60-second detection: same tool, identical input, N times

RunVouch hashes the input of every tool call it is told about. When the same tool with the same input hash appears eight times in one run, that is RETRY_STORM and you get a message. Call 8 of 1,535 happens within the first minute of that loop. The threshold is configurable; eight is where legitimate retries stop and loops start, in my experience.

curl -X POST https://api.runvouch.com/v1/runs/tool \
  -H "X-API-Key: $RUNVOUCH_KEY" -H "Content-Type: application/json" \
  -d '{"run_id":"…","tool":"process","input":{"action":"log","sessionId":"X"},"cost":0.001}'

A loop that polls with a changing cursor does not match, because the input changes. Polling the same endpoint with the same arguments does, which is the point.

The backstop: a daily cap the agent cannot talk its way past

Loop detection needs tool-level reporting. If you only report run start and end, you still get the second line of defence: cap_day_cost. Register the agent with a daily cap and every run reports its cost; the moment the 24-hour sum crosses the cap you get BUDGET_DAY, and a webhook can pause the agent so the next scheduled task does not start.

rv agent openclaw-main --cadence 15m --grace 5m --cap-day-cost 10 --evidence

For OpenClaw specifically there is a skill that teaches the agent to check in at start, per tool call and at the end, with evidence — and to stop repeating a call when RunVouch answers with an alert. Setup is in the OpenClaw docs.

Evidence closes the last gap

An agent in a loop is "working". An agent that finished and exited is "done". Neither tells you whether the inbox was actually answered. That is why the run end carries evidence — {"replied": true}, a file that changed, a URL that is live. No evidence on a green finish is NO_EVIDENCE, and the agent cannot fake it because the check runs on your side.

Free for three agents, $9 Solo, $29 Team, MIT self-host, EU hosting. Alerts on Telegram, Slack or any webhook.

FAQ

Won't my agent's normal polling trigger RETRY_STORM?
Only if it polls with byte-identical input. Include a cursor, timestamp or page token in the call and it will not match. If it genuinely polls the same thing unchanged, you probably want to know that too.

Can RunVouch stop the loop itself?
It alerts and, through your webhook, can pause the agent so the next run does not start. Killing a live process is your call — a watchdog that can take your job down is a second failure mode.

What if the agent never reports tool calls?
Then you still have MISSED, STALLED (no heartbeat past max runtime), BUDGET_DAY from run-level cost, DRIFT, and NO_EVIDENCE. Tool-level reporting adds RETRY_STORM and per-run budgets.


Try it: free for 3 agents · Docs: Claude Code · cron