OpenClaw ships with a built-in cron scheduler inside its Gateway daemon. If you’ve ever written a standard crontab, the syntax is immediately familiar — with two additions that matter for monitoring: timezone support and a choice between session modes.
The Basic Command Structure
A full cron job registration looks like this:
openclaw cron add --name "dbt-test-monitor" \ --cron "0 7 * * *" \ --tz "Europe/Paris" \ --session isolated \ --message "Run dbt test on the production project and summarize any failures. Group by severity." \ --announce \ --channel slack \ --to "channel:C1234567890"Breaking this down:
--nameis a human-readable identifier for the job. Use it to distinguish between similar jobs (“bq-failure-check” vs “bq-cost-check”).--crontakes standard five-field cron expressions.0 7 * * *means every day at 7:00 AM.--tzsets the timezone for the schedule. Without it, the Gateway uses whatever system timezone the host machine is configured with — which may not be the timezone you’re thinking in.--sessioncontrols how the task runs (detailed below).--messageis the natural language prompt the agent receives as its task instruction.--announcetells the agent to post results to a channel rather than silently logging them.--channeland--tospecify the delivery target.
Session Modes: Isolated vs. Main
The session mode is the most consequential configuration choice for scheduled monitoring tasks.
Main session injects the cron task into your active conversation thread. The agent picks up the task, runs it, and posts the result in whatever chat you currently have open. This mode is useful when you want to follow up interactively — if a test fails, you’re right there in the conversation to ask “why did that fail? Show me the model definition.” The continuity is genuinely convenient.
The problem with main session for monitoring is clutter. If you’re doing development work in your OpenClaw chat and a scheduled task fires, its output appears inline with your conversation. Multiple scheduled tasks create a fragmented thread where it’s unclear what’s a response to you and what’s an automated report.
Isolated session runs each cron task in its own dedicated agent turn, completely separate from any ongoing conversation. The agent receives the task prompt, does its work, delivers the result to the specified channel, and ends. Nothing bleeds into your main conversation.
For monitoring, isolated is almost always the right choice. The mental model is clean: scheduled tasks are like background jobs. They do their work and deliver results to the right place. Your main conversation thread is for interactive work.
The only time main session makes sense for monitoring is when you’re actively debugging a configuration and want to watch what the agent does in real time. Once monitoring is working reliably, switch to isolated.
Job Persistence and Inspection
Cron jobs persist in ~/.openclaw/cron/jobs.json. This file survives Gateway restarts, so you don’t need to re-register jobs after rebooting the host machine.
You can inspect this file directly:
cat ~/.openclaw/cron/jobs.jsonThe file contains the complete job definitions in JSON format. This means you can also version-control it — useful if you’re managing multiple monitoring setups across different machines or want to snapshot your configuration before changes.
For operational inspection, OpenClaw also provides a CLI command to list active jobs with their next scheduled run times. Check the OpenClaw cron documentation for the current command syntax, as this has evolved across versions.
Exponential Backoff on Failure
When a cron job fails — because the agent can’t connect to the warehouse, the command returns an error, or the AI call times out — OpenClaw applies exponential backoff before retrying:
| Retry | Delay |
|---|---|
| 1st | 30 seconds |
| 2nd | 1 minute |
| 3rd | 5 minutes |
| 4th | 15 minutes |
| 5th | 60 minutes |
This is sensible behavior for a few reasons. It prevents a broken job from hammering your warehouse or API endpoints. It gives transient issues time to resolve (a brief warehouse outage, a temporary network problem) without human intervention. And it means a single failed run doesn’t flood your Slack channel with repeated alerts.
The tradeoff is that you won’t get rapid retry attempts when something recovers quickly. If a warehouse blip lasts 90 seconds and your retry schedule says “wait 30 seconds, then 1 minute,” you’ll get your result in the second attempt. If the blip lasts 10 minutes, the third retry (5 minutes after the second attempt) will probably catch it. Neither is catastrophic for daily monitoring jobs where a 15-minute delay in a 7 AM report is acceptable.
For tighter SLAs — where you need to know within 5 minutes if a critical pipeline failed — the backoff schedule means OpenClaw isn’t the right choice for the alerting layer. Dedicated tools with purpose-built retry logic handle this better.
The Message Parameter as Natural Language Prompt
The --message parameter deserves attention because it’s doing something different from a standard cron command. In a typical crontab, you specify a command to execute: /usr/local/bin/dbt test --target prod. The computer does exactly that, nothing more.
In OpenClaw’s cron, the --message is a natural language prompt that the agent interprets. “Run dbt test on the production project and summarize any failures. Group by severity” is a set of instructions, not a command. The agent decides how to execute it, which means:
- The agent will navigate to the project directory (you should specify this in a skill so it knows where to look)
- It will run
dbt test --target prod(or similar, based on its understanding of the task) - It will parse the output using its own judgment about what counts as a failure vs. a warning
- It will format the summary in whatever way seems most readable
This is powerful because you don’t need to script output parsing. A dbt test failure message that says not_null_mrt__sales__orders_order__customer_id | FAIL 47 requires string manipulation to extract the test name, model, and count — the agent handles this interpretation automatically.
The risk is variability. The same underlying prompt can produce slightly different outputs depending on the model version, the specific shape of your dbt output that day, and subtle variations in how the agent interprets “summarize any failures.” If you need consistent, predictable output format every time, move the detailed instructions into a skill file rather than the cron message, and be explicit about the format you want. The OpenClaw Skills for Monitoring note covers how to structure skill instructions to reduce this variability.
Multiple Jobs for Multiple Projects
For consultants managing multiple client dbt projects, the pattern is straightforward: one cron job per project, all posting to the same (or different) Slack channels depending on how you want to organize the information.
# Client A - daily test check at 7 AM Paris timeopenclaw cron add --name "client-a-dbt-monitor" \ --cron "0 7 * * *" \ --tz "Europe/Paris" \ --session isolated \ --message "Run dbt test for the Client A project at /home/user/projects/client-a. Summarize failures with affected models and suggested actions." \ --announce \ --channel slack \ --to "channel:C_CLIENT_A_CHANNEL_ID"
# Client B - staggered by 5 minutes to avoid concurrent runsopenclaw cron add --name "client-b-dbt-monitor" \ --cron "5 7 * * *" \ --tz "Europe/Paris" \ --session isolated \ --message "Run dbt test for the Client B project at /home/user/projects/client-b. Summarize failures with affected models and suggested actions." \ --announce \ --channel slack \ --to "channel:C_CLIENT_B_CHANNEL_ID"Staggering start times prevents concurrent runs from competing for resources. A 5-minute offset is enough for most dbt projects. If any single project takes more than 5 minutes to test, increase the offset or accept that jobs may overlap — the isolated session mode means they won’t interfere with each other’s conversation context.
Delivery Modes
The --announce flag is one of three delivery modes for cron job output:
--announce with --channel and --to: Posts the agent’s response directly to a messaging channel. This is what you want for monitoring results that humans should see. The Slack channel ID (format C1234567890) or Telegram chat ID goes in the --to parameter.
Webhook POST: Sends structured data to an HTTP endpoint. Useful when you want to pipe results into another system — feeding failure counts to PagerDuty, posting structured JSON to a custom dashboard, or triggering a downstream automation. The endpoint receives the agent’s output as a POST request body.
Silent mode: Logs results locally without sending anything externally. Useful while you’re testing a new job configuration and don’t want to flood your Slack channel with partially-working reports. Switch to announce mode once the output looks right.
The combination you’ll use for almost all monitoring: --session isolated --announce --channel slack. Clean output, no conversation clutter, delivered directly to the team.