Skip to content
Guides

OpenClaw automations

Cron jobs, one-shot reminders, and why a job that fired sent nothing

6 min read

Automations are OpenClaw’s built-in scheduler: jobs persist in the Gateway’s database, the Gateway wakes the agent when they are due, and the output goes to a chat, a webhook or nowhere. The old cron command still works as an alias. What follows is the model, the five schedule kinds, the difference from the heartbeat, and the ladder for the two classic complaints: it did not fire, and it fired but nothing arrived.

How a job runs

  • Jobs run inside the Gateway process, not inside the model, so the Gateway must be up for anything to fire.
  • Definitions, state and run history live in the shared SQLite database and survive restarts.
  • One-shot jobs delete themselves after a confirmed delivery, and overdue isolated jobs are rescheduled at startup rather than replayed into the window where channels connect.
  • Every run has a wall-clock budget, with a sixty-minute watchdog on isolated jobs when you set none.

The docs prefer promotion over authoring: when you ask for substantially the same job several times, the agent offers to schedule it, restates the schedule and the task in plain words, creates it enabled, and runs it once as a visible test in the same thread. Enabled on purpose: a failing job raises a notification and is disabled after repeated errors, while a job left disabled waiting for approval is invisible to every guard.

Five schedule kinds

  • at: a one-shot timestamp, absolute or relative such as twenty minutes from now.
  • every: a fixed interval.
  • cron: a five- or six-field expression with an optional timezone. Top-of-hour jobs are staggered by up to five minutes unless you ask for exact timing.
  • on-exit: fire once when a watched command exits.
  • stream: fire from batched lines of a long-lived command’s output.

Two cron gotchas the docs call out: an expression with both a day-of-month and a day-of-week matches when either is true, so the fifteenth if it is a Monday fires five or six times a month; and a timestamp without a timezone is UTC. The heartbeat is a different mechanism, a periodic turn in the main session, and old heartbeat task lists migrate into ordinary automations. The OpenClaw heartbeat explains that one.

A job left disabled waiting for a confirmation that never arrives is invisible to every guard [...] a silent non-outcome, which is a worse failure than a job that runs and visibly complains.

It did not fire, or it fired and sent nothing

  • Not firing: the cron-enabled setting or a skip variable in the service environment, a Gateway that was not running, a timezone mismatch, or a job whose agent or creator account cannot be resolved.
  • Fired, nothing arrived: delivery mode none, a missing or invalid target, a channel credential error, or a run that returned the silent token, which suppresses delivery on purpose.
  • A job reported as failed while the work succeeded is usually a delivery failure, and the run history says which.

The ladder: status, Gateway status, automations status, the job list, the run history of the job, the last heartbeat, the logs, then doctor. OpenClaw not responding has the same ladder for a silent agent.

On Diali

On Diali the Gateway is always up, which removes the first cause on the list, and automations are created from the dashboard or from chat with their runs visible there. Delivery targets, timezones and the silent token are still yours to get right. Hosted OpenClaw on Diali is the assistant they run on.

  • The Gateway is the scheduler; if it is down, nothing fires.
  • Promote a repeated request rather than writing cron by hand.
  • Delivery is checked separately from the work.
Get started

Stop reading about it, build one

Set up an agent, pick a channel, and have it working inside the app you already keep open.