Cron (OpenClaw Scheduled Tasks)
OpenClaw's built-in scheduler runs inside the Gateway process. Jobs persist at ~/.openclaw/cron/jobs.json and survive Gateway restarts. Every execution creates a Background Task record. One-shot jobs auto-delete after successful completion by default.
Schedule Types
| Type | Flag | Description |
|---|---|---|
| One-shot | --at |
ISO 8601 timestamp or relative expression |
| Fixed interval | --every |
Duration-based recurrence |
| Cron expression | --cron |
Standard 5- or 6-field expression; optional --tz |
Staggering: recurring top-of-hour jobs auto-stagger up to 5 minutes unless --exact or --stagger <duration> specified.
Day logic: when both day-of-month and day-of-week are non-wildcard, croner uses OR logic (fires when either matches).
Timezone: --at without TZ defaults to UTC; --cron without --tz uses host timezone.
Execution Styles
| Style | --session |
Session | Use Case |
|---|---|---|---|
| Main session | main |
Enqueued at next heartbeat turn | Reminders, system events |
| Isolated | isolated |
Fresh cron:<jobId> session |
Reports, background work |
| Current | current |
Session bound at creation time | Context-aware tasks |
| Custom | session:xxx |
Persistent named session | History-building workflows |
Isolated jobs support --light-context (skip workspace bootstrap) and --tools <list> (restrict tool access).
Model selection precedence (isolated jobs):
- Gmail hook override (if applicable)
- Per-job
--model - Stored session override
- Agent/default
Delivery Modes
| Mode | Behavior |
|---|---|
announce |
Post summary to target channel (default for isolated) |
webhook |
HTTP POST finished-event payload to URL |
none |
No outbound delivery (internal only) |
Channel targets: --channel slack --to "channel:C123", --channel telegram --to "-1001234567890". Forum topics append :topic:<id>.
Failure destination: cron.failureDestination (global) or job.delivery.failureDestination (per-job); falls back to primary announce target.
Task Reconciliation
An active cron task stays live while the cron runtime tracks that job as running, regardless of stale session rows. Tasks are marked lost after a 5-minute grace window expires.
Inbound Webhooks
Webhooks turn OpenClaw into an event receiver as well as a scheduler.
{ hooks: { enabled: true, token: "shared-secret", path: "/hooks" } }
Auth: Authorization: Bearer <token> or x-openclaw-token: <token> header (query-string rejected).
| Endpoint | Purpose |
|---|---|
POST /hooks/wake |
Enqueue system event (text, optional mode) |
POST /hooks/agent |
Run isolated turn (message required) |
POST /hooks/<name> |
Custom mapped hook via hooks.mappings |
Security: keep behind loopback/trusted proxy; set hooks.allowedAgentIds; keep hooks.allowRequestSessionKey=false.
Gmail PubSub
openclaw webhooks gmail setup --account openclaw@gmail.com
Uses Tailscale Funnel for push endpoint. Gateway auto-starts gog gmail watch serve on boot. Supports per-Gmail model override via hooks.gmail.model.
Configuration
{
cron: {
enabled: true,
store: "~/.openclaw/cron/jobs.json",
maxConcurrentRuns: 1,
retry: {
maxAttempts: 3,
backoffMs: [60000, 120000, 300000],
retryOn: ["rate_limit", "overloaded", "network", "server_error"],
},
sessionRetention: "24h",
runLog: { maxBytes: "2mb", keepLines: 2000 },
},
}
Disable: cron.enabled: false or env OPENCLAW_SKIP_CRON=1.
Retry: one-shot jobs retry up to 3× (exponential backoff on transient errors); recurring jobs use escalating backoff 30s → 60m. Sessions pruned after sessionRetention; run logs capped by maxBytes/keepLines.
CLI Quick Reference
openclaw cron add --name "Brief" --cron "0 7 * * *" --tz "America/Los_Angeles" \
--session isolated --message "Summarize overnight updates" \
--announce --channel slack --to "channel:C123"
openclaw cron list
openclaw cron edit <id>
openclaw cron run <id> # force-execute now
openclaw cron run <id> --due # run only if scheduled time reached
openclaw cron runs --id <id> --limit 50
openclaw cron remove <id>
Troubleshooting
openclaw cron status
openclaw cron runs --id <jobId> --limit 20
openclaw system heartbeat last
openclaw logs --follow
openclaw doctor
- Cron not firing → verify
cron.enabled, Gateway running, timezone config - Fired but no delivery → check delivery mode isn't
none, validate channel/auth
See Also
- Automation & Tasks — six-mechanism overview and decision guide
- Heartbeat — fuzzy periodic monitoring; no task records, lower overhead
- Background Tasks — audit ledger populated by every cron run
- OpenClaw Hooks — event-driven counterpart to scheduled execution
- OpenClaw Gateway — Gateway process hosts the cron runtime
- Source - Scheduled Tasks / Cron Jobs (OpenClaw Docs)