Field notes · 2026-08-25 · RunVouch
The dead man's switch for AI agents (and why a ping isn't enough)
A ping monitor knows a job ran. For an agent that is the least interesting fact. What a dead man's switch has to check when the job is an LLM.
A dead man's switch is the oldest trick in operations: the job has to check in, and silence is the alarm. Healthchecks.io and Cronitor built good businesses on it for cron. I used Healthchecks for years and still think it is the right shape. But when the job became an agent, the switch stopped catching what actually went wrong.
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.
What a ping monitor knows, and what it can't
A ping monitor knows exactly one thing: at some moment, something sent an HTTP request to a URL. From that it derives "the job ran" and, with a schedule, "the job is late". That is enough when the job is a backup script: if it ran, it almost certainly did the thing, because the thing is deterministic.
An agent is not deterministic. It can run to completion, exit zero, send the ping, and have done nothing useful. Anthropic says this plainly about Claude Code Routines: a green status "does not mean the task in your prompt succeeded" (docs). The ping is sent by the same process that may have gone wrong, so the ping inherits the agent's blind spots.
The four questions a dead man's switch for agents has to answer
- Did it start on time? The classic. Silence past the cadence plus a grace period is
MISSED. This one a ping monitor does well. - Is it still moving? Agents hang: a tool waiting on a socket, an MCP server that never answers, a prompt nobody will confirm. Per-tool heartbeats turn a hung run into
STALLEDwithin minutes instead of at the next morning's review. - Did it do the work? The run has to hand over proof: a file that changed during the run, a URL that returns 200, an assertion that exits 0. No proof on a green exit is
NO_EVIDENCE. This is the check that does not exist in a ping monitor, and it is the one that would have caught most of my silent failures. - What did it cost, and is it looping? The same tool called with identical input eight times is a loop, whether or not each call "succeeded". A run or a day over its dollar cap is
BUDGET. Neither is visible from a ping, and both are where the money goes ($1,818 in two nights, 1,535 identical calls).
Why the clock has to live outside the agent
Every one of those checks has the same design rule: the thing that notices must not be the thing that fails. An agent cannot report that it never started. A hung agent is, by definition, not reporting. A looping agent is convinced it is making progress. So the expected cadence, the max runtime, the evidence rule and the cost cap all live on the watchdog's side, and the agent's only job is to check in with facts: started, tool called, ended with this exit code and this evidence.
The corollary is that the watchdog must never be able to take the job down. rv run fails open: if RunVouch is unreachable, your command runs exactly as before and you lose one run of monitoring, not the run.
Two lines around any job
rv agent nightly-report --cadence 24h --cap-run-cost 2 --evidence rv run nightly-report --evidence-file out/report.html -- claude -p "build tonight's report"
For Claude Code there is a plugin that does this through hooks; for Python and Node there are one-file clients; for everything else two HTTP calls. Alerts go to Telegram, Slack or a webhook. If you already run Healthchecks or Cronitor for classic cron, keep them — RunVouch is for the jobs where "it ran" is not the question.
FAQ
Isn't this just Healthchecks with extra fields?
The heartbeat part is the same idea, deliberately. The difference is evidence, retry-storm detection and cost caps — three checks that need to know about tool calls and outcomes, which a ping URL cannot carry.
What counts as evidence?
A file that exists, is non-empty and was modified during the run; an HTTPS URL that returns 200 after the run; or a boolean/assertion your code supplies. You decide up front what "done" looks like.
Does it need my prompts or outputs?
No. It receives timestamps, exit status, tool names, a hash of tool inputs, cost and token counts, output size and evidence verdicts. Prompts and outputs stay with you.
Try it: free for 3 agents · Docs: Claude Code · cron