Context
OpenClaw has a heartbeat mechanism distinct from cron. It's a periodic agent wake-up in the main session where the agent reads a HEARTBEAT.md checklist, handles whatever needs attention, and replies HEARTBEAT_OK if nothing does. This is fundamentally different from cron jobs which run at precise times with specific prompts.
OpenClaw docs:
Heartbeat vs Cron — Key Differences
| Aspect |
Heartbeat |
Cron |
| Session |
Main (shared context) |
Isolated or main |
| Prompt |
Agent reads HEARTBEAT.md checklist |
Specific prompt per job |
| Timing |
Regular interval (e.g. 30m), drifts ok |
Precise cron expression |
| Suppression |
HEARTBEAT_OK = nothing to report, no message sent |
action: "silent" |
| Batching |
One turn handles N checks |
One job = one task |
| Mutability |
Agent can update HEARTBEAT.md itself |
Schedule managed externally |
Why This Matters for Macroclaw
Currently macroclaw has several periodic cron jobs (memory-capture, dinner-prompt, improvement-ideas) that each spawn separate agent turns. A heartbeat would:
- Batch multiple checks into one agent turn → fewer API calls, lower cost
- Give the agent autonomy to decide what's worth surfacing vs. silently acknowledging
- Enable proactive behavior without hardcoding every check as a separate cron job
- Allow the agent to self-modify its own checklist (HEARTBEAT.md) as priorities change
- Maintain conversational context since it runs in the main session
Proposed Options
Option A: Native heartbeat (new mechanism)
Add a dedicated heartbeat loop alongside the existing cron scheduler:
- New config field:
heartbeat: { every: "30m", activeHours: {...} }
- Reads
HEARTBEAT.md from workspace
- Runs in main session
HEARTBEAT_OK token suppression (strip and don't deliver)
- Active hours support (skip outside window)
Pros: Clean separation, matches openclaw semantics
Cons: New code path, partially duplicates cron infrastructure
Option B: Heartbeat as a special cron job (lightweight)
Implement heartbeat behavior on top of existing cron:
- A cron job named
heartbeat with special handling
- Prompt reads
HEARTBEAT.md if it exists
- Runs in main session (not isolated)
HEARTBEAT_OK in response → auto-silent (no message delivered)
- Workspace template includes
HEARTBEAT.md
Pros: Minimal code changes, reuses existing cron infrastructure
Cons: Slightly overloads cron semantics
Option C: HEARTBEAT.md convention only (zero code)
No platform changes. Just:
- Add a
heartbeat cron job to workspace template's schedule.json
- Add
HEARTBEAT.md to workspace template
- Prompt instructs agent to read HEARTBEAT.md, reply with
action: "silent" if nothing to report
- Migrate existing periodic checks (memory-capture, dinner-prompt) into HEARTBEAT.md checklist items
Pros: Zero platform code, works today
Cons: No HEARTBEAT_OK suppression (relies on agent using action: "silent" correctly), no active hours, no cost optimizations
Recommendation
Option B — heartbeat as a special cron job. It fits macroclaw's design philosophy of keeping things simple and building on existing infrastructure. The key additions:
- Recognize
heartbeat as a special cron job name
- Auto-detect
HEARTBEAT_OK in response → treat as silent
- Always run in main session (not isolated)
- Add
HEARTBEAT.md to workspace template
We could even start with Option C (pure convention) to validate the pattern, then graduate to Option B when we want platform-level suppression.
OpenClaw Features We Can Skip (for now)
- Multi-agent heartbeats (macroclaw is single-agent)
- Per-channel visibility controls (macroclaw is single-channel Telegram)
lightContext / isolatedSession (macroclaw sessions are already lightweight)
includeReasoning delivery (not applicable)
- Manual wake CLI (
openclaw system event)
- Lobster workflow integration
Context
OpenClaw has a heartbeat mechanism distinct from cron. It's a periodic agent wake-up in the main session where the agent reads a
HEARTBEAT.mdchecklist, handles whatever needs attention, and repliesHEARTBEAT_OKif nothing does. This is fundamentally different from cron jobs which run at precise times with specific prompts.OpenClaw docs:
Heartbeat vs Cron — Key Differences
HEARTBEAT_OK= nothing to report, no message sentaction: "silent"Why This Matters for Macroclaw
Currently macroclaw has several periodic cron jobs (
memory-capture,dinner-prompt,improvement-ideas) that each spawn separate agent turns. A heartbeat would:Proposed Options
Option A: Native heartbeat (new mechanism)
Add a dedicated heartbeat loop alongside the existing cron scheduler:
heartbeat: { every: "30m", activeHours: {...} }HEARTBEAT.mdfrom workspaceHEARTBEAT_OKtoken suppression (strip and don't deliver)Pros: Clean separation, matches openclaw semantics
Cons: New code path, partially duplicates cron infrastructure
Option B: Heartbeat as a special cron job (lightweight)
Implement heartbeat behavior on top of existing cron:
heartbeatwith special handlingHEARTBEAT.mdif it existsHEARTBEAT_OKin response → auto-silent (no message delivered)HEARTBEAT.mdPros: Minimal code changes, reuses existing cron infrastructure
Cons: Slightly overloads cron semantics
Option C: HEARTBEAT.md convention only (zero code)
No platform changes. Just:
heartbeatcron job to workspace template'sschedule.jsonHEARTBEAT.mdto workspace templateaction: "silent"if nothing to reportPros: Zero platform code, works today
Cons: No
HEARTBEAT_OKsuppression (relies on agent usingaction: "silent"correctly), no active hours, no cost optimizationsRecommendation
Option B — heartbeat as a special cron job. It fits macroclaw's design philosophy of keeping things simple and building on existing infrastructure. The key additions:
heartbeatas a special cron job nameHEARTBEAT_OKin response → treat as silentHEARTBEAT.mdto workspace templateWe could even start with Option C (pure convention) to validate the pattern, then graduate to Option B when we want platform-level suppression.
OpenClaw Features We Can Skip (for now)
lightContext/isolatedSession(macroclaw sessions are already lightweight)includeReasoningdelivery (not applicable)openclaw system event)