openclaw - 💡(How to fix) Fix [Bug]: HEARTBEAT.md template claims empty=skip but heartbeat still runs — wastes API calls + saturates CPU

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

The HEARTBEAT.md template shipped with OpenClaw explicitly tells users:

Keep this file empty (or with only comments) to skip heartbeat API calls.

This is not true in practice. When heartbeat is enabled via agents.defaults.heartbeat.every: "30m", agents with empty/comment-only HEARTBEAT.md files still run full heartbeat cycles — making model calls, loading context, and consuming API tokens.

Root Cause

The shipped HEARTBEAT.md contains this comment:

# Keep this file empty (or with only comments) to skip heartbeat API calls.
# Add tasks below when you want the agent to check something periodically.

However, the heartbeat runner does not check HEARTBEAT.md content before dispatching. The enablement logic in heartbeat-summary.ts only checks whether the heartbeat config is truthy — empty {} is truthy, and an agent with no explicit heartbeat config inherits the defaults which always resolve to the default cadence.

This is a documentation-contract violation: the template promises a behavior that the code does not implement.

Fix Action

Fix / Workaround

However, the heartbeat runner does not check HEARTBEAT.md content before dispatching. The enablement logic in heartbeat-summary.ts only checks whether the heartbeat config is truthy — empty {} is truthy, and an agent with no explicit heartbeat config inherits the defaults which always resolve to the default cadence.

Long-term (code fix): Implement the promised behavior — check HEARTBEAT.md for non-comment content before dispatching a model call, as proposed in #77699.

Code Example

# Keep this file empty (or with only comments) to skip heartbeat API calls.
# Add tasks below when you want the agent to check something periodically.
RAW_BUFFERClick to expand / collapse

Summary

The HEARTBEAT.md template shipped with OpenClaw explicitly tells users:

Keep this file empty (or with only comments) to skip heartbeat API calls.

This is not true in practice. When heartbeat is enabled via agents.defaults.heartbeat.every: "30m", agents with empty/comment-only HEARTBEAT.md files still run full heartbeat cycles — making model calls, loading context, and consuming API tokens.

Reproduction

  1. Configure agents.defaults.heartbeat.every: "30m"
  2. Add a secondary agent (e.g., case, monday) with default heartbeat inheritance
  3. Keep the agent's HEARTBEAT.md at the shipped template (comments only, no tasks)
  4. Observe: the agent runs heartbeat every 30 minutes despite zero actionable tasks

Observed Impact

  • Event loop saturation: P99 event loop delay spikes to 15.8 seconds during heartbeat model calls, with event loop utilization hitting 100%
  • CPU at 98-100% for the duration of the heartbeat call
  • Wasted API calls: ~48 empty model invocations per day across multiple agents, each loading full conversation context
  • Multi-agent cascade: When multiple agents share the same heartbeat interval, a slow heartbeat from one agent delays all others (see #63149)

Root Cause

The shipped HEARTBEAT.md contains this comment:

# Keep this file empty (or with only comments) to skip heartbeat API calls.
# Add tasks below when you want the agent to check something periodically.

However, the heartbeat runner does not check HEARTBEAT.md content before dispatching. The enablement logic in heartbeat-summary.ts only checks whether the heartbeat config is truthy — empty {} is truthy, and an agent with no explicit heartbeat config inherits the defaults which always resolve to the default cadence.

This is a documentation-contract violation: the template promises a behavior that the code does not implement.

Related Issues

  • #64293: "Heartbeat runs despite heartbeat: {} config" — Confirms {} heartbeat config is treated as enabled; PR #64540 targeting fix
  • #77699: "Feature: Heartbeat auto-toggle when periodic tasks exist" — Feature request for exactly the behavior the template claims exists
  • #63149: "Gateway CPU stuck at 100%" — The downstream consequence; sequential multi-agent heartbeat broadcast + CPU saturation. PR #80470 targeting fix.

Suggested Fix

Short-term (doc fix): Update HEARTBEAT.md template to not claim empty-file-skip behavior. Add guidance that disabling heartbeat requires every: "0" or every: "auto" mode.

Long-term (code fix): Implement the promised behavior — check HEARTBEAT.md for non-comment content before dispatching a model call, as proposed in #77699.

Environment

  • OpenClaw 2026.5.7 (eeef486)
  • Windows 10, Node.js v24.15.0
  • Multi-agent setup: main + case + monday
  • Heartbeat model: DeepSeek V4 Flash (defaults)

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - 💡(How to fix) Fix [Bug]: HEARTBEAT.md template claims empty=skip but heartbeat still runs — wastes API calls + saturates CPU