定时任务(网关调度器)
Cron vs Heartbeat? 有关何时使用每个,请参阅 Cron vs Heartbeat。
Cron 是网关的内置调度器。它持久化任务、在正确时间唤醒智能体,并可选择将输出返回到聊天。
如果你想要 "每天早上运行这个" 或 "20 分钟后戳一下智能体",cron 就是这个机制。
TL;DR
- Cron 在网关内部运行(不在模型内部)。
- 任务持久化在
~/.openclaw/cron/下,重启不会丢失计划。 - 两种执行风格:
- 主会话:将系统事件加入队列,然后在下次心跳时运行。
- 隔离:在
cron:<jobId>中运行专用智能体轮次,可选择交付输出。
- 唤醒是一等公民:任务可以请求"立即唤醒"vs"下次心跳"。
面向初学者的概述
将定时任务视为:何时运行 + 做什么。
选择计划
- 一次性提醒 →
schedule.kind = "at"(CLI:--at) - 重复任务 →
schedule.kind = "every"或schedule.kind = "cron" - 如果你的 ISO 时间戳缺少时区,它被视为 UTC。
- 一次性提醒 →
选择运行位置
sessionTarget: "main"→ 在下次心跳时使用主上下文运行。sessionTarget: "isolated"→ 在cron:<jobId>中运行专用智能体轮次。
选择负载
- 主会话 →
payload.kind = "systemEvent" - 隔离会话 →
payload.kind = "agentTurn"
- 主会话 →
可选:deleteAfterRun: true 在成功后删除一次性任务。
概念
任务
定时任务是带有以下内容的存储记录:
- 计划(何时运行),
- 负载(做什么),
- 可选 交付(输出发送到哪里)。
- 可选 智能体绑定(
agentId):在特定智能体下运行任务;如果缺失或未知,网关回退到默认智能体。
任务由稳定的 jobId 标识(由 CLI/网关 API 使用)。在智能体工具调用中,jobId 是规范形式;遗留的 id 被接受用于兼容。任务可以通过 deleteAfterRun: true 在一次性运行成功后自动删除。
计划
Cron 支持三种计划类型:
at:一次性时间戳(自纪元以来的毫秒)。网关接受 ISO 8601 并强制转换为 UTC。every:固定间隔(毫秒)。cron:带可选 IANA 时区的 5 字段 cron 表达式。
Cron 表达式使用 croner。如果省略时区,使用网关主机的本地时区。
主会话 vs 隔离执行
主会话任务(系统事件)
主任务将系统事件加入队列,可选择唤醒心跳运行器。它们必须使用 payload.kind = "systemEvent"。
wakeMode: "next-heartbeat"(默认):事件等待下次计划心跳。wakeMode: "now":事件触发立即心跳运行。
这是你想要正常心跳提示 + 主会话上下文时的最佳选择。见心跳。
隔离任务(专用 cron 会话)
隔离任务在会话 cron:<jobId> 中运行专用智能体轮次。
关键行为:
- 提示以
[cron:<jobId> <job name>]为前缀以便追踪。 - 每次运行开始一个新的会话 ID(没有先前的对话延续)。
- 摘要发布到主会话(前缀
Cron,可配置)。 wakeMode: "now"在发布摘要后触发立即心跳。- 如果
payload.deliver: true,输出被交付到通道;否则保留在内部。
对嘈杂、频繁或"后台杂务"使用隔离任务,这些不应该垃圾你主要的聊天历史。
负载形状(运行什么)
支持两种负载类型:
systemEvent:仅主会话,通过心跳提示路由。agentTurn:仅隔离会话,运行专用智能体轮次。
常见 agentTurn 字段:
message:必需的文字提示。model/thinking:可选覆盖(见下文)。timeoutSeconds:可选超时覆盖。deliver:true以将输出发送到通道目标。channel:last或特定通道。to:通道特定目标(电话/聊天/通道 ID)。bestEffortDeliver:避免在交付失败时使任务失败。
隔离选项(仅用于 session=isolated):
postToMainPrefix(CLI:--post-prefix):主会话中系统事件的前缀。postToMainMode:summary(默认)或full。postToMainMaxChars:postToMainMode=full时的最大字符数(默认 8000)。
模型和思考覆盖
隔离任务(agentTurn)可以覆盖模型和思考级别:
model:提供商/模型字符串(例如anthropic/claude-sonnet-4-20250514)或别名(例如opus)thinking:思考级别(off、minimal、low、medium、high、xhigh;仅 GPT-5.2 + Codex 模型)
注意:你也可以在主会话任务上设置 model,但它会改变共享的主会话模型。我们建议仅对隔离任务使用模型覆盖,以避免意外的上下文切换。
解析优先级:
- 任务负载覆盖(最高)
- 钩子特定默认值(例如
hooks.gmail.model) - 智能体配置默认值
交付(通道 + 目标)
隔离任务可以将输出交付到通道。任务负载可以指定:
channel:whatsapp/telegram/discord/slack/mattermost(插件) /signal/imessage/lastto:通道特定接收者目标
如果 channel 或 to 省略,cron 可以回退到主会话的"最后路由"(智能体最后回复的地方)。
交付说明:
- 如果设置了
to,cron 自动交付智能体的最终输出,即使deliver被省略。 - 当你想要最后路由交付而没有显式
to时使用deliver: true。 - 使用
deliver: false以在存在to时也保持输出内部。
目标格式提醒:
- Slack/Discord/Mattermost(插件)目标应使用显式前缀(例如
channel:<id>、user:<id>)以避免歧义。 - Telegram 主题应使用
:topic:形式(见下文)。
Telegram 交付目标(主题 / 论坛线程)
Telegram 通过 message_thread_id 支持论坛主题。对于 cron 交付,你可以将主题/线程编码到 to 字段中:
-1001234567890(仅聊天 ID)-1001234567890:topic:123(首选:显式主题标记)-1001234567890:123(简写:数字后缀)
带前缀的目标如 telegram:... / telegram:group:... 也被接受:
telegram:group:-1001234567890:topic:123
存储和历史
- 任务存储:
~/.openclaw/cron/jobs.json(网关管理的 JSON)。 - 运行历史:
~/.openclaw/cron/runs/<jobId>.jsonl(JSONL,自动修剪)。 - 覆盖存储路径:配置中的
cron.store。
配置
{
cron: {
enabled: true, // 默认 true
store: "~/.openclaw/cron/jobs.json",
maxConcurrentRuns: 1 // 默认 1
}
}完全禁用 cron:
cron.enabled: false(配置)OPENCLAW_SKIP_CRON=1(环境变量)
CLI 快速开始
一次性提醒(UTC ISO,成功后自动删除):
openclaw cron add \
--name "发送提醒" \
--at "2026-01-12T18:00:00Z" \
--session main \
--system-event "提醒:提交费用报告。" \
--wake now \
--delete-after-run一次性提醒(主会话,立即唤醒):
openclaw cron add \
--name "日历检查" \
--at "20m" \
--session main \
--system-event "下次心跳:检查日历。" \
--wake now重复隔离任务(交付到 WhatsApp):
openclaw cron add \
--name "早晨状态" \
--cron "0 7 * * *" \
--tz "America/Los_Angeles" \
--session isolated \
--message "总结今天的收件箱 + 日历。" \
--deliver \
--channel whatsapp \
--to "+15551234567"重复隔离任务(交付到 Telegram 主题):
openclaw cron add \
--name "夜间摘要(主题)" \
--cron "0 22 * * *" \
--tz "America/Los_Angeles" \
--session isolated \
--message "总结今天;发送到夜间主题。" \
--deliver \
--channel telegram \
--to "-1001234567890:topic:123"带模型和思考覆盖的隔离任务:
openclaw cron add \
--name "深度分析" \
--cron "0 6 * * 1" \
--tz "America/Los_Angeles" \
--session isolated \
--message "项目进度的每周深度分析。" \
--model "opus" \
--thinking high \
--deliver \
--channel whatsapp \
--to "+15551234567"智能体选择(多智能体设置):
# 将任务固定到智能体 "ops"(如果该智能体缺失则回退到默认)
openclaw cron add --name "Ops 巡查" --cron "0 6 * * *" --session isolated --message "检查 ops 队列" --agent ops
# 在现有任务上切换或清除智能体
openclaw cron edit <jobId> --agent ops
openclaw cron edit <jobId> --clear-agent手动运行(调试):
openclaw cron run <jobId> --force编辑现有任务(修补字段):
openclaw cron edit <jobId> \
--message "更新后的提示" \
--model "opus" \
--thinking low运行历史:
openclaw cron runs --id <jobId> --limit 50立即系统事件而不创建任务:
openclaw system event --mode now --text "下次心跳:检查电池。"网关 API 表面
cron.list、cron.status、cron.add、cron.update、cron.removecron.run(强制或到期)、cron.runs对于没有任务的立即系统事件,使用openclaw system event。
故障排除
"什么都没运行"
- 检查 cron 已启用:
cron.enabled和OPENCLAW_SKIP_CRON。 - 检查网关持续运行(cron 在网关进程内部运行)。
- 对于
cron计划:确认时区(--tz)vs 主机时区。
Telegram 交付到错误位置
- 对于论坛主题,使用
-100…:topic:<id>以使其明确且无歧义。 - 如果你在日志或存储的"最后路由"目标中看到
telegram:...前缀,这是正常的;cron 交付接受它们并仍正确解析主题 ID。
工具调用的 JSON 模式
直接调用 Gateway 网关 cron.* 工具(智能体工具调用或 RPC)时使用这些结构。CLI 标志接受人类可读的时间格式如 20m,但工具调用应使用 ISO 8601 字符串作为 schedule.at,并使用毫秒作为 schedule.everyMs。
cron.add 参数
一次性主会话任务(系统事件):
{
"name": "Reminder",
"schedule": { "kind": "at", "at": "2026-02-01T16:00:00Z" },
"sessionTarget": "main",
"wakeMode": "now",
"payload": { "kind": "systemEvent", "text": "Reminder text" },
"deleteAfterRun": true
}带投递的周期性隔离任务:
{
"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."
},
"delivery": {
"mode": "announce",
"channel": "slack",
"to": "channel:C1234567890",
"bestEffort": true
}
}说明:
schedule.kind:at(at)、every(everyMs)或cron(expr,可选tz)。schedule.at接受 ISO 8601(可省略时区;省略时按 UTC 处理)。everyMs为毫秒数。sessionTarget必须为"main"或"isolated",且必须与payload.kind匹配。- 可选字段:
agentId、description、enabled、deleteAfterRun、delivery。 wakeMode省略时默认为"next-heartbeat"。
cron.update 参数
{
"jobId": "job-123",
"patch": {
"enabled": false,
"schedule": { "kind": "every", "everyMs": 3600000 }
}
}cron.run 和 cron.remove 参数
{ "jobId": "job-123", "mode": "force" }{ "jobId": "job-123" }快速开始(可操作)
创建一个一次性提醒,验证其存在,然后立即运行:
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>调度一个带投递功能的周期性隔离任务:
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"