# Cron Jobs & Heartbeats: Making OpenClaw Proactive

OpenClaw becomes proactive when it has a safe reason to wake up, check something, and report only when it matters. The two core scheduling mechanisms are **cron jobs** and **heartbeats**.

- **Cron jobs** run at an exact time or interval.
- **Heartbeats** run periodic agent turns for quiet, context-aware checks.

This guide explains when to use each, what people automate with them, and how to control cost, delivery, and risk.

## Cron Jobs vs Heartbeats

| Question | Use Cron Jobs | Use Heartbeats |
|---|---|---|
| Timing | Exact time, interval, or one-shot reminder | Approximate periodic checks |
| Context | Fresh isolated run, main session, or named custom session | Main-session context by default |
| Best for | Reports, reminders, scheduled jobs, webhooks | Inbox, calendar, follow-ups, low-noise monitoring |
| Delivery | Channel, webhook, or no fallback delivery | Internal by default, or alerts to a chosen target |

Use cron when missing the exact time would matter. Use a heartbeat when it is fine to check on the next cycle and the agent benefits from the current session context.

## Useful Proactive Workflows

### Cron jobs

- Send a weekday project or deployment digest.
- Create a one-time reminder for a deadline or meeting.
- Run a weekly backlog, incident, or cost review.
- Run an isolated report and post the result to a channel or webhook.

### Heartbeats

- Scan for urgent inbox items every 30 minutes.
- Check whether the next calendar event needs preparation.
- Surface blocked work or missing follow-ups.
- Monitor a small changing queue without sending routine “all clear” messages.

For broader workflow ideas, see the [OpenClaw business automation guide](/blog/openclaw-business-automation) and [browser automation guide](/blog/openclaw-browser-automation-guide).

## Create a Safe OpenClaw Cron Job

Cron runs inside the Gateway process. The Gateway must be running for schedules to fire, while job definitions and run history persist in OpenClaw's shared SQLite state database.

### Start with a one-shot reminder

```bash
openclaw cron add \
  --name "Calendar check" \
  --at "20m" \
  --session main \
  --system-event "Next heartbeat: check calendar for urgent preparation." \
  --wake now
```

### Use an isolated job for a scheduled report

```bash
openclaw cron create "0 9 * * 1-5" \
  "Summarize open issues, blocked work, and deploys from the last 24 hours. Keep it under 10 bullets." \
  --name "Weekday engineering brief" \
  --tz "Asia/Kolkata" \
  --session isolated \
  --announce \
  --channel slack \
  --to "channel:C1234567890"
```

Use an explicit IANA timezone. Without `--tz`, cron expressions use the Gateway host timezone. Offset-less one-shot timestamps are UTC unless you set a timezone.

### Test before enabling delivery or write access

```bash
openclaw cron list
openclaw cron show <job-id>
openclaw cron run <job-id> --wait
openclaw cron runs --id <job-id> --limit 20
```

## Use Heartbeats Without Creating Noise

Heartbeats are periodic main-session turns. They should surface attention-worthy work and otherwise remain quiet.

### Keep HEARTBEAT.md short

```markdown
# Heartbeat checklist

- Check for urgent unread inbox items.
- Check whether the next calendar event needs preparation.
- If a task is blocked, explain what is missing.
- Keep alerts short. If nothing needs attention, reply HEARTBEAT_OK.
```

### Give checks their own intervals

```markdown
tasks:
  - name: inbox-triage
    interval: 30m
    prompt: "Check for urgent unread emails and flag only time-sensitive items."
  - name: calendar-scan
    interval: 2h
    prompt: "Check for upcoming meetings that need preparation or follow-up."

- Keep alerts concise. If nothing needs attention, reply HEARTBEAT_OK.
```

### Restrict active hours and start with no external delivery

```json5
{
  agents: {
    defaults: {
      heartbeat: {
        every: "30m",
        target: "none",
        lightContext: true,
        isolatedSession: true,
        skipWhenBusy: true,
        activeHours: {
          start: "09:00",
          end: "22:00",
          timezone: "Asia/Kolkata"
        }
      }
    }
  }
}
```

`target: "none"` is the safe default for a new heartbeat. Add delivery only after you have confirmed that alerts are useful. Do not use identical start and end times for active hours, because that creates a zero-width window.

## Cost, Reliability, and Security

To control costs, use the longest practical cadence, keep `HEARTBEAT.md` small, enable `lightContext` or `isolatedSession` when shared history is unnecessary, and use a model appropriate for a lightweight check.

For safety:

- Start with read-only checks and private delivery.
- Require approval before scheduled workflows edit data, send messages, deploy, or spend substantial API budget.
- Use explicit delivery targets.
- Never put secrets in `HEARTBEAT.md` or a scheduled prompt.
- Treat command cron and event-trigger scripts as unattended code execution.
- Review run history and logs after every schedule or permission change.

Read [OpenClaw security best practices](/blog/openclaw-security-best-practices) and compare [managed vs self-hosted OpenClaw](/blog/openclaw-managed-vs-self-hosted) before operating a persistent agent in production.

## Troubleshooting

```bash
openclaw status
openclaw gateway status
openclaw cron status
openclaw cron list
openclaw cron runs --id <job-id> --limit 20
openclaw system heartbeat last
openclaw logs --follow
openclaw doctor
```

If a cron job does not fire, check Gateway uptime, cron enablement, and timezone. If it runs but nothing arrives, check its delivery mode, channel, recipient, and run history. If a heartbeat is too noisy, shorten the checklist, use `HEARTBEAT_OK`, and keep delivery disabled until an alert truly needs to be sent.

## Frequently Asked Questions

**What is the difference between cron jobs and heartbeats in OpenClaw?** Cron jobs run at exact times and work well for reminders, reports, and isolated background jobs. Heartbeats are periodic main-session agent turns for batched, context-aware checks.

**Do cron jobs survive restarts?** Yes. OpenClaw stores cron job definitions, runtime state, and run history in its shared SQLite state database. The Gateway must still be running for scheduled work to fire.

**How can I stop heartbeats from spamming me?** Keep `HEARTBEAT.md` short, hide routine `HEARTBEAT_OK` acknowledgments, use active hours, and enable external delivery only for genuine alerts.

**How do I test a cron job?** Inspect it with `openclaw cron show`, run it with `openclaw cron run <job-id> --wait`, then check `openclaw cron runs` before you enable sensitive actions.
