Cron
openclaw cron
Section titled “openclaw cron”Manage cron jobs for the Gateway scheduler.
Sessions
Section titled “Sessions”--session accepts main, isolated, current, or session:<id>.
Session keys
mainbinds to the agent’s main session.isolatedcreates a fresh transcript and session id for each run.currentbinds to the active session at creation time.- `session:
` pins to an explicit persistent session key.
Isolated session semantics
Isolated runs reset ambient conversation context. Channel and group routing, send/queue policy, elevation, origin, and ACP runtime binding are reset for the new run. Safe preferences and explicit user-selected model or auth overrides can carry across runs.
Delivery
Section titled “Delivery”openclaw cron list and openclaw cron show <job-id> preview the resolved delivery route. For channel: "last", the preview shows whether the route resolved from the main or current session, or will fail closed.
Provider-prefixed targets can disambiguate unresolved announce channels. For example, to: "telegram:123" selects Telegram when delivery.channel is omitted or last. Only prefixes advertised by the loaded plugin are provider selectors. If delivery.channel is explicit, the prefix must match that channel; channel: "whatsapp" with to: "telegram:123" is rejected. Service prefixes such as imessage: and sms: remain channel-owned target syntax.
Delivery ownership
Section titled “Delivery ownership”Isolated cron chat delivery is shared between the agent and the runner:
- The agent can send directly using the
messagetool when a chat route is available. announcefallback-delivers the final reply only when the agent did not send directly to the resolved target.webhookposts the finished payload to a URL.nonedisables runner fallback delivery.
--announce is runner fallback delivery for the final reply. --no-deliver disables that fallback but does not remove the agent’s message tool when a chat route is available.
Reminders created from an active chat preserve the live chat delivery target for fallback announce delivery. Internal session keys may be lowercase; do not use them as a source of truth for case-sensitive provider IDs such as Matrix room IDs.
Failure delivery
Section titled “Failure delivery”Failure notifications resolve in this order:
delivery.failureDestinationon the job.- Global
cron.failureDestination. - The job’s primary announce target (when no explicit failure destination is set).
Note: isolated cron runs treat run-level agent failures as job errors even when no reply payload is produced, so model/provider failures still increment error counters and trigger failure notifications.
If an isolated run times out before the first model request, openclaw cron show
and openclaw cron runs include a phase-specific error such as
setup timed out before runner start or
stalled before first model call (last phase: context-engine).
For CLI-backed providers, the pre-model watchdog stays active until the external
CLI turn starts, so session lookup, hook, auth, prompt, and CLI setup stalls are
reported as pre-model cron failures.
Scheduling
Section titled “Scheduling”One-shot jobs
Section titled “One-shot jobs”--at <datetime> schedules a one-shot run. Offset-less datetimes are treated as UTC unless you also pass --tz <iana>, which interprets the wall-clock time in the given timezone.
Recurring jobs
Section titled “Recurring jobs”Recurring jobs use exponential retry backoff after consecutive errors: 30s, 1m, 5m, 15m, 60m. The schedule returns to normal after the next successful run.
Skipped runs are tracked separately from execution errors. They do not affect retry backoff, but openclaw cron edit <job-id> --failure-alert-include-skipped can opt failure alerts into repeated skipped-run notifications.
For isolated jobs that target a local configured model provider, cron runs a lightweight provider preflight before starting the agent turn. Loopback, private-network, and .local api: "ollama" providers are probed at /api/tags; local OpenAI-compatible providers such as vLLM, SGLang, and LM Studio are probed at /models. If the endpoint is unreachable, the run is recorded as skipped and retried on a later schedule; matching dead endpoints are cached for 5 minutes to avoid many jobs hammering the same local server.
Note: cron job definitions live in jobs.json, while pending runtime state lives in jobs-state.json. If jobs.json is edited externally, the Gateway reloads changed schedules and clears stale pending slots; formatting-only rewrites do not clear the pending slot.
Manual runs
Section titled “Manual runs”openclaw cron run <job-id> force-runs by default and returns as soon as the manual run is queued. Successful responses include { ok: true, enqueued: true, runId }. Use the returned runId to inspect the later result:
openclaw cron run <job-id>openclaw cron runs --id <job-id> --run-id <run-id>Add --wait when a script should block until that exact queued run records a terminal status:
openclaw cron run <job-id> --wait --wait-timeout 10m --poll-interval 2sWith --wait, the CLI still calls cron.run first, then polls cron.runs for the returned runId. The command exits 0 only when the run finishes with status ok. It exits non-zero when the run finishes with error or skipped, when the Gateway response does not include a runId, or when --wait-timeout expires. --poll-interval must be greater than zero.
Models
Section titled “Models”cron add|edit --model <ref> selects an allowed model for the job.
Cron --model is a job primary, not a chat-session /model override. That means:
- Configured model fallbacks still apply when the selected job model fails.
- Per-job payload
fallbacksreplaces the configured fallback list when present. - An empty per-job fallback list (
fallbacks: []in the job payload/API) makes the cron run strict. - When a job has
--modelbut no fallback list is configured, OpenClaw passes an explicit empty fallback override so the agent primary is not appended as a hidden retry target.
openclaw doctor reports jobs that already have payload.model set, including provider namespace counts and mismatches against agents.defaults.model. Use that check when auth, provider, or billing behavior looks different between live chat and scheduled jobs.
Isolated cron model precedence
Section titled “Isolated cron model precedence”Isolated cron resolves the active model in this order:
- Gmail-hook override.
- Per-job
--model. - Stored cron-session model override (when the user selected one).
- Agent or default model selection.
Fast mode
Section titled “Fast mode”Isolated cron fast mode follows the resolved live model selection. Model config params.fastMode applies by default, but a stored session fastMode override still wins over config.
Live model switch retries
Section titled “Live model switch retries”If an isolated run throws LiveSessionModelSwitchError, cron persists the switched provider and model (and switched auth profile override when present) for the active run before retrying. The outer retry loop is bounded to two switch retries after the initial attempt, then aborts instead of looping forever.
Run output and denials
Section titled “Run output and denials”Stale acknowledgement suppression
Section titled “Stale acknowledgement suppression”Isolated cron turns suppress stale acknowledgement-only replies. If the first result is just an interim status update and no descendant subagent run is responsible for the eventual answer, cron re-prompts once for the real result before delivery.
Silent token suppression
Section titled “Silent token suppression”If an isolated cron run returns only the silent token (NO_REPLY or no_reply), cron suppresses both direct outbound delivery and the fallback queued summary path, so nothing is posted back to chat.
Structured denials
Section titled “Structured denials”Isolated cron runs use structured execution-denial metadata from the embedded run as the authoritative denial signal. They also honor node-host UNAVAILABLE wrappers when the nested structured error message starts with SYSTEM_RUN_DENIED or INVALID_REQUEST.
Cron does not classify final-output prose or approval-looking refusal phrases as denials unless the embedded run also provides structured denial metadata, so ordinary assistant text is not treated as a blocked command.
cron list and run history surface the denial reason instead of reporting a blocked command as ok.
Retention
Section titled “Retention”Retention and pruning are controlled in config:
cron.sessionRetention(default24h) prunes completed isolated run sessions.cron.runLog.maxBytesandcron.runLog.keepLinesprune~/.openclaw/cron/runs/<jobId>.jsonl.
Migrating older jobs
Section titled “Migrating older jobs”Common edits
Section titled “Common edits”Update delivery settings without changing the message:
openclaw cron edit <job-id> --announce --channel telegram --to "123456789"Disable delivery for an isolated job:
openclaw cron edit <job-id> --no-deliverEnable lightweight bootstrap context for an isolated job:
openclaw cron edit <job-id> --light-contextAnnounce to a specific channel:
openclaw cron edit <job-id> --announce --channel slack --to "channel:C1234567890"Announce to a Telegram forum topic:
openclaw cron edit <job-id> --announce --channel telegram --to "-1001234567890" --thread-id 42Create an isolated job with lightweight bootstrap context:
openclaw cron add \ --name "Lightweight morning brief" \ --cron "0 7 * * *" \ --session isolated \ --message "Summarize overnight updates." \ --light-context \ --no-deliver--light-context applies to isolated agent-turn jobs only. For cron runs, lightweight mode keeps bootstrap context empty instead of injecting the full workspace bootstrap set.
Common admin commands
Section titled “Common admin commands”Manual run and inspection:
openclaw cron listopenclaw cron list --agent opsopenclaw cron get <job-id>openclaw cron show <job-id>openclaw cron run <job-id>openclaw cron run <job-id> --dueopenclaw cron run <job-id> --wait --wait-timeout 10mopenclaw cron run <job-id> --wait --wait-timeout 10m --poll-interval 2sopenclaw cron runs --id <job-id> --limit 50openclaw cron runs --id <job-id> --run-id <run-id>openclaw cron list shows all matching jobs by default. Pass --agent <id> to show only jobs whose effective normalized agent id matches; jobs without a stored agent id count as the configured default agent.
openclaw cron get <job-id> returns the stored job JSON directly. Use cron show <job-id> when you want the human-readable view with delivery-route preview.
cron list --json and cron show <job-id> --json include a top-level status field on each job, computed from enabled, state.runningAtMs, and state.lastRunStatus. Values: disabled, running, ok, error, skipped, or idle. This mirrors the human-readable status column so external tooling can read job state without re-deriving it.
cron runs entries include delivery diagnostics with the intended cron target, the resolved target, message-tool sends, fallback use, and delivered state.
Agent and session retargeting:
openclaw cron edit <job-id> --agent opsopenclaw cron edit <job-id> --clear-agentopenclaw cron edit <job-id> --session currentopenclaw cron edit <job-id> --session "session:daily-brief"openclaw cron add warns when --agent is omitted on agent-turn jobs and falls back to the default agent (main). Pass --agent <id> at create time to pin a specific agent.
Delivery tweaks:
openclaw cron edit <job-id> --announce --channel slack --to "channel:C1234567890"openclaw cron edit <job-id> --best-effort-deliveropenclaw cron edit <job-id> --no-best-effort-deliveropenclaw cron edit <job-id> --no-deliver