OpenClaw Automation: Cron Jobs, Heartbeats, and Webhooks Explained
Most AI assistants are reactive. You send a message, they respond. OpenClaw can be proactive. It can wake up on a schedule, check for things that need attention, and message you without prompting. This guide covers the three automation primitives: cron jobs, heartbeats, and webhooks.
The Three Automation Modes
Cron Jobs
- What: Schedule specific tasks to run at exact times
- When: "Every Monday at 9am, summarize last week's GitHub activity"
- Use for: Time-based tasks with precise schedules
Heartbeats
- What: Periodic check-ins during active hours
- When: "Every 2 hours, check if there's anything I should know"
- Use for: Monitoring, batching multiple checks into one turn
Webhooks
- What: React to external events in real-time
- When: "When a GitHub PR is opened, review it and comment"
- Use for: Event-driven workflows (CI/CD, GitHub, email, APIs)
Heartbeats: The Proactive Assistant
Heartbeats are periodic check-ins. Think of them like a pulse. Your assistant wakes up, reads HEARTBEAT.md, and executes tasks.
Configuration
Edit ~/.openclaw/openclaw.json:
{
"agents": {
"defaults": {
"heartbeat": {
"every": "30m",
"activeHours": {
"start": "08:00",
"end": "23:00",
"timezone": "America/Chicago"
},
"model": "anthropic/claude-sonnet-4-5",
"target": "telegram"
}
}
}
}
Fields:
every— how often to wake up (e.g.,30m,1h,2h)activeHours— only run during these hoursmodel— which model to use (can be different from main)target— which channel to send messages to (telegram, discord, etc.)
HEARTBEAT.md
This file tells your assistant what to do on each heartbeat:
# HEARTBEAT.md
Read this file if it exists (workspace context). Follow it strictly.
Do not infer or repeat old tasks from prior chats. If nothing needs attention, reply HEARTBEAT_OK.
## Tasks (rotate through these)
### Email Check (every 2-4 hours)
- Last checked: [track in memory/heartbeat-state.json]
- Run: `himalaya list --folder INBOX --filter unseen`
- If urgent emails, summarize and notify
- Otherwise: HEARTBEAT_OK
### Calendar Check (morning and evening)
- Check for events in next 24 hours
- If meetings coming up, remind me
- Otherwise: HEARTBEAT_OK
### GitHub Notifications (once per day)
- Check unread notifications
- Summarize mentions, assigned issues, PR reviews needed
- Otherwise: HEARTBEAT_OK
How it works:
HEARTBEAT_OK (silent, no message sent)Tracking State
To avoid checking the same thing repeatedly, track state in a JSON file:
memory/heartbeat-state.json:
{
"lastChecks": {
"email": 1709567200,
"calendar": 1709563600,
"github": 1709563600
}
}
In HEARTBEAT.md:
## Email Check
- Read memory/heartbeat-state.json
- If email was checked less than 2 hours ago, skip
- Otherwise, check and update lastChecks.email
Silent vs Noisy Heartbeats
Silent:
HEARTBEAT_OK
No message sent. Used when nothing needs attention.
Noisy:
You have 3 unread emails:
1. Boss: Q1 budget review
2. HR: Benefits enrollment
3. [Newsletter]: AI news roundup
Message sent to your configured target channel.
Cron Jobs: Precise Scheduling
Cron jobs run at exact times. Use when heartbeats are too vague.
Creating a Cron Job
openclaw cron add \
--name "weekly-github-summary" \
--schedule "0 9 * * MON" \
--message "Summarize GitHub activity from last week. Include: PRs merged, issues closed, commits by author. Post to Slack #engineering."
Schedule format (cron syntax):
* * * * *
│ │ │ │ │
│ │ │ │ └── Day of week (0-7, 0 and 7 = Sunday)
│ │ │ └────── Month (1-12)
│ │ └──────────── Day of month (1-31)
│ └────────────────── Hour (0-23)
└──────────────────────── Minute (0-59)
Examples:
0 9 * * *— Every day at 9:00 AM0 9 * * MON— Every Monday at 9:00 AM*/15 * * * *— Every 15 minutes0 0 1 * *— First day of every month at midnight
List Cron Jobs
openclaw cron list
Example output:
ID: b0634783-c58d-4ecb-8564-6ad94c7b7ccb
Name: weekly-github-summary
Schedule: 0 9 * * MON
Next run: 2026-03-10 09:00:00
Enabled: true
View Cron Runs
openclaw cron runs --name weekly-github-summary
Shows past executions, results, and any errors.
Edit a Cron Job
openclaw cron edit b0634783 --schedule "0 10 * * MON"
Delete a Cron Job
openclaw cron delete b0634783
Cron vs Heartbeat: When to Use Each
Use cron when:
- Exact timing matters ("9:00 AM sharp")
- One-shot reminders ("remind me in 20 minutes")
- Isolated tasks (no conversational context needed)
- Different model or thinking level
- Timing can drift slightly ("every ~30 minutes")
- Multiple checks should batch together
- Conversational context from main session is useful
- You want to reduce API calls by combining checks
Webhooks: Event-Driven Automation
Webhooks let external services trigger OpenClaw actions.
Enable Webhooks
Edit ~/.openclaw/openclaw.json:
{
"webhooks": {
"enabled": true,
"port": 18790,
"secret": "your-webhook-secret"
}
}
Restart the gateway:
openclaw gateway restart
Create a Webhook
openclaw webhooks add \
--name "github-pr-opened" \
--path "/webhooks/github/pr" \
--action "Review the PR and comment with feedback. Use gh CLI."
This creates an endpoint:
http://127.0.0.1:18790/webhooks/github/pr
Configure GitHub Webhook
https://your-domain.com/webhooks/github/prapplication/jsonyour-webhook-secretNote: Use Tailscale Funnel or a reverse proxy to expose the webhook endpoint securely.
Webhook Payload
When GitHub sends a webhook, OpenClaw:
List Webhooks
openclaw webhooks list
View Webhook Logs
openclaw webhooks logs --name github-pr-opened
Example Workflows
Morning Briefing
Cron job:
openclaw cron add \
--name "morning-briefing" \
--schedule "0 8 * * MON-FRI" \
--message "Morning briefing: summarize unread emails (himalaya), today's calendar events, and GitHub notifications. Send to Telegram."
What happens:
Every weekday at 8:00 AM, you get a Telegram message with:
- Unread emails
- Today's meetings
- GitHub activity
CI/CD Pipeline Monitor
Webhook:
openclaw webhooks add \
--name "ci-failure" \
--path "/webhooks/ci/failure" \
--action "A CI pipeline failed. Analyze the logs and suggest a fix. Post to Slack #engineering."
Configure your CI tool (GitHub Actions, GitLab CI, Jenkins) to POST to this webhook when a build fails.
Result:
Your assistant analyzes the failure, suggests a fix, and posts to Slack automatically.
Weekly Standup Report
Cron job:
openclaw cron add \
--name "weekly-standup" \
--schedule "0 16 * * FRI" \
--message "Generate a weekly standup report: commits, PRs, issues closed. Format as markdown. Post to Slack #standup."
Email-Triggered Tasks
Heartbeat + Email Parsing:
In HEARTBEAT.md:
## Email Check
- Check for emails with subject: [ACTION NEEDED]
- If found:
- Parse the email body
- Execute the requested action (e.g., deploy, run script)
- Reply confirming completion
Security Considerations
Heartbeats
- Run in the main session (trusted context)
- Have full tool access
- Risk: If HEARTBEAT.md is compromised, malicious tasks could run
- Mitigation: Keep HEARTBEAT.md in version control, review changes
Cron Jobs
- Isolated sessions (separate from main)
- Can specify different model or tool policy
- Risk: Scheduled tasks run without user confirmation
- Mitigation: Test tasks manually first, review cron logs regularly
Webhooks
- Exposed to the internet (if using Tailscale Funnel or reverse proxy)
- Risk: Malicious webhooks could trigger unintended actions
- Mitigation:
Troubleshooting
Heartbeat Not Running
Check the config:
openclaw config get agents.defaults.heartbeat
Verify active hours match your timezone:
date +%Z
Check logs:
openclaw logs --tail 50 | grep heartbeat
Cron Job Not Executing
List cron jobs:
openclaw cron list
Check if it's enabled and the schedule is correct.
View runs:
openclaw cron runs --name <name>
Webhook Not Responding
Verify the endpoint is reachable:
curl -X POST http://127.0.0.1:18790/webhooks/test \
-H "Content-Type: application/json" \
-d '{"test": "payload"}'
Check webhook logs:
openclaw webhooks logs --name <name>
Best Practices
Conclusion
Automation transforms your assistant from a reactive chatbot into a proactive team member. Heartbeats for periodic monitoring, cron for precise scheduling, webhooks for event-driven workflows. Combined, they enable truly autonomous AI.
Set it and forget it. 🦞