Cron Jobs & Heartbeats — Making OpenClaw Proactive
Fix cron jobs that never fire, messages that don't deliver, and heartbeats that interrupt your agent's work. Complete troubleshooting for proactive automation.
⚠️ The Problem
🔍 Why This Happens
✅ The Fix
## Step 1: Verify Cron is Enabled
First, check if the Gateway is running and cron is enabled:
openclaw gateway statusLook for 'cron: enabled' in the output. If cron is disabled, check your config:
cat ~/.openclaw/openclaw.json | grep -A5 cronMake sure you don't have OPENCLAW_SKIP_CRON=1 in your environment:
env | grep OPENCLAW## Step 2: List Current Cron Jobs
View all scheduled jobs and their status:
openclaw cron listJobs showing 'idle' with 'Last: -' have never run. Check that 'enabled' is true for each job.
## Step 3: Fix Message Delivery (Critical)
The most common issue is messages going to a 'system' channel instead of reaching you. For reliable delivery, use this proven configuration:
{ "sessionTarget": "isolated", "payload": { "kind": "agentTurn", "deliver": true, "message": "Respond with [your exact text]. Do not remain silent." }}Key settings explained:
- sessionTarget: 'isolated' — Runs in its own session, doesn't conflict with active conversations
- deliver: true — Explicitly tells the agent to send output to your channel
- Explicit message instruction — Tell the agent exactly what to say; vague instructions may result in silence
## Step 4: Create a Reliable Cron Job via CLI
Jobs created via chat sometimes have schema issues. Create directly via CLI for reliability:
openclaw cron add \ --name "daily-reminder" \ --schedule "0 9 * * *" \ --session isolated \ --channel telegram \ --message "Good morning! Here's your daily briefing."Or use the full JSON format:
openclaw cron add --json '{ "name": "daily-reminder", "schedule": "0 9 * * *", "enabled": true, "sessionTarget": "isolated", "payload": { "kind": "agentTurn", "deliver": true, "channel": "telegram", "message": "Send me a good morning message with today\'s priorities." }}'## Step 5: Main Session vs Isolated Session
Understanding the difference prevents most issues:
| Session Type | Requires Heartbeat | Conflicts with Active Chat | Best For |
|--------------|-------------------|---------------------------|----------|
| main | Yes | Yes—may skip if you're chatting | Context-aware tasks |
| isolated | No | No—runs independently | Reminders, scheduled messages |
If heartbeats are disabled, main session cron jobs will never run. Either:
- Enable heartbeats in config, or
- Use sessionTarget: 'isolated' for all cron jobs
## Step 6: Fix 'not-due' When Force-Running
If openclaw cron run --force still returns 'not-due':
# Check the job's next scheduled timeopenclaw cron list --verbose# Verify the schedule expression is validopenclaw cron validate "*/5 * * * *"# Try updating the job to run immediatelyopenclaw cron update daily-reminder --next-run now## Step 7: Prevent Heartbeats from Interrupting Work
If heartbeats are killing your subagent tasks:
Edit your HEARTBEAT.md to only say HEARTBEAT_OK as the absolute final step:
# Heartbeat Checklist1. Check memory/ for pending tasks2. Review subagent status (do NOT interrupt active ones)3. Only if no active work exists, consider proactive actions4. FINAL STEP (always last): HEARTBEAT_OKThe key insight: When HEARTBEAT_OK is delivered, it can interrupt current activity including subagents. Structure your heartbeat so HEARTBEAT_OK only happens when truly idle.
## Step 8: Debug Why a Specific Job Didn't Run
Check the logs for your job:
openclaw logs --follow | grep cronCommon log messages and meanings:
- cron job skipped: session busy — Active conversation blocked it; use isolated session
- cron job skipped: not due — Schedule hasn't triggered yet
- cron delivered to system — deliver: true was missing; message went nowhere
- cron job ok, duration: Xms — Job ran but check if delivery worked
🔥 Your AI should run your business, not just answer questions.
We'll show you how.$97/mo (going to $197 soon)
📋 Quick Commands
| Command | Description |
|---|---|
| openclaw gateway status | Check if Gateway is running and cron is enabled |
| openclaw cron list | Show all cron jobs with status and last run time |
| openclaw cron list --verbose | Show detailed cron info including next scheduled run |
| openclaw cron add --name X --schedule "CRON" --session isolated --message "Y" | Create a new cron job with isolated session |
| openclaw cron run JOBNAME --force | Force-run a cron job immediately regardless of schedule |
| openclaw cron update JOBNAME --enabled true | Enable a disabled cron job |
| openclaw cron delete JOBNAME | Remove a cron job |
| openclaw logs --follow | grep cron | Watch cron-related log entries in real-time |
Related Issues
📚 You Might Also Like
How to Use Claude API: Complete Beginner's Guide
Step-by-step guide to getting started with Anthropic's Claude API. From getting your API key to making your first call to building with OpenClaw.
AI Assistant for Writers
Beat the blank page
Notion
Your AI-powered Notion assistant. Query databases, create pages, automate meeting notes, manage projects, and build team wikis through natural conversation. Enterprise-ready workspace automation.
AI Automation — Let AI Take Action For You
Go beyond chatbots. OpenClaw is AI that actually does things—sends emails, schedules meetings, manages files, controls your smart home. Real automation, not just conversation.
🐙 Your AI should run your business.
Weekly live builds + template vault. We'll show you how to make AI actually work.$97/mo (going to $197 soon)
Join Vibe Combinator →