Heartbeats that don't execute are one of the most frustrating OpenClaw experiences because the system appears to be working โ the heartbeat fires โ but your agent never actually does anything. The skip system exists by design, but the reasons aren't always obvious.
Here's every skip reason you might encounter, what it means, and what (if anything) to do about it.
Skip Reasons Reference
Agent replied with nothing
Your HEARTBEAT.md instructions resulted in the agent deciding there was nothing to do, and it replied with the special NO_REPLY token. OpenClaw suppresses the announce (notification) and skips the cycle cleanly.
โ This is correct behavior. No action needed unless you expected something to run.
If you want to confirm your heartbeat actually ran and just had nothing to do, check the heartbeat log file in your workspace.
Agent suppressed its own output
The agent completed a turn but its last visible reply was exactly ANNOUNCE_SKIP. OpenClaw treats this as an intentional signal to suppress the notification โ the agent did something but decided the result didn't warrant a ping.
โ Expected behavior if you've instructed your agent to avoid spammy notifications.
To see what ran, check your heartbeat-log.md in the workspace โ the agent should still be logging its actions there.
Previous turn still running
The heartbeat scheduler tried to fire but an existing agent turn was still in progress. OpenClaw doesn't run overlapping turns โ it skips and retries after 1 second. If the in-flight turn finishes before the next scheduled heartbeat, everything proceeds normally.
โ Action needed if this is frequent: Your heartbeat interval is too short relative to how long your agent takes to complete a turn. Increase the heartbeat interval or reduce the scope of work per heartbeat cycle.
// In your heartbeat config โ increase interval
"heartbeat": {
"intervalMinutes": 60 // increase from default 30
}
Local model already running inference
Specific to setups running local models via Ollama. If a conversation turn is already using the local model when the heartbeat fires, the heartbeat skips rather than queueing two inference jobs simultaneously. This is the heartbeat-cron collision avoidance behavior.
โ Action if frequent: Use a different model for heartbeat vs interactive sessions, or increase the heartbeat interval to reduce collision probability.
// Configure heartbeat to use a different model
"heartbeat": {
"model": "ollama/qwen3.5:9b", // local model for heartbeats
"intervalMinutes": 60
}
// Keep interactive sessions on your primary model
Gateway not running when heartbeat fired
The heartbeat scheduler fired but couldn't reach the gateway. Usually means the gateway crashed or was manually stopped. The skip reason logs the timestamp so you can correlate with gateway logs.
โ Action: Set up the gateway as a systemd service so it auto-restarts on crash. See our auto-start guide for the systemd config.
API provider returned rate limit error
The heartbeat ran but the model API returned a 429 rate limit response. OpenClaw retries with backoff. If you're seeing this frequently, you're hitting provider rate limits โ usually token-per-minute limits rather than request limits.
โ Action: Reduce heartbeat frequency, switch to a lower-tier model for heartbeat tasks, or increase your API tier. Sonnet has higher rate limits than Opus.
Context too long โ compaction running
The heartbeat session's context window was nearly full. OpenClaw triggered an automatic compaction (summarization of older context) before allowing new turns. The heartbeat is deferred until compaction completes.
โ Usually resolves automatically. If this is recurring, your heartbeat sessions are accumulating too much history.
Fix: Add a HEARTBEAT.md instruction to periodically summarize and clear old context:
# In HEARTBEAT.md ## Context Management - At the start of each cycle, check if this session is getting long - If context feels heavy, summarize key decisions to memory.md and start fresh
How to See Skip Reasons in Your Logs
# Recent heartbeat activity with skip reasons openclaw logs --filter heartbeat --since 24h # Or check the gateway log directly openclaw gateway logs | grep -i "skip\|heartbeat"
Heartbeat Never Running At All?
If your heartbeat isn't firing at all (not skipping โ just absent), different diagnosis:
- HEARTBEAT.md doesn't exist โ OpenClaw looks for this file in your workspace root. Create it if missing.
- Heartbeat disabled in config โ check
openclaw.jsonfor"heartbeat": { "enabled": false } - Gateway not running โ heartbeats only fire when the gateway is active
- Isolated sessions misconfigured โ if you're on 4.2+ with isolated heartbeat sessions, check for the sub-agent pairing error (see our pairing fix guide)
The simplest debug flow: Set your HEARTBEAT.md to reply with exactly one line: "Heartbeat at [time]: HEARTBEAT_OK". If that appears in your logs, heartbeats are running. If not, the issue is in the scheduling layer, not your instructions.