In this chapter, your agent stops waiting for you and starts acting on its own schedule.
By the end, you should be able to write a HEARTBEAT.md checklist, create a cron job for precise-time delivery, and explain why one heartbeat with five checklist items costs 80% less than five separate cron jobs. You will also learn HEARTBEAT_OK suppression (how the agent stays silent when nothing needs attention) and quiet hours (how to prevent 3 AM messages).
This is the line. Everything before this chapter was a chatbot with features. After this chapter, it is a Personal AI Employee.
James scrolled through his WhatsApp. Every message from his agent was a reply to something he had asked. "It never starts a conversation," he said. "I always go first."
"Two mechanisms change that." Emma held up one finger. "First: a heartbeat. The gateway has a built-in timer. Every thirty minutes, it wakes your agent and hands it a checklist you wrote. The agent reads the checklist, decides whether anything needs attention, and either acts or replies with a single token: HEARTBEAT_OK. When the gateway sees that token, it drops the message silently. Nothing hits your phone. One wake-up, many checks, silence when nothing matters."
"Like the shift walkthrough," James said. "At my old warehouse, the floor supervisor walked every aisle once per hour. One person, twelve aisles, one trip. If everything looked fine, no radio call. If a pallet was misplaced, he called it in."
Emma held up a second finger. "Second: a cron job. A cron fires at an exact time you specify. Not 'sometime in the next thirty minutes.' Exactly 9:00 AM. You use it when delivery must happen at a specific moment: a daily summary, a Monday morning report, a reminder before a meeting."
"Heartbeats are periodic awareness. Crons are precise delivery."
"Good. Now list five things you want automated."
James typed: check for new leads, send booking confirmations, follow up on cold contacts, deliver a daily summary, remind me about upcoming meetings. "Five cron jobs?"
"How many of those need exact timing?"
James looked at his list. "The daily summary. Nine AM." He paused. "One."
"And the rest?"
"Checklist items. The heartbeat picks them up on its next pass."
"Calculate it. Five separate cron jobs at 30-minute intervals: how many agent turns per day?"
James counted. Five jobs, every 30 minutes, 24 hours. "Two hundred forty."
"One heartbeat with four checklist items, plus one cron for the daily summary."
"Forty-eight heartbeat turns plus two for the cron." He stared at the numbers. "Fifty versus two hundred forty. That is an 80% reduction."
"One heartbeat. One cron." Emma stood up. "Go build it."
You are doing exactly what James is doing. Five scheduled tasks sounds like five separate cron jobs, until you understand the two mechanisms and do the math.
Your agent has skills, MCP connections, and browser access. It does everything you ask. But it still waits for you to ask. This chapter changes that. You will enable heartbeats (periodic self-checks that batch multiple items into one agent turn) and cron jobs (precisely timed tasks that fire at exact moments), learn the Agent OS mental model that ties the platform together, and understand the cost math that determines which mechanism to use.
Your workspace already has a HEARTBEAT.md file. By default it is empty (just comments), which means heartbeat runs are skipped entirely: no API call, no tokens spent. You activate heartbeats by adding checklist items.
Send this message on WhatsApp:
Your agent updates the file. Always verify what was actually written:
Compare what you asked for with what the agent wrote. Agents sometimes rewrite or simplify your instructions. If a checklist item is missing, ask the agent to add it back.
Notice the last line says "always send a status report." This means every heartbeat will produce a message. That is intentional for now. You will see a lot of messages during testing. Later in this chapter, you will learn about HEARTBEAT_OK suppression, which silences heartbeats that have nothing to report. But first, you need to see heartbeats working.
Why WhatsApp for this step?
The agent can read and write its own workspace files through normal conversation. You told it WHAT to check. The next step (routing heartbeat delivery) is gateway infrastructure that you control from the terminal, not the agent.
The moment you added checklist items to HEARTBEAT.md, heartbeats started running. The gateway fires them at the default 30-minute interval. But their output goes nowhere: the delivery target defaults to none, so the agent checks the checklist, replies, and the gateway drops the response silently.
Now you make them visible. First, send any message to your agent on WhatsApp so the chat is active. Then open your terminal:
Two settings and a restart:
Why target: last instead of a specific number?
You can also use target whatsapp with a to number to route heartbeats to a specific WhatsApp recipient. But target: last is simpler for getting started: no phone number to look up, no quoting issues, no risk of typos. If you need heartbeats routed to a specific number regardless of which chat was last active, use target whatsapp with the to flag:
Note the quoting: single quotes around double quotes. Phone numbers start with +, which the config parser interprets as a positive number unless you force it to be a string. The to number must be the number you chat FROM (the other phone), not the number your agent's WhatsApp is registered on.
This split is deliberate. The agent controls WHAT to check (HEARTBEAT.md). The operator controls HOW OFTEN and WHERE (gateway config). You will see this same separation throughout OpenClaw: agents own their content, operators own the infrastructure.
The Activation Dance
Heartbeats follow the same layered activation pattern you learned in Module 9.1, Chapter 2:
Restart the gateway after changing config.
Open your WhatsApp and wait. With a 1-minute interval, a message should arrive within a minute or two. Because your HEARTBEAT.md says "always send a status report," the agent will message you every single heartbeat cycle, even when nothing needs attention.
Read the message. It should be a brief status based on your checklist items. If a second message arrives a minute later, your heartbeats are working.
If no message arrives after two minutes, something is wrong. Debug in this order:
Step 1: Check the channel. Run openclaw channels status --probe. You should see WhatsApp default: enabled, configured, linked, running, connected. If any of those words are missing, your WhatsApp channel is not ready. The gateway may be reconnecting: WhatsApp connections drop periodically, and the gateway auto-restarts them.
Step 2: Check the logs. The gateway log at ~/.openclaw/logs/gateway.log tells you exactly what happened. Look for [heartbeat] entries. The most common failure is channel not ready, meaning the heartbeat fired while WhatsApp was reconnecting. Wait for the channel to reconnect and the next heartbeat will deliver.
Step 3: Check the dashboard. If the dashboard shows heartbeat activity (the agent responded) but nothing arrived on WhatsApp, the heartbeat ran but delivery failed. Check that target is set correctly and that you messaged the agent on WhatsApp recently (so it is the "last" channel).
You will notice a problem quickly: every heartbeat sends a message. At 1-minute intervals, your phone buzzes constantly. At the production interval of 30 minutes, that is 48 messages per day, most of them saying "nothing to report." This is why HEARTBEAT_OK suppression exists.
At whatever interval you configured (1 minute for testing, 30 minutes for production), the gateway wakes your agent. Not because someone sent a message. Not because an event fired. Because the timer fired. The agent reads its HEARTBEAT.md checklist, decides whether anything needs attention, and either acts or goes back to sleep.
When a heartbeat fires, the gateway loads HEARTBEAT.md from the agent's workspace into the system prompt. This file contains the agent's checklist: what to check, what to monitor, what to follow up on.
You just saw the problem: every heartbeat sends a message, even when nothing needs attention. The fix is a special token called HEARTBEAT_OK.
Update your HEARTBEAT.md from WhatsApp:
Verify the update:
Make sure the file includes the exact text HEARTBEAT_OK. Agents sometimes paraphrase instructions. If the agent wrote something like "reply that everything is okay" instead of the literal token, ask it to fix it: the gateway matches the exact string HEARTBEAT_OK, not the intent.
Now wait for the next heartbeat. If nothing needs attention, your WhatsApp stays silent. Here is why:
The gateway scans the agent's response for the HEARTBEAT_OK token at the start or end. When it finds the token, it strips it out and checks the remaining content. If what is left is 300 characters or fewer (configurable via ackMaxChars), the entire message is dropped. No delivery to any channel. No notification on your phone.
This is the silent heartbeat. The agent checked in, found nothing, and went back to sleep. Silent heartbeats are not wasted computation. They are proof that the agent is alive, watching, and has nothing to report.
When the agent does find something that needs attention, it replies with the alert text and omits the HEARTBEAT_OK token entirely. The gateway sees no acknowledgment token, treats the response as an alert, and delivers it to the configured target channel.
Switch to Production Interval
Now that suppression is working, switch from the 1-minute test interval to a production interval before you forget:
The Default State Is Free
Your HEARTBEAT.md shipped empty (just comments and headers). In this state, OpenClaw skips the heartbeat run entirely: no API call, no tokens spent. Heartbeats become active the moment you add real checklist items. To deactivate heartbeats without changing the gateway config, clear your checklist back to comments only.
Heartbeats are for periodic awareness: "check if anything needs attention." Cron jobs are for precise timing: "do this specific thing at this specific time."
The distinction matters:
Your agent has a built-in cron tool. Before using it, ask your agent what it does. On WhatsApp:
The agent will explain that it schedules tasks to run at specific times or intervals, independent of your current chat. Now that you know the tool exists and what it does, use it:
The key phrase is "Use the cron schedule tasks tool." Without it, the agent may reach for Unix crontab or other system tools instead of the OpenClaw cron system. In testing, a generic prompt like "create a cron job" caused the agent to create a Unix crontab entry with a bash script that never reached WhatsApp. Naming the tool explicitly fixed it.
Verify the job was created by checking the dashboard Cron Jobs page, or ask on WhatsApp:
There are three types of cron schedules you can ask for:
If WhatsApp creation does not work, you can create cron jobs from the terminal using openclaw cron add. Run openclaw cron add --help to see all available flags.
When creating cron jobs via WhatsApp, how you ask determines which tool the agent uses:
In testing, vague prompts caused the agent to create Unix crontab entries with bash scripts that echoed text to stdout and never reached WhatsApp. The agent understood the intent but picked the wrong system. Naming the tool explicitly ("Use the cron schedule tasks tool") fixed it every time.
Always verify the result. Check the dashboard Cron Jobs page or ask: "List my cron jobs." If the job does not appear, the agent used the wrong tool. Clean up and try again with an explicit tool reference, or use the terminal.
You can manage cron jobs entirely from WhatsApp:
You can also check the dashboard Cron Jobs page for a visual view of all active jobs, their schedules, and run history. The dashboard is the quickest way to verify whether a job was created correctly and whether it has fired.
For terminal management, openclaw cron list, openclaw cron edit, and openclaw cron remove provide direct control. Run openclaw cron --help for the full command set.
This is not abstract. It directly affects your API bill.
5 cron jobs at 30-minute intervals:
1 heartbeat with 5 checklist items:
Same work. 80% fewer API calls. Use heartbeats for batched periodic checks. Use crons only when exact timing matters and the task cannot be batched.
An agent that messages customers at 3 AM is not a feature. It is a compliance violation and a lost customer. Quiet hours must be enforced at two levels:
Include timing constraints directly in the heartbeat checklist:
The agent reads these instructions and should follow them. But "should" is not "will." Prompt-level enforcement depends on the model obeying the instruction.
Outside the active window, heartbeats do not run. No model call. No token cost. No risk of a message being sent. The gateway skips the heartbeat entirely.
Use both. The activeHours config prevents heartbeats outside business hours at the infrastructure level. The HEARTBEAT.md instructions add a second layer of protection at the prompt level. If either layer fails, the other catches it.
This is a pattern you will see again in Module 9.1, Chapter 13 (hooks and security tiers): defense in depth means multiple layers, each independently sufficient, so that a single failure does not cascade.
Step back and look at what you have assembled across Module 9.1, Chapters 1 through 7. This is not a chatbot. It is an operating system.
This mapping is not decorative. When something breaks, the table tells you where to look. Agent not responding? Check the gateway (kernel). Wrong personality? Check SOUL.md (file system). Tool missing? Check plugins (device drivers). Once you think "operating system" instead of "chatbot framework," you stop being surprised and start diagnosing.
The body used a generic checklist. Now make one that is useful for YOUR work. Ask your agent on WhatsApp:
Review the suggestions. Edit them. Then ask:
Verify the file and wait for the next heartbeat. Is the report more relevant than the generic one?
What you are learning: A heartbeat is only as useful as its checklist. Generic checks produce generic reports. A checklist tailored to your work produces actionable alerts.
Create something you will actually keep. On WhatsApp:
Check the dashboard Cron Jobs page to verify it was created. If the job does not appear, the agent used the wrong tool. Try again with the explicit tool name.
Then schedule a one-shot reminder for something real:
What you are learning: The difference between recurring crons (daily briefing) and one-shot crons (reminders). Both are created from WhatsApp by naming the tool explicitly. The dashboard confirms what was actually created.
You have five tasks you want automated. Send this list to your agent on WhatsApp:
Compare the agent's answer with your own judgment. Items 1, 3, and 5 are periodic checks (heartbeat). Item 2 needs exact timing (cron). Item 4 needs exact timing relative to events (cron). Did the agent agree?
What you are learning: The decision framework for heartbeat vs. cron. Periodic awareness goes in the heartbeat checklist. Precise timing gets its own cron job. Your agent can help you classify, but you make the final call.
Heartbeats are periodic checks (every 30 minutes by default). One wake-up, many checklist items, silence when nothing matters. Cron jobs fire at exact times (9:00 AM, Monday at 8:00 AM). Use heartbeats for "check if anything needs attention." Use crons for "deliver this at exactly this time."
One heartbeat checking five items: 48 agent turns per day. Five separate cron jobs doing the same work: 240 turns per day. The heartbeat approach costs 80% less because it batches work into one wake-up cycle.
When the agent checks the heartbeat list and finds nothing to report, it responds with HEARTBEAT_OK. The gateway sees this token and drops the message silently. Nothing reaches your phone. This is how your agent stays alive without generating noise.
Configure activeHours to prevent agent activity during off-hours. Enforce at both the infrastructure level (config) and the prompt level (HEARTBEAT.md instructions). Defense in depth: the model might ignore prompt instructions, but it cannot override the config.
James looked at his phone. A message had arrived from his agent, unprompted. A brief status update, relevant, well-timed, and nothing he had asked for.
"It just... did something on its own."
"That is the line. Everything before this chapter was a chatbot with features. From here on, it is a Personal AI Employee."
"I set up one heartbeat and one cron. The heartbeat handles the routine checks. The cron handles the daily summary at 9 AM." He paused. "I almost built five cron jobs. At my old warehouse, we ran five separate daily reports until the floor manager bundled them into one morning briefing. Same information, one fifth the paperwork."
Emma nodded. "The 80% number would have caught up with you. But the bigger thing is what just happened." She gestured at his phone. "You did not ask it to do that. It decided."
She leaned back. "We covered what you need to get heartbeats and crons working. But there is more under the surface when you are ready. Two flags called lightContext and isolatedSession cut heartbeat token costs by 95%. System events let external webhooks wake your agent immediately instead of waiting for the next heartbeat tick. Each agent can have its own heartbeat config, which matters the moment you add a second agent. And cron jobs can POST results to a webhook instead of a chat channel." She paused. "You do not need any of that today. But when your heartbeats are running smoothly, explore the automation docs. There is a layer below the one we just worked on."
James picked up his phone. "The message is text. Half my old warehouse crew never read text messages. They listened to voice notes while driving forklifts."
"Module 9.1, Chapter 9. Two config lines and a plugin enable."