Appearance
Cron 定时任务(Gateway 调度器)
Cron 还是 Heartbeat? 参见 Cron vs Heartbeat 了解选型建议。
Cron 是 Gateway 内置的调度器。它能持久化任务、在正确时间唤醒龙虾,还可以把输出回传到聊天界面。
想要"每天早上运行一次"或"20 分钟后提醒我",cron 就是你需要的机制。
故障排查:/openclaw/automation/troubleshooting
快速概览
- Cron 运行在 Gateway 内部(不在模型内部)。
- 任务持久化到
~/.openclaw/cron/,重启不会丢失调度计划。 - 两种执行模式:
- 主会话:入队一个系统事件,下次心跳时执行。
- 隔离:在
cron:<jobId>或自定义会话中运行独立的 agent 轮次,并支持交付(默认 announce)。 - 当前会话:绑定到创建 cron 时所在的会话(
sessionTarget: "current")。 - 自定义会话:在持久化命名会话中运行(
sessionTarget: "session:custom-id")。
- Wakeup 是一等公民:任务可以选择"立即唤醒"或"等下次心跳"。
- Webhook 投递按任务配置,通过
delivery.mode = "webhook"+delivery.to = "<url>"。 - 存储中
notify: true的旧式任务仍兼容cron.webhook,建议迁移到 webhook 交付模式。 - 升级时可用
openclaw doctor --fix规范化旧 cron 存储字段。
快速上手
创建一次性提醒,验证存在,并立即运行:
bash
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>
openclaw cron runs --id <job-id>创建带交付的周期性隔离任务:
bash
openclaw cron add \
--name "Morning brief" \
--cron "0 7 * * *" \
--tz "America/Los_Angeles" \
--session isolated \
--message "Summarize overnight updates." \
--announce \
--channel slack \
--to "channel:C1234567890"工具调用等价写法(Gateway cron 工具)
工具调用的标准 JSON 格式,见下方 JSON schema。
Cron 任务存储位置
Cron 任务默认持久化到 Gateway 主机的 ~/.openclaw/cron/jobs.json。Gateway 启动时加载到内存,有变更时写回磁盘,因此只有在 Gateway 停止时才能安全地手动编辑。建议通过 openclaw cron add/edit 或 cron 工具调用 API 进行修改。
入门概念
把 cron 任务理解为:何时运行 + 做什么。
选择调度方式
- 一次性提醒 →
schedule.kind = "at"(CLI:--at) - 周期性任务 →
schedule.kind = "every"或schedule.kind = "cron" - 如果 ISO 时间戳没有时区,视为 UTC。
- 一次性提醒 →
选择运行位置
sessionTarget: "main"→ 在下次心跳时以主会话上下文运行。sessionTarget: "isolated"→ 在cron:<jobId>中运行独立 agent 轮次。sessionTarget: "current"→ 绑定当前会话(创建时解析为session:<sessionKey>)。sessionTarget: "session:custom-id"→ 在持久化命名会话中运行,跨次保留上下文。
默认行为(不变):
systemEvent载荷默认使用mainagentTurn载荷默认使用isolated
要使用当前会话绑定,需显式设置
sessionTarget: "current"。选择载荷类型
- 主会话 →
payload.kind = "systemEvent" - 隔离会话 →
payload.kind = "agentTurn"
- 主会话 →
可选:一次性任务(schedule.kind = "at")成功后默认自动删除。设置 deleteAfterRun: false 可保留(成功后禁用而非删除)。
核心概念
任务(Jobs)
一个 cron 任务包含:
- 调度计划(何时运行)
- 载荷(做什么)
- 可选的交付模式(
announce、webhook或none) - 可选的 agent 绑定(
agentId):绑定到特定 agent 运行;缺失或未知时回退到默认 agent。
任务通过稳定的 jobId 标识(CLI/Gateway API 均使用)。工具调用中 jobId 为标准字段,兼容旧版 id。一次性任务默认成功后自动删除,设置 deleteAfterRun: false 可保留。
调度计划(Schedules)
Cron 支持三种调度方式:
at:一次性时间戳,通过schedule.at(ISO 8601)指定。every:固定间隔(毫秒)。cron:5 字段(或含秒的 6 字段)cron 表达式,可选 IANA 时区。
Cron 表达式使用 croner 解析。若不指定时区,使用 Gateway 主机的本地时区。
为减少多 Gateway 实例的整点负载尖峰,OpenClaw 对整点周期性表达式(如 0 * * * *、0 */2 * * *)按任务施加最多 5 分钟的确定性随机错开。固定小时表达式(如 0 7 * * *)保持精确。
可以用 schedule.staggerMs 设置显式错开窗口(0 表示精确执行)。CLI 快捷方式:
--stagger 30s(或1m、5m):设置错开窗口--exact:强制staggerMs = 0
主会话 vs 隔离执行
主会话任务(系统事件)
主会话任务入队一个系统事件,可选地唤醒心跳执行器。必须使用 payload.kind = "systemEvent"。
wakeMode: "now"(默认):事件触发立即心跳。wakeMode: "next-heartbeat":事件等待下次定时心跳。
适合需要普通心跳提示词 + 主会话上下文的场景。参见 Heartbeat(如有该页面)。
隔离任务(独立 cron 会话)
隔离任务在 cron:<jobId> 或自定义会话中运行独立的 agent 轮次。
关键行为:
- 提示词会加上
[cron:<jobId> <job name>]前缀,便于追踪。 - 每次运行使用全新 session id(无历史对话延续),自定义会话除外。
- 自定义会话(
session:xxx)跨次保留上下文,可实现类似"每日站会接续前次摘要"的工作流。 - 默认行为:若省略
delivery,隔离任务默认 announce 摘要(delivery.mode = "announce")。 delivery.mode决定后续处理:announce:通过出站渠道适配器直接投递摘要,并在主会话发布简短摘要。webhook:运行完成事件含摘要时,POST 到delivery.to。none:仅内部处理(无投递,无主会话摘要)。
wakeMode控制主会话摘要的发布时机:now:立即触发心跳。next-heartbeat:等待下次定时心跳。
对于嘈杂、高频或"后台杂务"类任务,用隔离模式避免污染主聊天记录。
载荷类型
支持两种载荷:
systemEvent:仅限主会话,通过心跳提示词路由。agentTurn:仅限隔离会话,运行独立 agent 轮次。
agentTurn 常用字段:
message:必填,提示词文本。model/thinking:可选覆盖(见下)。timeoutSeconds:可选超时覆盖。lightContext:可选轻量启动模式,适合不需要工作区 bootstrap 文件注入的任务。
交付配置:
delivery.mode:none|announce|webhook。delivery.channel:last或指定渠道。delivery.to:渠道特定目标(announce 模式)或 webhook URL(webhook 模式)。delivery.bestEffort:announce 交付失败时不让任务失败。
Announce 交付会抑制该次运行中 messaging 工具的发送;用 delivery.channel/delivery.to 指定目标聊天。delivery.mode = "none" 时不向主会话发布摘要。
若隔离任务省略 delivery,OpenClaw 默认使用 announce。
Announce 交付流程
delivery.mode = "announce" 时,cron 直接通过出站渠道适配器投递。主 agent 不会启动来转发消息。
行为细节:
- 内容:使用隔离运行的出站载荷(文本/媒体),按正常分块和渠道格式化。
- 仅含
HEARTBEAT_OK的响应(无实质内容)不会投递。 - 若隔离运行已通过 message 工具向同一目标发送了消息,则跳过投递以避免重复。
- 目标缺失或无效时任务失败,除非
delivery.bestEffort = true。 - 仅
delivery.mode = "announce"时才会向主会话发布简短摘要。 - 主会话摘要遵循
wakeMode:now触发立即心跳,next-heartbeat等待下次心跳。
Webhook 交付流程
delivery.mode = "webhook" 时,完成事件含摘要时,cron 将载荷 POST 到 delivery.to。
行为细节:
- 端点必须是合法的 HTTP(S) URL。
- Webhook 模式不尝试渠道投递。
- Webhook 模式不向主会话发布摘要。
- 若设置了
cron.webhookToken,Auth 头为Authorization: Bearer <cron.webhookToken>。 - 旧式降级:存储中
notify: true的任务仍会 POST 到cron.webhook(若已配置),并显示警告提示迁移。
模型与思考级别覆盖
隔离任务(agentTurn)可以覆盖模型和思考级别:
model:provider/模型字符串(如anthropic/claude-sonnet-4-20250514)或别名(如opus)thinking:思考级别(off、minimal、low、medium、high、xhigh;仅 GPT-5.2 + Codex 模型支持)
注意:主会话任务也可设置 model,但会改变共享的主会话模型。建议只在隔离任务上覆盖模型,避免上下文意外切换。
解析优先级:
- 任务载荷覆盖(最高)
- Hook 特定默认值(如
hooks.gmail.model) - Agent 配置默认值
轻量 bootstrap 上下文
隔离任务(agentTurn)可设置 lightContext: true 使用轻量 bootstrap 上下文。
- 适用于不需要工作区 bootstrap 文件注入的定时杂务。
- 实际上,内嵌运行时使用
bootstrapContextMode: "lightweight",有意保持 cron bootstrap 上下文为空。 - CLI 等价:
openclaw cron add --light-context ...和openclaw cron edit --light-context。
交付(渠道 + 目标)
隔离任务可通过顶层 delivery 配置将输出投递到渠道:
delivery.mode:announce(渠道投递)、webhook(HTTP POST)或none。delivery.channel:whatsapp/telegram/discord/slack/signal/imessage/irc/googlechat/line/last,以及扩展渠道如msteams/mattermost(插件)。delivery.to:渠道特定的接收目标。
announce 交付仅对隔离任务(sessionTarget: "isolated")有效。webhook 交付对主会话和隔离任务均有效。
若省略 delivery.channel 或 delivery.to,cron 可回退到主会话的"最后路由"(agent 最后一次回复的地方)。
目标格式提示:
- Slack/Discord/Mattermost(插件)目标应使用显式前缀(如
channel:<id>、user:<id>)以避免歧义。Mattermost 裸 26 字符 ID 优先解析为 user(若 user 存在则 DM,否则 channel)——建议用user:<id>或channel:<id>确保确定性路由。 - Telegram 话题应使用
:topic:格式(见下)。
Telegram 交付目标(话题 / 论坛帖子)
Telegram 通过 message_thread_id 支持论坛话题。cron 交付时可在 to 字段编码话题/帖子:
-1001234567890(仅 chat id)-1001234567890:topic:123(推荐:显式话题标记)-1001234567890:123(简写:数字后缀)
也接受带前缀的目标:
telegram:group:-1001234567890:topic:123
JSON schema(工具调用)
直接调用 Gateway cron.* 工具时(agent 工具调用或 RPC),使用以下格式。CLI 接受 20m 这样的人性化时间,但工具调用中 schedule.at 应使用 ISO 8601 字符串,schedule.everyMs 应使用毫秒数。
cron.add 参数
一次性主会话任务(系统事件):
json
{
"name": "Reminder",
"schedule": { "kind": "at", "at": "2026-02-01T16:00:00Z" },
"sessionTarget": "main",
"wakeMode": "now",
"payload": { "kind": "systemEvent", "text": "Reminder text" },
"deleteAfterRun": true
}周期性隔离任务(含交付):
json
{
"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.",
"lightContext": true
},
"delivery": {
"mode": "announce",
"channel": "slack",
"to": "channel:C1234567890",
"bestEffort": true
}
}绑定当前会话的周期性任务(创建时自动解析):
json
{
"name": "Daily standup",
"schedule": { "kind": "cron", "expr": "0 9 * * *" },
"sessionTarget": "current",
"payload": {
"kind": "agentTurn",
"message": "Summarize yesterday's progress."
}
}使用自定义持久化会话的周期性任务:
json
{
"name": "Project monitor",
"schedule": { "kind": "every", "everyMs": 300000 },
"sessionTarget": "session:project-alpha-monitor",
"payload": {
"kind": "agentTurn",
"message": "Check project status and update the running log."
}
}字段说明:
schedule.kind:at(at)、every(everyMs)或cron(expr,可选tz)。schedule.at接受 ISO 8601。工具/API 无时区值视为 UTC;CLI 支持openclaw cron add|edit --at "<offset-less-iso>" --tz <iana>的本地时钟一次性任务。everyMs单位为毫秒。sessionTarget:"main"、"isolated"、"current"或"session:<custom-id>"。"current"创建时解析为"session:<sessionKey>"。- 自定义会话(
session:xxx)跨次保留上下文。 - 可选字段:
agentId、description、enabled、deleteAfterRun(at类型默认 true)、delivery。 wakeMode省略时默认"now"。
cron.update 参数
json
{
"jobId": "job-123",
"patch": {
"enabled": false,
"schedule": { "kind": "every", "everyMs": 3600000 }
}
}说明:
jobId为标准字段,兼容id。- 用
agentId: null清除 agent 绑定。
cron.run 和 cron.remove 参数
json
{ "jobId": "job-123", "mode": "force" }json
{ "jobId": "job-123" }存储与历史
- 任务存储:
~/.openclaw/cron/jobs.json(Gateway 管理的 JSON)。 - 运行历史:
~/.openclaw/cron/runs/<jobId>.jsonl(JSONL,按大小和行数自动裁剪)。 sessions.json中的隔离 cron 运行会话由cron.sessionRetention清理(默认24h;设为false禁用)。- 覆盖存储路径:配置中的
cron.store。
重试策略
任务失败时,OpenClaw 将错误分类为瞬时(可重试)或永久(立即禁用)。
瞬时错误(重试)
- 速率限制(429、too many requests、resource exhausted)
- Provider 过载(如 Anthropic
529 overloaded_error、过载降级摘要) - 网络错误(超时、ECONNRESET、fetch failed、socket)
- 服务器错误(5xx)
- Cloudflare 相关错误
永久错误(不重试)
- 鉴权失败(无效 API key、未授权)
- 配置或校验错误
- 其他非瞬时错误
默认行为(无配置)
一次性任务(schedule.kind: "at"):
- 瞬时错误:最多重试 3 次,指数退避(30s → 1m → 5m)。
- 永久错误:立即禁用。
- 成功或跳过:禁用(
deleteAfterRun: true则删除)。
周期性任务(cron / every):
- 任何错误:对下次计划运行应用指数退避(30s → 1m → 5m → 15m → 60m)。
- 任务保持启用;下次成功运行后退避重置。
可通过 cron.retry 覆盖默认值(见配置)。
配置
json5
{
cron: {
enabled: true, // 默认 true
store: "~/.openclaw/cron/jobs.json",
maxConcurrentRuns: 1, // 默认 1
// 可选:覆盖一次性任务的重试策略
retry: {
maxAttempts: 3,
backoffMs: [60000, 120000, 300000],
retryOn: ["rate_limit", "overloaded", "network", "server_error"],
},
webhook: "https://example.invalid/legacy", // 旧式降级:notify:true 任务用
webhookToken: "replace-with-dedicated-webhook-token", // 可选 bearer token
sessionRetention: "24h", // 时间字符串或 false
runLog: {
maxBytes: "2mb", // 默认 2_000_000 字节
keepLines: 2000, // 默认 2000
},
},
}运行日志裁剪:
cron.runLog.maxBytes:裁剪前的运行日志文件最大大小。cron.runLog.keepLines:裁剪时保留最新 N 行。- 均作用于
cron/runs/<jobId>.jsonl文件。
Webhook 行为:
- 推荐:按任务设置
delivery.mode: "webhook"+delivery.to: "https://..."。 - Webhook URL 必须是合法的
http://或https://URL。 - POST 载荷为 cron finished event JSON。
- 若设置了
cron.webhookToken,Auth 头为Authorization: Bearer <cron.webhookToken>;否则不发Authorization头。 - 旧式降级:存储中
notify: true的任务仍使用cron.webhook(若存在)。
完全禁用 cron:
cron.enabled: false(配置)OPENCLAW_SKIP_CRON=1(环境变量)
维护
Cron 内置两条维护路径:隔离运行会话保留和运行日志裁剪。
默认值
cron.sessionRetention:24h(设为false禁用会话裁剪)cron.runLog.maxBytes:2_000_000字节cron.runLog.keepLines:2000
工作原理
- 隔离运行创建会话条目(
...:cron:<jobId>:run:<uuid>)和 transcript 文件。 - 清理器删除超过
cron.sessionRetention的旧会话条目。 - 对于已从会话存储中删除的运行会话,OpenClaw 归档 transcript 文件,并在同一保留窗口内清除旧的已删除归档。
- 每次追加运行记录后,检查
cron/runs/<jobId>.jsonl的大小:- 若超过
runLog.maxBytes,裁剪为最新runLog.keepLines行。
- 若超过
高频调度的性能注意事项
高频 cron 设置会产生大量运行会话和日志。维护是内置的,但宽松的限制仍会造成不必要的 IO 和清理工作。
需要关注:
- 隔离运行次数多且
cron.sessionRetention窗口长 cron.runLog.keepLines高且runLog.maxBytes大- 多个嘈杂周期任务写同一个
cron/runs/<jobId>.jsonl
建议:
- 根据调试/审计需要尽量缩短
cron.sessionRetention - 用适中的
runLog.maxBytes和runLog.keepLines限制日志大小 - 把嘈杂后台任务迁移到带交付规则的隔离模式,避免不必要的噪音
- 定期用
openclaw cron runs查看增长情况,在日志变大前调整保留策略
配置示例
保留运行会话一周,允许更大日志:
json5
{
cron: {
sessionRetention: "7d",
runLog: {
maxBytes: "10mb",
keepLines: 5000,
},
},
}禁用隔离运行会话裁剪,保留日志裁剪:
json5
{
cron: {
sessionRetention: false,
runLog: {
maxBytes: "5mb",
keepLines: 3000,
},
},
}高频 cron 调优示例:
json5
{
cron: {
sessionRetention: "12h",
runLog: {
maxBytes: "3mb",
keepLines: 1500,
},
},
}CLI 快速参考
一次性提醒(UTC ISO,成功后自动删除):
bash
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一次性提醒(主会话,立即唤醒):
bash
openclaw cron add \
--name "Calendar check" \
--at "20m" \
--session main \
--system-event "Next heartbeat: check calendar." \
--wake now周期性隔离任务(announce 到 WhatsApp):
bash
openclaw cron add \
--name "Morning status" \
--cron "0 7 * * *" \
--tz "America/Los_Angeles" \
--session isolated \
--message "Summarize inbox + calendar for today." \
--announce \
--channel whatsapp \
--to "+15551234567"带显式 30 秒错开的周期任务:
bash
openclaw cron add \
--name "Minute watcher" \
--cron "0 * * * * *" \
--tz "UTC" \
--stagger 30s \
--session isolated \
--message "Run minute watcher checks." \
--announce投递到 Telegram 话题的隔离任务:
bash
openclaw cron add \
--name "Nightly summary (topic)" \
--cron "0 22 * * *" \
--tz "America/Los_Angeles" \
--session isolated \
--message "Summarize today; send to the nightly topic." \
--announce \
--channel telegram \
--to "-1001234567890:topic:123"带模型和思考覆盖的隔离任务:
bash
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 \
--announce \
--channel whatsapp \
--to "+15551234567"Agent 选择(多 agent 场景):
bash
# 将任务绑定到 "ops" agent(找不到时回退默认 agent)
openclaw cron add --name "Ops sweep" --cron "0 6 * * *" --session isolated --message "Check ops queue" --agent ops
# 修改或清除现有任务的 agent
openclaw cron edit <jobId> --agent ops
openclaw cron edit <jobId> --clear-agent手动运行(默认强制,--due 仅在到期时运行):
bash
openclaw cron run <jobId>
openclaw cron run <jobId> --duecron.run 在手动运行入队后即返回确认,不等任务完成。成功入队响应形如 { ok: true, enqueued: true, runId }。若任务已在运行或 --due 未到期,响应为 { ok: true, ran: false, reason }。用 openclaw cron runs --id <jobId> 或 cron.runs 查看最终完成记录。
修改现有任务(patch 字段):
bash
openclaw cron edit <jobId> \
--message "Updated prompt" \
--model "opus" \
--thinking low强制现有任务按精确计划运行(无错开):
bash
openclaw cron edit <jobId> --exact查看运行历史:
bash
openclaw cron runs --id <jobId> --limit 50不创建任务直接发送系统事件:
bash
openclaw system event --mode now --text "Next heartbeat: check battery."Gateway API
cron.list、cron.status、cron.add、cron.update、cron.removecron.run(强制或到期时)、cron.runs无需创建任务直接发送系统事件,用openclaw system event(如有该页面)。
故障排查
"任务不执行"
- 检查 cron 是否启用:
cron.enabled和OPENCLAW_SKIP_CRON。 - 检查 Gateway 是否持续运行(cron 在 Gateway 进程内运行)。
cron调度:确认时区(--tz)与主机时区的关系。
周期任务在失败后持续延迟
- OpenClaw 对周期任务连续失败后应用指数退避重试:30s、1m、5m、15m,最后 60m。
- 下次成功运行后退避自动重置。
- 一次性(
at)任务对瞬时错误(速率限制、过载、网络、server_error)最多重试 3 次;永久错误立即禁用。参见重试策略。
Telegram 投递到了错误的地方
- 对论坛话题,使用
-100…:topic:<id>以确保明确无歧义。 - 若日志或存储的"last route"目标中出现
telegram:...前缀,这是正常现象;cron 交付能接受并正确解析话题 ID。
子 agent announce 交付重试
- 子 agent 运行完成后,gateway 向请求方会话发布结果。
- 若 announce 流程返回
false(如请求方会话正忙),gateway 通过announceRetryCount跟踪并最多重试 3 次。 - 超过
endedAt后 5 分钟的 announce 会强制过期,防止陈旧条目无限循环。 - 若日志中出现重复 announce 投递,检查子 agent 注册表中
announceRetryCount较高的条目。