Expose the existing model override capability via CLI flags: - Add --model to cron add and cron edit commands - Document model and thinking overrides in cron-jobs.md - Add CLI example showing model/thinking usage The backend already supported model in agentTurn payloads; this change exposes it through the CLI interface.
6.3 KiB
summary, read_when
| summary | read_when | ||
|---|---|---|---|
| Cron jobs + wakeups for the Gateway scheduler |
|
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).
Jobs are identified by a stable 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.
Cron expressions use 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 use payload.kind = "systemEvent".
wakeMode: "next-heartbeat"(default): event waits for the next scheduled heartbeat.wakeMode: "now": event triggers an immediate heartbeat run.
This is the best fit when you want the normal heartbeat prompt + main-session context. See Heartbeat.
Isolated jobs (dedicated cron sessions)
Isolated jobs run a dedicated agent turn in session cron:<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.
Use isolated jobs for noisy, frequent, or "background chores" that shouldn't spam your main chat history.
Model and thinking overrides
Isolated jobs (agentTurn) can override the model and thinking level:
model: Provider/model string (e.g.,anthropic/claude-sonnet-4-20250514) or alias (e.g.,opus)thinking: Thinking level (off,minimal,low,medium,high)
Resolution priority:
- Job payload override (highest)
- Hook-specific defaults (e.g.,
hooks.gmail.model) - Agent config default
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
If 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 via message_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)
Prefixed targets like 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: true, // default true
store: "~/.clawdbot/cron/jobs.json",
maxConcurrentRuns: 1 // default 1
}
}
Disable cron entirely:
cron.enabled: false(config)CLAWDBOT_SKIP_CRON=1(env)
CLI quickstart
One-shot reminder (main session, wake immediately):
clawdbot cron add \
--name "Calendar check" \
--at "20m" \
--session main \
--system-event "Next heartbeat: check calendar." \
--wake now
Recurring isolated job (deliver to WhatsApp):
clawdbot cron add \
--name "Morning status" \
--cron "0 7 * * *" \
--tz "America/Los_Angeles" \
--session isolated \
--message "Summarize inbox + calendar for today." \
--deliver \
--provider whatsapp \
--to "+15551234567"
Recurring isolated job (deliver to a Telegram topic):
clawdbot cron add \
--name "Nightly summary (topic)" \
--cron "0 22 * * *" \
--tz "America/Los_Angeles" \
--session isolated \
--message "Summarize today; send to the nightly topic." \
--deliver \
--provider telegram \
--to "-1001234567890:topic:123"
Isolated job with model and thinking override:
clawdbot cron add \
--name "Deep analysis" \
--cron "0 6 * * 1" \
--tz "America/Los_Angeles" \
--session isolated \
--message "Weekly deep analysis of project progress." \
--model "opus" \
--thinking high \
--deliver \
--provider whatsapp \
--to "+15551234567"
Manual run (debug):
clawdbot cron run <jobId> --force
Run history:
clawdbot cron runs --id <jobId> --limit 50
Immediate wake without creating a job:
clawdbot wake --mode now --text "Next heartbeat: check battery."
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.