Building Proactive Agents with OpenClaw
Building Proactive Agents with OpenClaw
Most AI assistants are reactive. You ask, they answer. OpenClaw breaks that pattern. With heartbeats, cron jobs, and persistent memory, you can build agents that monitor, act, and report without waiting for a prompt.
This guide walks through the architecture of a proactive agent โ one that checks your email, watches for events, and reaches out when something matters.
The Three Pillars of Proactive Behavior
A proactive OpenClaw agent relies on three systems working together:
- Heartbeats โ periodic polling cycles where the agent checks for work
- Cron jobs โ precisely scheduled tasks that run in isolated sessions
- Memory โ persistent files that track state across sessions
Each serves a different purpose, and understanding when to use which is the key to building reliable automation.
Heartbeats: The Agent's Pulse
Heartbeats are periodic wake-up calls sent to the main session. When the agent receives one, it can check multiple things in a single turn โ email, calendar, notifications โ and decide whether to act or stay quiet.
How Heartbeats Work
OpenClaw sends a configurable heartbeat prompt at regular intervals. The agent reads HEARTBEAT.md from the workspace, follows its instructions, and either takes action or replies HEARTBEAT_OK to signal that nothing needs attention.
# HEARTBEAT.md
## Checks
- Email: scan inbox for urgent messages
- Calendar: flag events in the next 2 hours
- GitHub: check for failed CI runs
The agent processes each item, acts on anything urgent, and goes back to sleep.
When to Use Heartbeats
Heartbeats work best when:
- Multiple checks can batch together. One heartbeat turn can cover email, calendar, and notifications โ saving API calls compared to three separate cron jobs.
- You need conversational context. Heartbeats run in the main session, so the agent has access to recent chat history and full workspace context.
- Timing can be approximate. Heartbeats fire on a schedule (e.g., every 30 minutes), but they're not precise to the second.
State Tracking
Without state tracking, the agent checks the same things repeatedly and can't tell what's new. Use a simple JSON file:
{
"lastChecks": {
"email": 1703275200,
"calendar": 1703260800,
"github": null
}
}
Save this to memory/heartbeat-state.json. Each heartbeat cycle, the agent reads it, checks only what's due, and updates the timestamps.
Cron Jobs: Precision Scheduling
Where heartbeats are approximate and batched, cron jobs are exact and isolated. Each cron job runs in its own session with a specific task.
Creating a Cron Job
Use the cron tool to schedule recurring tasks:
cron add {
"name": "Morning Briefing",
"schedule": { "kind": "cron", "expr": "0 9 * * 1-5", "tz": "America/New_York" },
"payload": { "kind": "agentTurn", "message": "Generate today's briefing: check calendar, weather, and top emails. Send summary to the main session." },
"sessionTarget": "isolated",
"delivery": { "mode": "announce" }
}
This creates a job that runs at 9 AM Eastern on weekdays, in an isolated session, and delivers the result back to the user's chat.
Cron vs. Heartbeat: Decision Framework
| Factor | Heartbeat | Cron | |--------|-----------|------| | Timing precision | Approximate | Exact | | Session context | Full main session | Isolated | | Multiple checks per cycle | Yes | One task per job | | Model override | No (uses main model) | Yes (per-job) | | Cost efficiency | Higher (batched) | Lower per-task flexibility |
Rule of thumb: Use heartbeats for monitoring and triage. Use cron for scheduled deliverables.
One-Shot Reminders
Cron isn't just for recurring tasks. Use the at schedule for one-time triggers:
cron add {
"name": "Meeting Prep Reminder",
"schedule": { "kind": "at", "at": "2026-02-19T14:30:00-05:00" },
"payload": { "kind": "systemEvent", "text": "Reminder: your strategy meeting starts in 30 minutes. Review the deck." },
"sessionTarget": "main"
}
This injects a system event into the main session at exactly 2:30 PM. The agent processes it like any other message and can take action.
Memory: The Continuity Layer
Proactive agents need to remember what they've done. Without memory, every heartbeat is a blank slate.
Daily Logs
Write observations and actions to memory/YYYY-MM-DD.md:
# 2026-02-19
## 09:00 โ Morning Briefing
- 3 calendar events today
- 12 unread emails (2 flagged urgent)
- Weather: 45ยฐF, rain expected after 3 PM
## 09:15 โ Email Triage
- Replied to client inquiry (ticket #4521)
- Flagged invoice from vendor for review
Long-Term Memory
Periodically (during quiet heartbeats), the agent reviews daily logs and distills insights into MEMORY.md:
## Client Patterns
- Client X typically emails Monday mornings with urgent requests
- Vendor invoices arrive on the 15th โ auto-flag for review
## Operational Notes
- GitHub CI fails most often on dependency updates (Tuesdays)
- Calendar sync lag: ~5 min delay between Google Calendar and local cache
This curated memory informs future decisions. The agent learns that Monday mornings need extra email vigilance, or that Tuesday CI failures are usually benign.
Memory Search
Use memory_search to semantically query across all memory files:
memory_search { "query": "client X payment history" }
This returns relevant snippets with file paths and line numbers โ useful when the agent needs to reference past context before taking action.
Putting It All Together: A Proactive Workflow
Here's a complete example โ an agent that monitors a project and reports daily:
1. HEARTBEAT.md
# Checks
- GitHub: new issues or failed CI in the last 30 minutes
- Email: urgent messages from project stakeholders
- If anything found: summarize and send via iMessage
2. Cron: Daily Report
cron add {
"name": "Daily Project Report",
"schedule": { "kind": "cron", "expr": "0 17 * * 1-5", "tz": "America/New_York" },
"payload": {
"kind": "agentTurn",
"message": "Generate end-of-day report: summarize today's GitHub activity, emails handled, and open issues. Write to memory/YYYY-MM-DD.md and send summary to main session."
},
"sessionTarget": "isolated",
"delivery": { "mode": "announce" }
}
3. State File
{
"lastChecks": {
"github": 1771516800,
"email": 1771516800
},
"dailyReportSent": true
}
4. Memory Update
During a quiet heartbeat, the agent reviews the week's daily logs and updates MEMORY.md with patterns:
"CI failures spiked on Wednesday โ all related to the Node 25 upgrade. Resolved by Thursday. Client feedback on the new dashboard was positive โ 3 of 4 stakeholders approved."
Best Practices
Don't over-schedule. More cron jobs means more API calls and more cost. Batch related checks into heartbeats when precision isn't critical.
Respect quiet hours. A proactive agent that messages at 3 AM is worse than a reactive one. Check the time before sending notifications, and configure your heartbeat to stay silent during off-hours.
Track what you've done. Without state files, the agent will re-check and re-notify about the same things. Always update heartbeat-state.json after each cycle.
Use isolated sessions for heavy work. Cron jobs with sessionTarget: "isolated" don't pollute the main session's context window. Use them for tasks that generate long outputs or require different models.
Let the agent learn. The memory layer isn't just a log โ it's a feedback loop. When the agent notices patterns (e.g., recurring failures on Tuesdays), it should update MEMORY.md so future decisions are better informed.
Conclusion
Proactive agents are the real unlock in OpenClaw. Reactive assistants answer questions. Proactive agents anticipate needs, monitor systems, and surface what matters โ all without being asked. The combination of heartbeats for monitoring, cron for precision, and memory for continuity creates agents that genuinely work alongside you, not just for you.
Start small. Add one heartbeat check. Schedule one daily briefing. Build the state file. Then iterate. The agent gets smarter as its memory grows.
Enjoyed this article?
Join the ClawMakers community to discuss this and more with fellow builders.
Join on Skool โ It's Free โ