Cron jobs (Gateway scheduler)
Cron is the Gateway’s built-in scheduler. It persists jobs, wakes the agent at the right time, and can optionally deliver output back to a chat. If you want “run this every morning” or “poke the agent in 20 minutes”, cron is the mechanism.TL;DR
- Cron runs inside the Gateway (not inside the model).
- Jobs persist under
~/.clawdbot/cron/so restarts don’t lose schedules. - Two execution styles:
- Main session: enqueue a system event, then run on the next heartbeat.
- Isolated: run a dedicated agent turn in
cron:<jobId>, optionally deliver output.
- Wakeups are first-class: a job can request “wake now” vs “next heartbeat”.
Concepts
Jobs
A cron job is a stored record with:- a schedule (when it should run),
- a payload (what it should do),
- optional delivery (where output should be sent).
jobId (used by CLI/Gateway APIs).
In agent tool calls, jobId is canonical; legacy id is accepted for compatibility.
Schedules
Cron supports three schedule kinds:at: one-shot timestamp (ms since epoch).every: fixed interval (ms).cron: 5-field cron expression with optional IANA timezone.
croner. If a timezone is omitted, the Gateway host’s
local timezone is used.
Main vs isolated execution
Main session jobs (system events)
Main jobs enqueue a system event and optionally wake the heartbeat runner. They must usepayload.kind = "systemEvent".
wakeMode: "next-heartbeat"(default): event waits for the next scheduled heartbeat.wakeMode: "now": event triggers an immediate heartbeat run.
Isolated jobs (dedicated cron sessions)
Isolated jobs run a dedicated agent turn in sessioncron:<jobId>.
Key behaviors:
- Prompt is prefixed with
[cron:<jobId> <job name>]for traceability. - A summary is posted to the main session (prefix
Cron, configurable). wakeMode: "now"triggers an immediate heartbeat after posting the summary.- If
payload.deliver: true, output is delivered to a provider; otherwise it stays internal.
Delivery (provider + target)
Isolated jobs can deliver output to a provider. The job payload can specify:provider:whatsapp/telegram/discord/slack/signal/imessage/lastto: provider-specific recipient target
provider or to is omitted, cron can fall back to the main session’s “last route”
(the last place the agent replied).
Telegram delivery targets (topics / forum threads)
Telegram supports forum topics viamessage_thread_id. For cron delivery, you can encode
the topic/thread into the to field:
-1001234567890(chat id only)-1001234567890:topic:123(preferred: explicit topic marker)-1001234567890:123(shorthand: numeric suffix)
telegram:... / telegram:group:... are also accepted:
telegram:group:-1001234567890:topic:123
Storage & history
- Job store:
~/.clawdbot/cron/jobs.json(Gateway-managed JSON). - Run history:
~/.clawdbot/cron/runs/<jobId>.jsonl(JSONL, auto-pruned). - Override store path:
cron.storein config.
Configuration
cron.enabled: false(config)CLAWDBOT_SKIP_CRON=1(env)
CLI quickstart
One-shot reminder (main session, wake immediately):Gateway API surface
cron.list,cron.status,cron.add,cron.update,cron.removecron.run(force or due),cron.runswake(enqueue system event + optional heartbeat)
Troubleshooting
“Nothing runs”
- Check cron is enabled:
cron.enabledandCLAWDBOT_SKIP_CRON. - Check the Gateway is running continuously (cron runs inside the Gateway process).
- For
cronschedules: confirm timezone (--tz) vs the host timezone.
Telegram delivers to the wrong place
- For forum topics, use
-100…:topic:<id>so it’s explicit and unambiguous. - If you see
telegram:...prefixes in logs or stored “last route” targets, that’s normal; cron delivery accepts them and still parses topic IDs correctly.