
Your bots are alive. They just can't prove it.
OpenClaw's heartbeat system has five bugs that silently eat your bots' messages before they ever reach you. No errors. No logs. Just silence. This prompt diagnoses your entire fleet, fixes the pipeline, and gets proof-of-life messages flowing again — in one paste.
openclaw system heartbeat last → null Bot running for hours — zero heartbeat messages received Heartbeat worked once, then stopped forever Some bots deliver, others don't — same config Your bots aren't dead. OpenClaw is eating their messages before they reach you.
If any of this sounds familiar, you're not alone:
“I set up heartbeats but never got a single message. I assumed they weren't configured right.” “Three of my bots send heartbeats fine. The other two are silent. Same config on all of them.” “It worked for one tick, then stopped. I spent an hour debugging before giving up.” “I checked the session transcript — the bot IS responding. But the message never reaches Telegram.”
Five Things Go Wrong — Most Fleets Hit All Five
1. The escape hatch: OpenClaw's default prompt tells your bot “if nothing needs attention, reply HEARTBEAT_OK.” The bot obeys. OpenClaw strips “HEARTBEAT_OK” from the response and suppresses delivery if what's left is under 300 characters. Your bot did everything right — and got silenced for it.
2. Cron contamination: your cron job responses go through the same filter that checks for HEARTBEAT_OK. If a cron response accidentally contains that text, it gets misclassified and suppressed. Cron jobs and heartbeats should have separate pipelines. They don't.
3. Queue collision: before firing a heartbeat, OpenClaw checks whether anything else is running. If a cron job is active at that exact moment, the heartbeat is silently skipped. When your cron and heartbeat intervals share a common factor (both at 10 minutes), they collide on a fixed schedule.
4. The dedup trap: OpenClaw suppresses heartbeat messages that look too similar to the last one. Bots with simple tasks produce “nothing to report” in slightly different words. The dedup filter sees through the paraphrasing and silently drops every message after the first. No errors. No logs.
5. The active drop: if your bot is doing anything when a heartbeat tick fires — reading a message, running a tool, processing a cron — the heartbeat is immediately dropped. Not queued. Not deferred. Dropped. This is hardcoded in OpenClaw and cannot be fixed via config.
The Core Fix
This single change fixes bugs 1–4: ackMaxChars: 0 means only a completely empty response gets suppressed (bug 1, and its downstream cron/queue entanglements — bugs 2 and 3 — all trace back to the same stripHeartbeatToken pipeline), and appending [tick:<unix_timestamp>] to every response defeats the dedup filter (bug 4). Bug 5 — the active session drop — is hardcoded in OpenClaw and can't be fixed via config; a prime-number interval just minimizes how often it collides with your cron jobs.
Want a different interval, a different response style (jokes, weather, fun facts, or your own custom instruction), or the full guided diagnostic across your whole fleet? Build it below.
Build Your Heartbeat Fix Prompt
Build Your Heartbeat Fix Prompt
Customize your heartbeat settings. The generator builds a Claude Code prompt tailored to your fleet. Copy it, paste it into Claude Code on the same machine as your bots, and let it fix everything.
Heartbeat Interval
OpenClaw default: 30mShorter = more proof-of-life messages but more API calls. Longer = fewer messages but lower cost.
Adjusted to 31m (prime) to avoid cron collisions
Heartbeat Response Style
What your bot says on each heartbeat tick.
Live Heartbeat Prompt Preview
This is what gets written to your clawdbot.json heartbeat prompt field.
The generator above produces a longer, guided version of this prompt — it discovers every bot on your machine, reports each one's current heartbeat config, and walks Claude Code through pre-flight checks, the fix, a reload, and a two-tick verification before declaring success.
Five Bugs — Technical Detail
Behind those five bugs is a 7-gate suppression pipeline — resolveActiveRunQueueAction(), normalizeStreamingText(), stripHeartbeatToken(), buildReplyPayloads(), normalizeReplyPayload(), isRenderablePayload(), and shouldSuppressMessagingToolReplies() — each one another place a heartbeat can quietly die. Six of the seven gates are fixed by the ackMaxChars: 0 change above; only gate 1 (the active-drop) has no config-level fix, and gate 7 is a documented limitation if your bot uses a messaging tool during its heartbeat.
1. Default prompt biased toward silence 2. Shared classification pipeline for cron and heartbeat 3. Queue gate with no heartbeat priority 4. Dedup filter on a monitoring system 5. Active session drop with no deferral The common thread: OpenClaw's heartbeat was designed for alerting (tell me when something's wrong), not monitoring (prove you're alive). These config workarounds bridge the gap until the architecture catches up.