Browse guides
Back to Guides
IntermediateConfigurationOpenClaw

Heartbeat & Cron Job Configuration

Understand OpenClaw's heartbeat system: optimize it for cost and performance, configure active hours, set up cron jobs, and monitor autonomous behavior.

Sam Okafor25 minutes

#What Is the Heartbeat?

The heartbeat is OpenClaw's internal clock, a periodic cycle where the agent "wakes up" and thinks about what it should be doing. During each heartbeat, the agent:

  1. Checks for pending tasks: reminders, scheduled actions, follow-ups
  2. Evaluates its environment: new emails, calendar events, system status
  3. Processes background skills: skills that run on a schedule rather than on demand
  4. Maintains awareness: the agent reflects on recent interactions and plans ahead

Think of it as the agent's autonomous thinking cycle. Without the heartbeat, your agent only responds when spoken to. With it, the agent proactively checks things, sends reminders, and stays aware of its surroundings.

The heartbeat is what makes OpenClaw an autonomous agent rather than a simple chatbot. It allows proactive behavior, the agent can message you unprompted when it has something important to share.


#Default Configuration and Cost Implications

By default, the heartbeat fires every 10 minutes using whatever model is configured as default. This has significant cost implications.

#The Cost Problem

Each heartbeat cycle sends a prompt to your LLM provider. Let's do the math:

IntervalCycles/DayUsing Opus 4.6 (~$0.05/cycle)Using Sonnet 4.6 (~$0.01/cycle)Using Haiku 4 (~$0.003/cycle)
5 min288$14.40/day$2.88/day$0.86/day
10 min144$7.20/day$1.44/day$0.43/day
15 min96$4.80/day$0.96/day$0.29/day
30 min48$2.40/day$0.48/day$0.14/day
60 min24$1.20/day$0.24/day$0.07/day

The default 10-minute heartbeat with Claude Opus 4.6 costs approximately $216/month in API calls alone, just for the heartbeat, before any user interactions. This is the most common surprise expense for new OpenClaw users.

For most users, the optimal heartbeat configuration is:

json
{
"heartbeat": {
"enabled": true,
"interval_minutes": 15,
"model": "claude-haiku-4-20260210",
"max_tokens": 1024,
"active_hours": {
"start": "08:00",
"end": "23:00",
"timezone": "America/New_York"
},
"sleep_interval_minutes": 60
}
}

This configuration:

  • Uses Claude Haiku 4 for heartbeats (cheap but capable)
  • Runs every 15 minutes during active hours
  • Slows to every 60 minutes during sleep hours
  • Costs approximately $5-8/month

#Configuring the Heartbeat

#Basic Heartbeat Settings

Edit ~/.openclaw/openclaw.json. There is no openclaw config edit; openclaw config file "Prints the active config file path" so you open the right one, and openclaw config set <key> <value> changes a single key without an editor at all.

$openclaw config file
json
{
"heartbeat": {
"enabled": true,
"interval_minutes": 15,
"model": "claude-haiku-4-20260210"
}
}

#Heartbeat Model Selection

The heartbeat does not need your most powerful model. Its job is to:

  • Check if reminders are due
  • Scan for new events
  • Decide if anything needs attention
  • Escalate to the full model only when necessary

Claude Haiku 4 is ideal for this because it is:

  • Fast (responds in under 1 second)
  • Cheap ($1/1M input tokens vs $15/1M for Opus)
  • Capable enough for triage and simple decisions

If the heartbeat detects something that needs deeper reasoning, it triggers a full processing cycle using your default model (e.g., Sonnet 4.6).

#Escalation Configuration

json
{
"heartbeat": {
"model": "claude-haiku-4-20260210",
"escalation_model": "claude-sonnet-4-6-20260217",
"escalate_on": [
"pending_reminder",
"new_email_important",
"calendar_event_soon",
"skill_alert",
"user_mentioned"
]
}
}

#Active Hours

Active hours define when your agent is most responsive. During active hours, the heartbeat runs at the configured interval. Outside active hours (sleep period), it runs at a slower rate.

#Configuration

json
{
"heartbeat": {
"active_hours": {
"start": "07:00",
"end": "23:00",
"timezone": "America/Los_Angeles",
"days": ["mon", "tue", "wed", "thu", "fri", "sat", "sun"]
},
"interval_minutes": 15,
"sleep_interval_minutes": 60
}
}

#Day-Specific Schedules

You can set different schedules for different days:

json
{
"heartbeat": {
"schedules": [
{
"days": ["mon", "tue", "wed", "thu", "fri"],
"start": "07:00",
"end": "22:00",
"interval_minutes": 10
},
{
"days": ["sat", "sun"],
"start": "09:00",
"end": "23:00",
"interval_minutes": 30
}
],
"sleep_interval_minutes": 120,
"timezone": "America/New_York"
}
}

This runs more frequent heartbeats on weekdays (every 10 minutes from 7 AM to 10 PM) and less frequent on weekends (every 30 minutes from 9 AM to 11 PM).

Active hours do not affect your ability to message the agent. You can always send a message at any time, and the agent will respond. Active hours only control the autonomous heartbeat frequency.


#Disabling the Heartbeat

If you want a purely reactive agent (only responds when messaged), disable the heartbeat:

json
{
"heartbeat": {
"enabled": false
}
}

This eliminates heartbeat API costs entirely. The trade-off is that your agent will not:

  • Send proactive reminders
  • Check for new emails or events autonomously
  • Execute time-based skills
  • Run cron jobs (cron jobs depend on the heartbeat)

#Cron Jobs

Cron jobs let you schedule specific tasks to run at defined times. They are more targeted than the general heartbeat, each cron job has a specific task with a specific schedule.

#Adding a Cron Job via CLI

$openclaw cron add "Summarize my unread emails" --schedule "0 8 * * *" --model claude-sonnet-4-6-20260217

This creates a cron job that runs every day at 8:00 AM, summarizing unread emails using Sonnet 4.

#Cron Schedule Syntax

OpenClaw uses standard cron syntax:

┌───────── minute (0-59)
│ ┌─────── hour (0-23)
│ │ ┌───── day of month (1-31)
│ │ │ ┌─── month (1-12)
│ │ │ │ ┌─ day of week (0-6, Sunday=0)
│ │ │ │ │
* * * * *

Common schedules:

ScheduleCron ExpressionDescription
Every morning at 8 AM0 8 * * *Daily morning brief
Every hour0 * * * *Hourly check-in
Weekdays at 9 AM0 9 * * 1-5Workday morning
Sunday at 7 PM0 19 * * 0Weekly review
Every 30 minutes*/30 * * * *Frequent monitoring
First of month at noon0 12 1 * *Monthly report

#Managing Cron Jobs

List all cron jobs:

$openclaw cron list

Output:

ID Schedule Model Task
1 0 8 * * * sonnet-4.6 Summarize my unread emails
2 0 9 * * 1-5 haiku-4 Check my calendar and tell me what's happening today
3 0 20 * * 0 sonnet-4.6 Write a weekly summary of what we accomplished
4 */30 * * * * haiku-4 Check if any important emails arrived

Remove a cron job:

$openclaw cron remove 3

Pause a cron job: there is no cron pause or cron resume. Pausing and resuming are disable and enable, and the docs say to "Use openclaw automations enable <job-id> to resume scheduled runs."

$openclaw cron disable 4

Resume a paused cron job:

$openclaw cron enable 4

#Cron Job Configuration in JSON

You can also define cron jobs directly in openclaw.json:

json
{
"cron": {
"jobs": [
{
"id": 1,
"task": "Summarize my unread emails and send the summary to me",
"schedule": "0 8 * * *",
"model": "claude-sonnet-4-6-20260217",
"channel": "telegram",
"enabled": true
},
{
"id": 2,
"task": "Check my calendar and brief me on today's events",
"schedule": "0 9 * * 1-5",
"model": "claude-haiku-4-20260210",
"channel": "telegram",
"enabled": true
},
{
"id": 3,
"task": "Scan Hacker News for AI-related stories and send me the top 5",
"schedule": "0 12 * * *",
"model": "claude-sonnet-4-6-20260217",
"channel": "discord",
"enabled": true
}
],
"timezone": "America/New_York",
"max_concurrent": 2,
"retry_on_failure": true,
"retry_delay_minutes": 5
}
}

#Example Cron Job Workflows

#Morning Briefing

Schedule: 0 7 * * * (7:00 AM daily)
Model: claude-sonnet-4-6-20260217
Task: "Good morning! Check my calendar for today's events, summarize
any important unread emails from overnight, check the weather forecast,
and give me a brief summary of top tech news. Keep it concise."

#End-of-Day Review

Schedule: 0 18 * * 1-5 (6:00 PM weekdays)
Model: claude-sonnet-4-6-20260217
Task: "Wrap up my day. Tell me what tasks I completed today,
what's still pending, and what's on my calendar for tomorrow."

#Weekly Planning

Schedule: 0 20 * * 0 (8:00 PM Sundays)
Model: claude-opus-4-6-20260217
Task: "It's Sunday evening. Review everything we discussed and
accomplished this week. Create a summary and suggest priorities
for next week."

#Health Monitoring

Schedule: */15 * * * * (every 15 minutes)
Model: claude-haiku-4-20260210
Task: "Quick check: Is everything running smoothly? Check for any
system alerts or important notifications. Only message me if
something needs attention."

For the health monitoring cron, set the model to Haiku and instruct the agent to only message you if something is wrong. This keeps costs minimal while providing continuous monitoring.


#Monitoring Heartbeat and Cron Execution

#View Heartbeat History

There is no openclaw heartbeat command group and no --last flag. The documented reader is openclaw system heartbeat last, whose siblings are enable and disable, and which "always print the raw RPC JSON payload".

$openclaw system heartbeat last

Output:

Time Model Tokens Actions Taken
2026-02-20 08:00:01 haiku-4 312 Triggered morning briefing cron
2026-02-20 08:15:00 haiku-4 245 No action needed
2026-02-20 08:30:01 haiku-4 289 Sent reminder: dentist at 2pm
2026-02-20 08:45:00 haiku-4 201 No action needed
...

#View Cron Execution History

There is no cron history. Run history is runs, where "automations runs is the preferred spelling. cron runs and the leaf-local --id <job-id> form remain supported compatibility aliases."

$openclaw cron runs <job-id> --limit 50
ID Time Status Model Tokens Duration
1 2026-02-20 08:00:03 Success sonnet-4.6 2,451 4.2s
2 2026-02-20 09:00:01 Success haiku-4 892 1.1s
3 2026-02-20 12:00:02 Failed sonnet-4.6 — timeout

#Monitor Costs

There is no top-level openclaw usage and no --breakdown flag. openclaw gateway usage-cost takes --days, --agent, --all-agents and --json, so scope it to the agent that owns the heartbeat:

$openclaw gateway usage-cost --days 7 --agent <id>
Heartbeat API Usage (Last 7 Days)
=================================
Total cycles: 672
Total tokens: 198,432
Estimated cost: $2.38
By model:
claude-haiku-4: 648 cycles, 182,400 tokens, $0.91
claude-sonnet-4.6: 24 cycles, 16,032 tokens, $1.65
Cron job costs:
Morning briefing: $0.84/week
Calendar check: $0.21/week
News scan: $0.42/week

#Cost Optimization Tips for Heartbeat

  1. Use Haiku 4 for heartbeat: It is 10-20x cheaper than Opus and fast enough for triage
  2. Increase the interval: 15-30 minutes is sufficient for most users
  3. Set active hours: No need to run frequent heartbeats at 3 AM
  4. Use escalation: Let Haiku decide when to invoke a more capable model
  5. Minimize cron jobs: Each cron job is an additional API call
  6. Use "only notify if important" instructions: Reduce unnecessary responses

See the Cost Optimization Guide for comprehensive strategies.


#Troubleshooting

#Heartbeat not firing

$openclaw doctor --check heartbeat

Common causes:

  • Heartbeat is disabled in configuration
  • Gateway is not running
  • API key is invalid or rate-limited

#Cron jobs not executing

  • Verify the cron schedule syntax is correct
  • Check that the job is enabled (openclaw cron list)
  • Ensure the heartbeat is enabled (cron jobs are processed during heartbeat cycles)
  • Check the Gateway logs for errors with openclaw logs --follow, since there is no openclaw gateway logs subcommand

#Cron jobs running at wrong times

  • Verify the timezone is set correctly in the cron configuration
  • Check system timezone: date +%Z
  • The timezone field in configuration must be a valid IANA timezone name (e.g., America/New_York, not EST)

#Next Steps

Sources

  1. OpenClaw: Config
  2. OpenClaw: Automations (cron)
  3. OpenClaw: System
  4. OpenClaw: Logs
  5. OpenClaw: Query a running Gateway

Skip the trial and error

ClawDocx members get 500+ tested prompts, ready-to-install SKILL.md files, SOUL.md and CLAUDE.md templates, and an MCP server so your agent can pull all of it directly while it works.