OpenClaw is reactive by default. You message it and it answers. The moment you turn on heartbeat or cron it stops being a chat bot and starts behaving like a service that keeps an eye on things.
People mix these up because both “run later” but they solve different problems.
- Heartbeat is a periodic check that runs inside an agent’s main session. It reads
HEARTBEAT.mdfrom the workspace and decides if anything needs attention. If nothing is wrong it repliesHEARTBEAT_OKand OpenClaw drops the message quietly. - Cron runs scheduled jobs at specific times or intervals. Cron can run in the main session or in an isolated session. It can also “announce” results back to your chat.
And here’s the practical part: on a laptop heartbeat is annoying because your machine sleeps and the app closes. On a VPS heartbeat and cron stay alive. That is the whole point of hosting OpenClaw somewhere that does not go to sleep. If you haven’t deployed yet we wrote a VPS-focused setup path in host OpenClaw securely on VPS and there’s also OpenClaw cron scheduler guide if you want to go deep on cron flags.
So what does “proactive” mean in OpenClaw?
I think the clean mental model is this:
- Heartbeat is “is anything happening that I should know about?”
- Cron is “do this at 09:00” or “do this every Friday”
Heartbeat works best when a single run can batch multiple checks. Inbox sweep plus calendar scan plus a quick service health check is perfect. Cron works best when you care about timing or you want predictable isolated runs.
OpenClaw’s own docs separate the two concepts and that page is worth skimming once because it matches what you’ll see in production.
Heartbeat in OpenClaw
How heartbeat runs
Heartbeat is a scheduled agent run that reads a checklist from HEARTBEAT.md in the workspace. The response contract matters:
- If nothing needs attention the agent should reply
HEARTBEAT_OK. - OpenClaw treats
HEARTBEAT_OKas an acknowledgement and it drops the reply if there is nothing else meaningful in it.
This is why heartbeat stays quiet on good days. If your heartbeat is spamming you it usually means your checklist is vague and the agent keeps “finding” work that does not exist.
Basic heartbeat config
Heartbeat is configured per agent. You can set defaults then override on a specific agent:
agents: {
defaults: {
heartbeat: {
every: "30m",
target: "last"
}
},
list: [
{ id: "main", default: true },
{
id: "ops",
heartbeat: {
every: "1h",
target: "whatsapp",
to: "+15551234567",
prompt: "Read HEARTBEAT.md. Follow it strictly. Reply HEARTBEAT_OK if nothing needs attention."
}
}
]
}
If you want a canonical explanation of HEARTBEAT_OK handling and what gets dropped you can cross-check the official heartbeat page.
Writing HEARTBEAT.md so it behaves
Write it like a checklist. Not a brainstorm. If you give it open ended tasks you will get open ended output.
A simple template that works well:
# HEARTBEAT.md
- Inbox: check urgent messages and draft replies if needed.
- Calendar: check events in the next 2 hours and remind me 15 min before.
- VPS: check disk and memory then alert on thresholds.
- If nothing needs attention reply HEARTBEAT_OK.
What I change in real setups after a week of running it:
- I add stop conditions so the agent knows when to shut up.
- I replace vague checks with explicit commands once I know what tools I trust.
- I remove tasks that are not time-sensitive because heartbeat has a cost and it runs a lot.
If you are using OpenClaw’s Gmail and Calendar tools then your heartbeat checklist becomes way more useful. These two guides help with the plumbing: OpenClaw Gmail integration and OpenClaw Google Calendar integration.
When heartbeat is a bad fit
Heartbeat is not great for “send the weekly report Monday at 09:00” or “remind me in 17 minutes”. It will drift because it is interval-based and it also runs in the main session context which you may not want for heavy tasks.
It is also not great for expensive models at very short intervals. You don’t need a 5 minute heartbeat to check a calendar that changes twice a day.
Cron in OpenClaw
What cron runs and where it runs
Cron jobs can run in the main session or in an isolated session. Isolated is the default choice for anything that is noisy or heavy because it does not pollute your main chat history and it is easier to reason about. OpenClaw’s cron docs also call out delivery behaviors like “announce” and “none”.
The command surface changes over time so I rely on the official CLI page when I forget flags.
Daily briefing example
This is a good first cron job because it is predictable and it gives you a reason to keep the gateway running on a VPS.
openclaw cron add \
--name "Daily briefing" \
--cron "0 9 * * *" \
--session isolated \
--message "Daily briefing: calendar today, inbox urgent summary, VPS health, and anything I should watch." \
--announce \
--channel whatsapp \
--to "+15551234567"
Notice two things:
--session isolatedkeeps the run clean and separate.--announceis the “post a summary back” mode that isolated jobs default to in current versions.
One-shot reminder example
For “remind me in 20 minutes” cron is the right tool because it can schedule a one-shot job. The CLI notes that one-shot jobs delete after success by default and you can keep them if you want.
Example pattern:
openclaw cron add \
--name "Water the plants" \
--at "20m" \
--message "Reminder: water the plants." \
--channel telegram \
--to "tg:123456789" \
--announce
Why cron “runs” but nothing shows up
This is one of those issues that makes people think cron is broken when it is really delivery configuration or a channel permission problem. OpenClaw ships an automation troubleshooting page that is actually useful when jobs appear scheduled but do not fire or do not deliver.
Also note that isolated jobs default to announce delivery and “deliver” is now treated as a deprecated alias in the CLI notes.
If you want the boring debugging checklist I use:
- Run
openclaw cron listand confirm the job is enabled and has a next run time. - Check delivery mode. If you set “none” you will get silence by design.
- Confirm the channel is logged in and allowed to message the target peer.
- Look at recent runs and errors. The troubleshooting doc calls out common signatures and “scheduler disabled” style failures.
Heartbeat vs cron in real setups
I like to decide by asking one question: “do I care about exact timing?”
- If yes then cron.
- If no and it is a periodic awareness sweep then heartbeat.
Some examples that map cleanly:
Inbox and calendar sweep
Heartbeat is better because it can batch checks and it can use the main session context. If you chatted about a meeting earlier heartbeat can reference that naturally. Cron can do it too but it tends to become a pile of separate jobs.
Ops monitoring for the VPS
Heartbeat is good for “is anything on fire” style checks that should be quiet most of the time. A separate ops agent helps a lot here because you can lock down tools and keep the ops memory separate from your personal chat.
Pair this with our file and log automation guide if you want a deeper automation approach: OpenClaw file management automation.
Weekly report
Cron in an isolated session. Heavy summary work is exactly what you do not want in the main session every 30 minutes by accident.
A VPS checklist that makes heartbeat and cron behave
This part is not glamorous but it prevents most “why did it stop” tickets.
Keep the gateway running
On Linux a systemd service is the easiest way to keep OpenClaw alive across reboots. If you are hosting on LumaDock your VPS is already designed for long-running services and you can keep firewall rules tight while still exposing only what you need. If you want the OpenClaw-specific hosting context see OpenClaw VPS hosting now available.
Be strict about what can talk to your agent
Heartbeat and cron are proactive features which means they can message people while you are not watching. Use allowlists on chat platforms when you can and keep “public facing bot” agents on restricted tools.
We keep a longer security runbook here: OpenClaw security best practices.
Keep HEARTBEAT.md short
Heartbeat pulls context from the main session plus your checklist. If your checklist turns into a page of prose you pay for it every interval and you also get weird behavior because the agent tries to be helpful about vague tasks.
Ready-to-copy examples
HEARTBEAT.md for personal plus basic VPS checks
# HEARTBEAT.md
- VPS disk: run `df -h` and alert if any partition is above 85%.
- VPS memory: run `free -h` and alert if used is above 90%.
- Inbox: scan for urgent emails and draft replies when it is clearly needed.
- Calendar: check next 2 hours and remind me 15 min before events.
- If nothing needs attention reply HEARTBEAT_OK.
Two cron jobs that pair well with that heartbeat
openclaw cron add \
--name "Daily briefing" \
--cron "0 9 * * *" \
--session isolated \
--message "Daily briefing: calendar today, inbox urgent summary, VPS health." \
--announce \
--channel telegram \
--to "tg:123456789"
openclaw cron add \
--name "Weekly review" \
--cron "0 9 * * 1" \
--session isolated \
--message "Weekly review: summarize the past week and list open loops that still need action." \
--announce \
--channel telegram \
--to "tg:123456789"

