OpenClaw Cron Jobs: How to Automate Tasks on a Schedule in 2026
Every OpenClaw operator eventually runs into the same realization: the agent is only useful when someone is there to talk to it. You ask a question, it answers. You request a task, it executes. But what happens at 3:00 AM when a server goes down and nobody is at the keyboard? What about things you want done every single morning, week after week, without having to type the same prompt?
That is what OpenClaw cron jobs are for. Scheduled automation turns OpenClaw from a chat agent you actively use into an autonomous operator that works around the clock. A properly configured OpenClaw cron job can generate your daily briefings, monitor your infrastructure, publish content, collect market intelligence, and post updates to Slack or Telegram — all without any human intervention.
This guide covers everything you need to know about OpenClaw cron jobs: how they work, how to configure them in openclaw.json or via the API, the delivery options that determine how you get notified, the gotchas that waste hours of debugging time, and ten practical cron jobs every operator should have running right now. Whether you manage a single personal assistant or a fleet of production agents, these patterns apply.
OpenClaw Cron Basics: How It Works
An OpenClaw cron job is a scheduled task that runs inside a fresh agent session. You define what the agent should do and when it should do it. The gateKeeper (the daemon process) checks the cron schedule and launches jobs on time.
Each cron job has three essential components:
Schedule. You can use standard cron expressions (five or six fields: minute, hour, day of month, month, day of week, and optionally year) or a simple interval string like every 6h, every 30m, or every 1d. The interval syntax is parsed with cron-parser and is generally easier to read and write than raw cron expressions.
Task. This is the prompt you want the agent to execute. It must be self-contained — more on that later. The task can be a plain text instruction, a named named prompt reference, or a JSON/Loop-style workflow.
Delivery. This controls how the cron job announces its completion. You can post results to a Slack or Telegram channel, send them silently to the agent’s active memory, or run the job with no announcement at all.
Beyond these three core components, every cron job maintains state that OpenClaw exposes through its API and logs. The state includes:
- lastRunAt. Timestamp of the most recent execution.
- lastRunStatus. One of
success,failure, orskipped. - consecutiveErrors. A counter that increments on every failed run and resets to 0 on success. This is the single most important metric for monitoring cron health.
- isRunning. A boolean flag indicating whether the job is currently executing.
- state. An enum (
idle,active,paused) that controls whether the cron job is eligible to run.
Cron jobs are defined in the cron section of your openclaw.json file, or managed at runtime through the OpenClaw REST API with the cron.create, cron.update, cron.list, cron.delete, and cron.run endpoints. Both methods use the same configuration schema.
Creating Your First Cron Job
There are two ways to create a cron job in OpenClaw: configuration file or API. The configuration file approach is best for jobs that are part of your permanent infrastructure. The API approach is better for testing, temporary jobs, or dynamic scheduling driven by another system.
Method 1: openclaw.json Configuration
Add a cron key to your openclaw.json file. Each job gets a unique name as the key and a configuration object as the value. Here is a minimal example that sends a daily health check to the operator every morning:
{
"cron": {
"daily-heartbeat": {
"schedule": "every 24h",
"task": "Run a complete system health check. Check disk usage, memory, CPU load, and gateway status. Summarize any issues found. If any metric is critical, flag it with URGENT in the response.",
"delivery": {
"mode": "announce",
"channel": "C01234ABCDEF"
}
}
}
}
In this configuration, the daily-heartbeat cron job runs once every 24 hours. The agent receives the task prompt, executes the health check using its available tools, and posts the result to the Slack channel with ID C01234ABCDEF.
You can also use traditional cron expressions for more precise scheduling:
{
"cron": {
"morning-briefing": {
"schedule": "0 6 * * *",
"task": "Generate the daily briefing. Check Scout for any new market intelligence from the last 24 hours. Summarize the top three items. Post to the team.",
"delivery": {
"mode": "announce",
"channel": "C01234ABCDEF"
}
}
}
}
The expression 0 6 * * * means “every day at 06:00 UTC.” The six-field format with year is also supported (cron and year).
Method 2: OpenClaw API
You can create the same cron job programmatically. The cron.create endpoint accepts the same schema as the JSON configuration. This is useful when you want to create jobs on the fly from another system, or when you want to test a job before committing it to your configuration file.
To create a cron job via the API:
curl -X POST "https://your-gateway.openclaw.local/api/cron" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "hourly-system-check",
"schedule": "0 * * * *",
"task": "Check the system load average and disk usage. Report only if anything is above 80%.",
"delivery": {
"mode": "announce",
"channel": "C01234ABCDEF"
}
}'
The other cron API endpoints give you full lifecycle management:
cron.list— List all configured cron jobs with their current state.cron.update— Modify an existing cron job’s schedule, task, or delivery.cron.delete— Remove a cron job permanently.cron.run— Force-run a cron job immediately, bypassing the schedule. This is essential for testing.
Delivery Configuration: How to Get Notified
Delivery configuration determines how the cron job’s output reaches you. OpenClaw supports three delivery modes:
announce. The agent posts the cron job result to a channel. This is the most common mode for production cron jobs. You specify the target with delivery.channel or delivery.to.
none. The job runs silently. No notification is sent. Use this for maintenance tasks like database backups or cache cleanups where you only care about failures. When you use none delivery, you should monitor the consecutiveErrors field to detect problems.
Direct message (API-specific). Some channel plugins support to with a user ID to deliver the cron output as a direct message instead of a channel post.
Here is how delivery targeting works in detail:
{
"cron": {
"silent-backup": {
"schedule": "every 12h",
"task": "Run the database backup script. Verify the backup file exists and is non-empty. Store the result in active memory.",
"delivery": {
"mode": "none"
}
},
"announced-report": {
"schedule": "0 9 * * 1",
"task": "Generate the weekly operations report.",
"delivery": {
"mode": "announce",
"channel": "C01234ABCDEF"
}
}
}
}
The Channel ID Gotcha
There is a well-documented and frustrating bug that every OpenClaw cron operator encounters. The delivery.channel field expects bare Slack channel IDs. But the OpenClaw API may lowercase these IDs internally, which produces an “Unsupported channel” error when the system tries to deliver the message.
Slack channel IDs are alphanumeric strings starting with C. They are case-sensitive. If the API lowercases them, the channel ID becomes invalid and the delivery silently fails.
The workaround is straightforward: use delivery.to with the format channel:CHANNELID instead of delivery.channel. This bypasses the lowercasing behavior and has the same effect.
{
"cron": {
"safe-delivery-example": {
"schedule": "every 1h",
"task": "Ping the uptime monitor and report.",
"delivery": {
"mode": "announce",
"to": "channel:C01234ABCDEF"
}
}
}
}
If you are not seeing cron job output in your channel, check this first. It is the single most common configuration error. Test with cron.run before relying on the scheduled execution.
The Isolated Session Problem: Writing Self-Contained Cron Prompts
Cron jobs run in isolated sessions. This is the most important conceptual shift when moving from interactive use to scheduled automation. When you talk to OpenClaw interactively, the agent has the conversation history, the current session context, and any active memory recalls it made during the conversation. A cron job has none of that background.
A cron job session starts fresh. The agent loads its system prompt and MEMORY.md, but it does not have your “last” channel, the message thread you were just in, or the context of what happened yesterday. The cron prompt must be entirely self-contained. You cannot say “check the usual metrics” or “run the same report as yesterday.” The agent does not know what those refer to.
Here is what a poorly written cron prompt looks like:
// Bad — assumes context the cron session does not have
"task": "Check the servers and post the usual status update"
Here is the same task written properly:
// Good — fully self-contained
"task": "Check the following servers by running the health endpoint on each: server-primary (10.0.1.10), server-backup (10.0.1.11), and server-cache (10.0.1.12). For each, verify HTTP 200 response on port 80 and check that the uptime is greater than 300 seconds. If any check fails, flag it as CRITICAL. Summarize all results."
The same principle applies to tool references and delivery context. If you want the cron job to post to a specific channel, specify it in the delivery configuration. Do not assume the agent knows where to post. The agent cannot read the delivery config and route output accordingly — the cron system handles delivery based on the delivery config, not the agent’s decision. But the prompt itself should be explicit about what to do so that if delivery fails, the result is still meaningful.
Self-contained prompts are slightly longer to write, but they are far more reliable. Invest the extra 30 seconds per prompt and save hours of debugging time later.
Monitoring Cron Health: consecutiveErrors and Status
OpenClaw tracks the health of every cron job through its state object. The critical field is consecutiveErrors. Every time a cron job runs and the agent returns a failure or the execution crashes, this counter increments by one. Every successful run resets it to 0.
If you have a cron job with a consecutiveErrors count of 5, that means it has failed five times in a row. A cron job with consecutiveErrors of 50 has been silently failing for a long time, and you probably have not noticed because you set delivery.mode to none.
You can check cron health through the API:
curl -X GET "https://your-gateway.openclaw.local/api/cron" \
-H "Authorization: Bearer YOUR_API_TOKEN"
Or filter for a specific job:
curl -X GET "https://your-gateway.openclaw.local/api/cron/daily-heartbeat" \
-H "Authorization: Bearer YOUR_API_TOKEN"
The response includes the full state object for each cron job:
{
"name": "daily-heartbeat",
"schedule": "every 24h",
"task": "Run system health check...",
"state": "active",
"lastRunAt": "2026-04-27T06:00:00.000Z",
"lastRunStatus": "success",
"consecutiveErrors": 0,
"isRunning": false
}
Best practices for cron health monitoring:
- Set up an alert on consecutiveErrors. If you have a monitoring system, watch for any cron job where
consecutiveErrors > 3. This catches stuck crons early. - Use
delivery.mode: announcefor critical jobs. If the job is important enough to schedule, it is important enough to know when it fails. Use silent delivery only for jobs where a missed run does not matter. - Test with
cron.runbefore deploying. Never deploy a new cron job without running it manually first. Thecron.runendpoint forces an immediate execution so you can verify the task prompt is self-contained and the delivery configuration works. - Watch the gateway logs. Cron job errors appear in the gateKeeper logs with the prefix
[cron]. Tail your logs periodically to catch failures before they accumulate.
10 Cron Jobs Every OpenClaw Operator Should Have
These ten cron jobs cover the most common and valuable use cases for scheduled OpenClaw automation. Each one includes a working configuration example and notes on what to customize for your setup.
1. Heartbeat Health Check
The most basic cron job. Runs every hour and confirms the gateway and its core services are responding. Essential for any production deployment.
{
"cron": {
"heartbeat": {
"schedule": "every 1h",
"task": "Ping the local gateway health endpoint. Verify response time under 2 seconds. Check that the model provider is reachable. If any check fails, prefix the report with CRITICAL.",
"delivery": {
"mode": "announce",
"to": "channel:C01234ABCDEF"
}
}
}
}
2. Daily Intelligence Brief
Collects Scout market intelligence at the start of every day and summarizes it for the team. This uses Scout data if you have it configured, or falls back to web search.
{
"cron": {
"daily-brief": {
"schedule": "0 6 * * *",
"task": "Check commons/agents/scout/ for any new intelligence reports from the last 24 hours. Summarize the top three items. If nothing new is found, run a search for AI industry news from the past 24 hours and summarize that instead. Post a clean summary with bullet points.",
"delivery": {
"mode": "announce",
"to": "channel:C01234ABCDEF"
}
}
}
}
3. Content Publishing Pipeline
If you produce regular content — newsletters, blog posts, social threads — a cron can prep and stage content for review.
{
"cron": {
"content-stage": {
"schedule": "0 14 * * 1,3,5",
"task": "Check the drafts directory for any completed content drafts. For each draft found, verify it has a title, body, and tags. If a draft is complete, move it to the published directory and log the action. If incomplete, leave a note listing what is missing.",
"delivery": {
"mode": "announce",
"to": "channel:C01234ABCDEF"
}
}
}
}
4. Backup Verification Runner
Triggers backup scripts and validates the output. Delivery is silent because you only need to know when it breaks.
{
"cron": {
"backup-check": {
"schedule": "every 12h",
"task": "Run the backup verification tool on the last backup file. Confirm the file is not empty and the checksum matches the recorded value. Store the result in active memory under key last_backup_status.",
"delivery": {
"mode": "none"
}
}
}
}
5. Market Price Tracker
Periodically checks prices for services or products you track. Useful for competitive intelligence or cost monitoring.
{
"cron": {
"price-tracker": {
"schedule": "0 0 * * *",
"task": "Check the current per-token pricing for GPT-4o, Claude Sonnet 4, and DeepSeek V4 on their respective provider pages. Compare against last recorded prices. Report any changes and highlight price drops (green) or increases (red).",
"delivery": {
"mode": "announce",
"to": "channel:C01234ABCDEF"
}
}
}
}
6. Weekly Ops Report
Summarizes the week’s cron job health, total task counts, token usage, and error rates.
{
"cron": {
"weekly-report": {
"schedule": "0 10 * * 1",
"task": "Review all cron jobs and their state. Count total successful runs, total failed runs, and sum the consecutiveErrors across all jobs. Report the overall health score: GREEN if zero errors this week, YELLOW if 1-3 errors, RED if more than 3. Include a brief explanation.",
"delivery": {
"mode": "announce",
"to": "channel:C01234ABCDEF"
}
}
}
}
7. Social Media Queue Check
If you schedule social posts through OpenClaw, this cron ensures the queue is topped up and nothing is stuck.
{
"cron": {
"social-queue": {
"schedule": "0 8,20 * * *",
"task": "Check the social media post queue. If the queue has fewer than 5 pending posts, generate 3 new posts from the content backlog with appropriate hashtags. Do not post them — stage them for human review in the staged-posts directory.",
"delivery": {
"mode": "announce",
"to": "channel:C01234ABCDEF"
}
}
}
}
8. Token Budget Monitor
For cost-conscious operators, this cron tracks token consumption against your monthly budget.
{
"cron": {
"token-budget": {
"schedule": "0 12 * * *",
"task": "Check the token usage logs for the current month. Sum input and output tokens. If usage exceeds 80% of the monthly budget (80M input, 20M output), post a warning. If it exceeds 95%, post a CRITICAL alert.",
"delivery": {
"mode": "announce",
"to": "channel:C01234ABCDEF"
}
}
}
}
9. Commitment Check (Git Repo Health)
For teams using Git, this cron ensures code and documentation commits are flowing.
{
"cron": {
"git-health": {
"schedule": "0 9 * * 1-5",
"task": "Check each repository in /home/node/git-repos/ for commits in the last 24 hours. If any production repo has no commits for 48 hours and there are open issues, flag it. Report the daily commit count per repo.",
"delivery": {
"mode": "announce",
"to": "channel:C01234ABCDEF"
}
}
}
}
10. Cleanup and Maintenance
Prevents workspace bloat by removing old temp files and trimming logs.
{
"cron": {
"cleanup": {
"schedule": "0 3 * * 0",
"task": "Scan the workspace for files older than 30 days in the temp/ directory. Delete them. Check if the gateway log file exceeds 100MB. If so, rotate it by copying to a dated archive and truncating the active log. Summarize how much space was reclaimed.",
"delivery": {
"mode": "none"
}
}
}
}
Common Cron Mistakes and How to Avoid Them
Even experienced operators stumble on the same cron configuration pitfalls. Here are the most common mistakes and how to avoid each one.
Mistake 1: Using delivery.channel instead of delivery.to. This is the channel ID lowercasing bug described earlier. Just use delivery.to with channel:CHANNELID format and skip the headache entirely.
Mistake 2: Writing prompts that assume context. Every cron prompt must be standalone. If your prompt says “run the analysis like last time,” it will fail on the second run because the isolated session has no memory of “last time.” Always include full instructions, server addresses, file paths, and expected output format.
Mistake 3: Deploying cron jobs without testing with cron.run. The schedule might be perfect and the delivery config might be correct, but if the task prompt is too vague or the agent lacks the tools needed to execute it, the first real execution will fail. Run cron.run at least once in a controlled environment before trusting the schedule.
Mistake 4: Setting delivery.mode to none for critical jobs. If the job matters, you need to know when it breaks. Silent delivery is tempting for noise reduction, but it turns cron failures into silent data loss events. Use none only for jobs where failure is inconsequential.
Mistake 5: Not monitoring consecutiveErrors. A cron job with 100 consecutive errors has been failing for days or weeks. Without active monitoring of this counter, you will not notice until something breaks downstream. Build a simple health check that alerts when consecutiveErrors > 3.
Mistake 6: Using complex cron expressions when intervals work fine. The interval syntax (every 24h, every 30m) is easier to read, less error-prone, and handles timezone adjustments naturally. Use traditional cron expressions only when you need specific wall-clock timing like “at 06:00 UTC every Monday.”
Mistake 7: Forgetting that cron jobs cost tokens. Every cron execution consumes model tokens. A job that runs every minute and generates long responses can burn through a monthly token budget in hours. Estimate token costs per run before deploying high-frequency cron jobs.
Sources
- OpenClaw 2026-4-24 Release Features: Voice, DeepSeek V4, and Browser Automation
- OpenClaw Memory That Actually Persists: What the Setup Guide Gets Wrong
- OpenClaw official documentation: Cron Job Configuration (openclaw.json schema)
- OpenClaw API Reference: cron.create, cron.update, cron.list, cron.delete, cron.run endpoints
