Your openclaw heartbeat stopped firing and you have no idea why. The logs are silent, the agent is idle, and the scheduled checks you set up last week are just not happening. This guide walks through every known cause, from misconfigured intervals to a subtle eligibility trap that has bitten nearly everyone who customizes per-agent heartbeat settings.
Heartbeat failures account for roughly half of all “my agent stopped working” reports in the OpenClaw community. The fix is almost never “restart the gateway.” It is almost always a configuration issue hiding in plain sight.
Start Here: The Diagnostic Command Ladder
Before guessing at causes, run these four commands in order. Each one narrows the problem space.
openclaw system heartbeat last
This is the single most useful command. It shows the last heartbeat result, including the skip reason if one exists. If the output shows "ran" with a recent timestamp, your heartbeat is firing and the problem is downstream (delivery, not scheduling). If it shows a skip reason, that reason tells you exactly where to look next.
openclaw config get agents.defaults.heartbeat
This dumps your full heartbeat configuration. Check every (must be non-zero), lightContext, target, and activeHours. We will reference specific fields throughout this guide.
openclaw logs --follow
Watch the live log stream for heartbeat-related entries. Look for lines containing heartbeat, skip, or eligibility.
openclaw channels status --probe
If heartbeat runs but messages never arrive, this command tests channel connectivity. A failed probe means delivery is broken, not the heartbeat itself.
Common Skip Reasons and What They Mean
When openclaw system heartbeat last shows a skip reason instead of "ran", the system is telling you exactly why it skipped. Here is what each reason means and how to fix it.
empty-heartbeat-file
The heartbeat was skipped because your HEARTBEAT.md file has no actionable content and no tagged cron event is queued. This is the most common skip reason when lightContext is set to true.
When lightContext: true, the agent only receives the contents of HEARTBEAT.md as its context. If that file is empty or missing entirely, OpenClaw skips the heartbeat to avoid wasting an API call on nothing.
Fix: Create or populate HEARTBEAT.md in your workspace root with at least one checklist item:
# Heartbeat checklist
- Check for pending notifications
- Review flagged tasks
- Scan for urgent follow-ups
quiet-hours
The heartbeat was skipped because the current time falls outside your configured activeHours window.
Fix: Check your timezone configuration:
openclaw config get agents.defaults.heartbeat.activeHours
openclaw config get agents.defaults.userTimezone
A common trap: if userTimezone is unset, OpenClaw falls back to the host machine’s timezone. If your server is in UTC but you configured activeHours thinking in Eastern time, your heartbeat window is shifted by 4-5 hours.
requests-in-flight
The main processing lane is busy with another request. Heartbeat will automatically reschedule for the next available slot.
Fix: This is transient and self-resolving. If it persists, your agent may be stuck in a long-running task. Check openclaw logs --follow for the blocking request.
alerts-disabled
All three visibility flags (showOk, showAlerts, useIndicator) are set to false. When this happens, OpenClaw skips the heartbeat run entirely with no model call.
Fix: Enable at least one visibility flag:
openclaw config set channels.defaults.heartbeat.showAlerts true
The Explicit-Agent Mode Trap
This one catches nearly everyone who customizes per-agent heartbeat settings. It comes from GitHub Issue #26219 and the behavior is documented but not obvious.
Here is the rule: when any agent in your agents.list[] defines a heartbeat block, OpenClaw switches to “explicit-agent mode.” In this mode, only agents with their own heartbeat configuration will run heartbeats. Agents relying on agents.defaults.heartbeat become ineligible.
A concrete example. Say you have three agents: main, trustee, and scout. You disable heartbeat for scout by adding heartbeat: { every: "0m" } to its config. You expect main and trustee to inherit the default 30-minute heartbeat. They will not. Because scout has an explicit heartbeat block, the system enters explicit-agent mode and main and trustee are now ineligible.
Fix (Pattern A, recommended): Remove all per-agent heartbeat blocks. Control everything through agents.defaults.heartbeat.
Fix (Pattern B): Define heartbeat blocks for every agent, including the ones you want to keep at defaults:
agents: {
list: [
{ id: "main", heartbeat: { every: "30m" } },
{ id: "trustee", heartbeat: { every: "30m" } },
{ id: "scout", heartbeat: { every: "0m" } }
]
}
One more gotcha: openclaw system heartbeat enable only toggles the global pause flag. It does not override per-agent eligibility. Running it will return success even when no agent is eligible to heartbeat, which is misleading.
Known Bugs by Version
Several heartbeat regressions have shipped in specific OpenClaw releases. If your heartbeat broke after an update, check this table.
| Version | Bug | Symptom | GitHub Issue | Status |
|---|---|---|---|---|
| 2026.2.24 | Explicit-agent mode blocks defaults | Heartbeat disabled for all agents despite config | #26219 | Closed (config behavior) |
| 2026.3.11 | Stale timestamp injection | Agent sees time 2+ hours behind reality | #44993 | Fixed |
| 2026.3.28 | Model override regression | heartbeat.model ignored, uses primary model | #58137 | Open |
| 2026.2.3 | Model override not working | heartbeat.model config ignored | #9556 | Fixed |
The stale timestamp bug in v2026.3.11 is worth highlighting. The root cause was a guard in appendCronStyleCurrentTimeLine that prevented timestamp refreshing once a “Current time:” line already existed in the message. The workaround before the fix was restarting the gateway periodically.
Manual Trigger for Testing
When diagnosing, you do not want to wait 30 minutes between tests. Force an immediate heartbeat with:
openclaw system event --text "Check for urgent follow-ups" --mode now
Use --mode next-heartbeat to queue the event for the next scheduled tick instead of firing immediately. This is useful for testing that the scheduler itself is working.
lightContext: When Less Context Causes More Problems
The lightContext: true setting is a cost optimization that restricts the heartbeat’s context to only HEARTBEAT.md. In normal operation, this cuts token usage from roughly 100K per run to 2-5K. But it creates a failure mode that is easy to miss.
If lightContext is true and HEARTBEAT.md is empty, deleted, or contains only whitespace, the heartbeat skips with the empty-heartbeat-file reason. No error is thrown. No log line warns you. The heartbeat just silently stops.
A common scenario is enabling lightContext for cost savings, then weeks later wondering why the heartbeat stopped. The HEARTBEAT.md file was accidentally deleted during a repo cleanup.
Recommendation: If you use lightContext: true, add HEARTBEAT.md to your project’s protected files or version control. Treat it as infrastructure, not a scratch file.
Frequently Asked Questions
Why is my openclaw heartbeat not triggering at all?
Run openclaw system heartbeat last and check the skip reason. The five most common causes are: every set to "0m", empty-heartbeat-file when using lightContext, the explicit-agent mode trap from Issue #26219, quiet-hours from timezone misconfiguration, and alerts-disabled from all visibility flags being off. The skip reason from that command will point you to the right section of this guide.
How do I manually trigger a heartbeat for testing?
Run openclaw system event --text "Check for urgent follow-ups" --mode now. This fires an immediate heartbeat without waiting for the scheduled interval. For testing the scheduler itself rather than just the heartbeat logic, use --mode next-heartbeat to queue the event for the next tick.
What does the empty-heartbeat-file skip reason mean?
It means lightContext is enabled and your HEARTBEAT.md file is either missing, empty, or contains only whitespace. OpenClaw skips the heartbeat to avoid an API call with no useful context. Create a HEARTBEAT.md with at least one checklist item to fix it.
My heartbeat runs but messages never arrive. What is wrong?
The heartbeat is firing but delivery is failing. Run openclaw channels status --probe to test channel connectivity. Also check your target setting, which controls where messages go. A target of "none" means the heartbeat runs internally but sends no outbound messages. Verify channels.defaults.heartbeat.showAlerts is true.
Should I use heartbeat or cron for scheduled tasks?
Heartbeat runs within the main session and is designed for lightweight, periodic check-ins. Cron jobs create detached background task records and are better for heavy, independent workloads. Use heartbeat for monitoring and alerting. Use cron for scheduled data processing, report generation, or anything that should run regardless of session state.
How do I reduce heartbeat API costs?
Three settings make the biggest difference: isolatedSession: true drops token usage from around 100K to 2-5K per run. lightContext: true limits bootstrap context to just HEARTBEAT.md. And overriding model to a cheaper option (like GPT-5.4 instead of Claude Opus 4.6) further reduces per-run cost. See our OpenClaw API costs guide for full pricing breakdowns.
Why does openclaw heartbeat show the wrong time?
This was a known bug in v2026.3.11 (GitHub Issue #44993). A guard in the timestamp injection code prevented refresh once a “Current time:” line existed. The fix replaced the early-return guard with regex-based in-place substitution. Update to a version after 2026.3.11 or restart the gateway as a workaround.
Does system heartbeat enable actually enable heartbeat for all agents?
No. It only toggles the global pause flag. If your configuration puts the system in explicit-agent mode (any agent in agents.list[] has a heartbeat block), the enable command will return success but agents without their own heartbeat block remain ineligible. Check per-agent eligibility with openclaw config get agents.list.
Key Takeaways
- Always start diagnosis with
openclaw system heartbeat lastand read the skip reason before changing anything - The explicit-agent mode trap (Issue #26219) is the most common non-obvious cause: adding a heartbeat block to any agent changes eligibility rules for all agents
- If you use
lightContext: true, treatHEARTBEAT.mdas critical infrastructure, not a disposable file - Timezone mismatches between
userTimezoneandactiveHourscause silent heartbeat suppression during what you think are active hours - Check the known bugs table after any OpenClaw version upgrade that breaks your heartbeat schedule
Related Resources
- OpenClaw Heartbeat Scheduling Guide for initial setup and configuration
- OpenClaw Cron Jobs for heavier scheduled workloads
- OpenClaw Logging and Debugging for deeper log analysis
- OpenClaw API Costs for heartbeat cost optimization
- OpenClaw Setup Guide for first-time installation
- Official OpenClaw Heartbeat Docs for the full configuration reference
SFAI Labs