Most bad agent automation is self-inflicted. People turn every recurring check into a cron job, then wonder why their agent keeps talking, their main session fills with junk, and their token bill climbs for no good reason. OpenClaw gives you two different scheduling loops because they solve two different problems—Cron for precise timing and isolated work, Heartbeat for periodic awareness in the main session. Swap them at your own risk.
The Core Difference
Heartbeat runs periodic agent turns in the main session with full context. It's approximate by design—default cadence is 30 minutes—and meant for recurring awareness, not sharp timing. Cron is the Gateway's built-in scheduler supporting at, every, and cron-expression schedules with timezone support. The docs are explicit: heartbeat batches checks while cron multiplies turns. That's the big cost and noise difference.
When to Use Heartbeat
Use heartbeat for context-sensitive tasks like checking inboxes, reviewing calendars for upcoming events, watching for finished background tasks, or sending lightweight check-ins during active hours. These are all tasks that benefit from main-session context and can be batched into one turn. The key feature? Heartbeat suppresses HEARTBEAT_OK replies when nothing needs attention, keeping both costs and chat noise lower.
When to Use Cron
Cron is for exact schedules, one-shot reminders, and isolated background work. If you need a report at exactly 9:00 AM or a reminder in 20 minutes, cron is your tool. The docs break cron into execution styles: main session (enqueued through heartbeat flow), isolated session (dedicated runs under cron:
The Expensive Mistake
The most common bad setup is five cron jobs running every 30 minutes—check inbox, check calendar, check notifications, check background tasks, check if human needs a nudge. That's five separate loops and often five separate agent turns. Heartbeat can batch all those checks in one pass. The reverse mistake: stuffing an exact 9:00 AM report into heartbeat because it runs every 30 minutes. That's sloppy. Heartbeat is approximate. Cron is exact.
Two Details Most People Miss
Top-of-hour cron expressions like "0 * * * *" are automatically staggered up to five minutes to reduce load spikes. Use --exact or set schedule.staggerMs to 0 if you need exact timing. Also, current-session and custom-session cron are often overlooked—OpenClaw supports binding recurring work to a persistent named session while still using cron's scheduling model instead of heartbeat's periodic awareness.
Key Takeaways
- Use Heartbeat when exact timing doesn't matter, the task benefits from main-session context, and multiple checks can be batched
- Use Cron when you need exact schedules, one-shot reminders, isolated sessions, or direct delivery to channels/webhooks
- Configure heartbeat with activeHours (e.g., 08:00-22:00) to prevent pointless night-time runs
- Prefer isolated cron for noisy chores that shouldn't pollute the main session
The Bottom Line
Heartbeat is your agent's recurring awareness loop. Cron is your scheduler. They overlap just enough to confuse people, but not enough to replace each other. When you respect that boundary—heartbeat for context-aware periodic checking, cron for exact or isolated scheduled work—OpenClaw feels clean. Ignore it and you build an expensive notification machine. Remember: heartbeat batches, cron multiplies.