Cron Jobs
Gateway scheduler cron jobs + wake.
Tutorial.alert.info
Cron is the gateway's built-in scheduler. It holds jobs, wakes the agent
at the right time, and can optionally pipe output back to chat.
If you want _"run this every morning"_ or _"poke the agent in 20 minutes"_,
cron is the mechanism.
The long and short; TL;DR
- Cron runs <strong>inside the gateway</strong> (not inside the model).
- Jobs persist under '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'~/.openclaw/cron/'</code>', so restarts don't lose schedules.
- Two execution modes:
- <strong>Main session</strong>: queues a system event, then runs at the next heartbeat.
- '<strong>'Isolated'</strong>': runs a dedicated agent turn in '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'cron:<jobId>'</code>', optionally delivering output.
- Wake is first-class: jobs can request "wake now" vs "next heartbeat".
Quickstart (actionable)
Create a one-time reminder, verify it exists, and run it immediately:
openclaw cron add --name "Reminder" --at "2026-02-01T16:00:00Z" --session main --system-event "Reminder: check the cron docs draft" --wake now --delete-after-run openclaw cron list openclaw cron run <job-id> --force openclaw cron runs --id <job-id>
Schedule a repeating isolated job with delivery:
openclaw cron add --name "Morning brief" --cron "0 7 * * *" --tz "America/Los_Angeles" --session isolated --message "Summarize overnight updates." --deliver --channel slack --to "channel:C1234567890"
Tool call equivalents (gateway cron tools)
See '<a href="/automation/cron-jobs#json-schema-for-tool-calls" className="text-emerald-400 hover:text-emerald-300 transition-colors">'JSON schema for tool calls'</a>' for the canonical JSON shape and examples.
Where cron jobs are stored
By default, cron jobs persist on the gateway host at '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'~/.openclaw/cron/jobs.json'</code>'.
The gateway loads the file into memory and writes it back on changes, so manual editing
is only safe when the gateway is stopped. Prefer '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'openclaw cron add/edit'</code>' or cron
tool call APIs for changes.
Beginner-friendly overview
Think of a cron job as: <strong>when</strong> to run + <strong>what</strong> to do.
1. <strong>Pick a schedule</strong>
- One-time reminder β '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'schedule.kind = "at"'</code>' (CLI: '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'--at'</code>')
- Repeating job β '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'schedule.kind = "every"'</code>' or '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'schedule.kind = "cron"'</code>'
- If your ISO timestamp omits a timezone, it's treated as <strong>UTC</strong>.
2. <strong>Pick where to run</strong>
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'sessionTarget: "main"'</code>' β runs in main context during next heartbeat.
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'sessionTarget: "isolated"'</code>' β runs a dedicated agent turn in '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'cron:<jobId>'</code>'.
3. <strong>Pick a payload</strong>
- Main session β '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'payload.kind = "systemEvent"'</code>'
- Isolated session β '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'payload.kind = "agentTurn"'</code>'
Optional: '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'deleteAfterRun: true'</code>' removes a successful one-time job from storage.
Concepts
#
Jobs
A cron job is a stored record of:
- a <strong>schedule</strong> (when to run),
- a <strong>payload</strong> (what it should do),
optional <strong>delivery</strong> (where output should be sent).
- optional '<strong>'agent binding'</strong>' ('<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'agentId'</code>'): run the job under a specific agent; if
missing or unknown, the gateway falls back to the default agent.
Jobs are identified by a stable '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'jobId'</code>' (used by CLI/gateway API).
In agent tool calls, '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'jobId'</code>' is canonical; legacy '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'id'</code>' is accepted for compatibility.
Jobs can optionally auto-delete after a successful one-time run via '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'deleteAfterRun: true'</code>'.
#
Schedules
Cron supports three schedule types:
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'at'</code>': one-time timestamp (milliseconds since epoch). Gateway accepts ISO 8601 and coerces to UTC.
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'every'</code>': fixed interval (milliseconds).
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'cron'</code>': 5-field cron expression with optional IANA timezone.
Cron expressions use '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'croner'</code>'. If timezone is omitted, the gateway host's
local timezone is used.
#
Main vs Isolated execution
##
Main session jobs (system events)
Main jobs queue a system event and optionally wake the heartbeat runner.
They must use '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'payload.kind = "systemEvent"'</code>'.
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'wakeMode: "next-heartbeat"'</code>' (default): event waits for the next scheduled heartbeat.
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'wakeMode: "now"'</code>': event triggers an immediate heartbeat run.
This is best when you want a normal heartbeat prompt + main session context.
See '<a href="/gateway/heartbeat" className="text-emerald-400 hover:text-emerald-300 transition-colors">'Heartbeat'</a>'.
##
Isolated jobs (dedicated cron sessions)
Isolated jobs run a dedicated agent turn in session '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'cron:<jobId>'</code>'.
Key behaviors:
- Prompts are prefixed with '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'[cron:<jobId> <job name>]'</code>' for traceability.
- Each run starts a <strong>new session ID</strong> (no prior conversation carryover).
- Summary is posted to main session (prefix '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'Cron'</code>', configurable).
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'wakeMode: "now"'</code>' triggers heartbeat immediately after posting summary.
- If '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'payload.deliver: true'</code>', output is delivered to channel; otherwise it stays internal.
Use isolated jobs for noisy, frequent, or "background chores" that shouldn't spam
your main chat history.
#
Payload shapes (what runs)
Two payload types are supported:
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'systemEvent'</code>': main session only, routed via heartbeat prompt.
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'agentTurn'</code>': isolated session only, runs a dedicated agent turn.
Common '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'agentTurn'</code>' fields:
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'message'</code>': required text prompt.
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'model'</code>' / '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'thinking'</code>': optional overrides (see below).
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'timeoutSeconds'</code>': optional timeout override.
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'deliver'</code>': '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'true'</code>' sends output to channel target.
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'channel'</code>': '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'last'</code>' or specific channel.
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'to'</code>': channel-specific target (phone/chat/channel ID).
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'bestEffortDeliver'</code>': avoid job failure on delivery failure.
Isolation options (only for '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'session=isolated'</code>'):
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'postToMainPrefix'</code>' (CLI: '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'--post-prefix'</code>'): prefix for system event in main.
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'postToMainMode'</code>': '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'summary'</code>' (default) or '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'full'</code>'.
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'postToMainMaxChars'</code>': max characters when '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'postToMainMode=full'</code>' (default 8000).
#
Model and thinking overrides
Isolated jobs ('<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'agentTurn'</code>') can override model and thinking level:
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'model'</code>': provider/model string (e.g., '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'anthropic/claude-sonnet-4-20250514'</code>') or alias (e.g., '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'opus'</code>')
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'thinking'</code>': thinking level ('<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'off'</code>', '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'minimal'</code>', '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'low'</code>', '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'medium'</code>', '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'high'</code>', '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'xhigh'</code>'; GPT-5.2 + Codex models only)
Note: You can also set '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'model'</code>' on a main session job, but it changes the shared main
session model. We recommend model overrides only for isolated jobs to avoid
unexpected context changes.
Resolution priority:
1. Job payload override (highest)
2. Hook-specific defaults (e.g., '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'hooks.gmail.model'</code>')
3. Agent config defaults
#
Delivery (channel + target)
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'channel'</code>': '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'whatsapp'</code>' / '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'telegram'</code>' / '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'discord'</code>' / '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'slack'</code>' / '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'mattermost'</code>' (plugin) / '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'signal'</code>' / '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'imessage'</code>' / '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'last'</code>'
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'to'</code>': channel-specific recipient target
If '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'channel'</code>' or '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'to'</code>' are omitted, cron can fall back to the main session's "last route"
(where the agent last replied).
Delivery notes:
- If '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'to'</code>' is set, cron automatically delivers the agent's final output even if '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'deliver'</code>' is omitted.
- Use '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'deliver: true'</code>' when you want last-route delivery without an explicit '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'to'</code>'.
- Use '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'deliver: false'</code>' to keep output internal even if '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'to'</code>' is present.
Target format reminders:
- Slack/Discord/Mattermost (plugin) targets should use explicit prefixes (e.g., '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'channel:<id>'</code>', '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'user:<id>'</code>') to avoid ambiguity.
- Telegram topics should use '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">':topic:'</code>' format (see below).
##
Telegram delivery targets (topics/forum threads)
Telegram supports forum topics via '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'message_thread_id'</code>'. For cron delivery, you can encode
the topic/thread into the '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'to'</code>' field:
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'-1001234567890'</code>' (chat ID only)
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'-1001234567890:topic:123'</code>' (preferred: explicit topic marker)
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'-1001234567890:123'</code>' (shorthand: numeric suffix)
Prefixed targets like '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'telegram:...'</code>' / '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'telegram:group:...'</code>' are also accepted:
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'telegram:group:-1001234567890:topic:123'</code>'
JSON schema for tool calls
ReferenceAutomationCronJobsPage step 16: P1
ReferenceAutomationCronJobsPage step 16: P2
ReferenceAutomationCronJobsPage step 16: Content
Examples
One-time reminder:
{
"name": "Reminder",
"schedule": { "kind": "at", "atMs": 1738262400000 },
"sessionTarget": "main",
"wakeMode": "now",
"payload": { "kind": "systemEvent", "text": "Reminder text" },
"deleteAfterRun": true
}Repeating, isolated delivery job:
{
"name": "Morning brief",
"schedule": { "kind": "cron", "expr": "0 7 * * *", "tz": "America/Los_Angeles" },
"sessionTarget": "isolated",
"wakeMode": "next-heartbeat",
"payload": {
"kind": "agentTurn",
"message": "Summarize overnight updates.",
"deliver": true,
"channel": "slack",
"to": "channel:C1234567890",
"bestEffortDeliver": true
},
"isolation": { "postToMainPrefix": "Cron", "postToMainMode": "summary" }
}Notes:
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'schedule.kind'</code>': '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'at'</code>' ('<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'atMs'</code>'), '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'every'</code>' ('<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'everyMs'</code>') or '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'cron'</code>' ('<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'expr'</code>', optional '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'tz'</code>').
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'atMs'</code>' and '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'everyMs'</code>' are epoch milliseconds.
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'sessionTarget'</code>' must be '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'"main"'</code>' or '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'"isolated"'</code>' and must match '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'payload.kind'</code>'.
- Optional fields: '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'agentId'</code>', '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'description'</code>', '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'enabled'</code>', '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'deleteAfterRun'</code>', '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'isolation'</code>'.
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'wakeMode'</code>' defaults to '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'"next-heartbeat"'</code>' when omitted.
#
cron.update parameters
{
"jobId": "job-123",
"patch": {
"enabled": false,
"schedule": { "kind": "every", "everyMs": 3600000 }
}
}Notes:
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'jobId'</code>' is canonical; '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'id'</code>' is accepted for compatibility.
- Use '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'agentId: null'</code>' in patch to clear agent binding.
#
cron.run and cron.remove parameters
{ "jobId": "job-123", "mode": "force" }{ "jobId": "job-123" }Storage and history
- Job storage: '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'~/.openclaw/cron/jobs.json'</code>' (gateway-managed JSON).
- Run history: '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'~/.openclaw/cron/runs/<jobId>.jsonl'</code>' (JSONL, auto-trimmed).
- Override storage path in config: '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'cron.store'</code>'.
Configuration
{
cron: {
enabled: true, // default true
store: "~/.openclaw/cron/jobs.json",
maxConcurrentRuns: 1, // default 1
},
}Disable cron entirely:
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'cron.enabled: false'</code>' (config)
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'OPENCLAW_SKIP_CRON=1'</code>' (environment)
CLI quickstart
One-time reminder (UTC ISO, auto-delete after success):
openclaw cron add --name "Send reminder" --at "2026-01-12T18:00:00Z" --session main --system-event "Reminder: submit expense report." --wake now --delete-after-run
One-time reminder (main session, immediate wake):
openclaw cron add --name "Calendar check" --at "20m" --session main --system-event "Next heartbeat: check calendar." --wake now
Repeating isolated job (send to WhatsApp):
openclaw cron add --name "Morning status" --cron "0 7 * * *" --tz "America/Los_Angeles" --session isolated --message "Summarize inbox + calendar for today." --deliver --channel whatsapp --to "+15551234567"
Repeating isolated job (send to Telegram topic):
openclaw cron add --name "Nightly summary (topic)" --cron "0 22 * * *" --tz "America/Los_Angeles" --session isolated --message "Summarize today; send to the nightly topic." --deliver --channel telegram --to "-1001234567890:topic:123"
Isolated job with model and thinking overrides:
openclaw 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 --channel whatsapp --to "+15551234567"
Agent selection (multi-agent setup):
openclaw cron add --name "Ops sweep" --cron "0 6 * * *" --session isolated --message "Check ops queue" --agent ops openclaw cron edit <jobId> --agent ops openclaw cron edit <jobId> --clear-agent
Manual run (debugging):
openclaw cron run <jobId> --force
Edit existing job (patch fields):
openclaw cron edit <jobId> --message "Updated prompt" --model "opus" --thinking low
Run history:
openclaw cron runs --id <jobId> --limit 50
System event immediately without creating a job:
openclaw system event --mode now --text "Next heartbeat: check battery."
Gateway API
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'cron.list'</code>', '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'cron.status'</code>', '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'cron.add'</code>', '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'cron.update'</code>', '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'cron.remove'</code>'
- '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'cron.run'</code>' (force or due), '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'cron.runs'</code>'
For immediate system events without a job, use '<a href="/cli/system" className="text-emerald-400 hover:text-emerald-300 transition-colors">''<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'openclaw system event'</code>''</a>'.
Troubleshooting
#
"Nothing runs"
- Check if cron is enabled: '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'cron.enabled'</code>' and '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'OPENCLAW_SKIP_CRON'</code>'.
- Check that gateway is running continuously (cron runs inside the gateway process).
- For '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'cron'</code>' schedules: confirm timezone ('<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'--tz'</code>') matches host timezone.
#
Telegram sends to wrong place
- For forum topics, use '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'-100β¦:topic:<id>'</code>' to be explicit and unambiguous.
- If you see '<code className="bg-white/10 px-1.5 py-0.5 rounded text-emerald-300 text-sm">'telegram:...'</code>' prefixes in logs or stored "last route" targets, this is normal;
cron delivery accepts them and still parses topic IDs correctly.