OpenClaw 白皮书
定时任务(Gateway网关调度器)
定时任务还是心跳? 请参阅定时任务与心跳对比了解何时使用哪种方式。
定时任务是 Gateway网关内置的调度器。它持久化任务、在合适的时间唤醒智能体,并可选择将输出发送回聊天。
如果你想要 "每天早上运行" 或 "20 分钟后提醒智能体",定时任务就是对应的机制。
简要概述
- ✦定时任务运行在 Gateway网关内部(而非模型内部)。
- ✦任务持久化存储在
~/.openclaw/cron/下,因此重启不会丢失计划。 - ✦两种执行方式:
- ✦主会话:入队一个系统事件,然后在下一次心跳时运行。
- ✦隔离式:在
cron:<jobId>中运行专用智能体轮次,可投递摘要(默认 announce)或不投递。
- ✦唤醒是一等功能:任务可以请求"立即唤醒"或"下次心跳时"。
快速开始(可操作)
创建一个一次性提醒,验证其存在,然后立即运行:
bashopenclaw 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>
调度一个带投递功能的周期性隔离任务:
bashopenclaw 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网关定时任务工具)
有关规范的 JSON 结构和示例,请参阅工具调用的 JSON 模式。
定时任务的存储位置
定时任务默认持久化存储在 Gateway网关主机的
~/.openclaw/cron/jobs.json 中。Gateway网关将文件加载到内存中,并在更改时写回,因此仅在 Gateway网关停止时手动编辑才是安全的。请优先使用 openclaw cron add/edit 或定时任务工具调用 API 进行更改。新手友好概述
将定时任务理解为:何时运行 + 做什么。
- ✦
选择调度计划
- ✦一次性提醒 →
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"
- ✦主会话 →
可选:一次性任务(
schedule.kind = "at")默认会在成功运行后删除。设置
deleteAfterRun: false 可保留它(成功后会禁用)。概念
任务
定时任务是一条存储记录,包含:
- ✦一个调度计划(何时运行),
- ✦一个负载(做什么),
- ✦可选的投递(输出发送到哪里)。
- ✦可选的智能体绑定(
agentId):在指定智能体下运行任务;如果缺失或未知,Gateway网关会回退到默认智能体。
任务通过稳定的
jobId 标识(用于 CLI/Gateway网关 API)。
在智能体工具调用中,jobId 是规范字段;旧版 id 仍可兼容使用。
一次性任务默认会在成功运行后自动删除;设置 deleteAfterRun: false 可保留它。调度计划
定时任务支持三种调度类型:
- ✦
at:一次性时间戳(ISO 8601 字符串)。 - ✦
every:固定间隔(毫秒)。 - ✦
cron:5 字段 cron 表达式,可选 IANA 时区。
Cron 表达式使用
croner。如果省略时区,将使用 Gateway网关主机的本地时区。主会话与隔离式执行
主会话任务(系统事件)
主会话任务入队一个系统事件,并可选择唤醒心跳运行器。它们必须使用
payload.kind = "systemEvent"。- ✦
wakeMode: "next-heartbeat"(默认):事件等待下一次计划心跳。 - ✦
wakeMode: "now":事件触发立即心跳运行。
当你需要正常的心跳提示 + 主会话上下文时,这是最佳选择。参见心跳。
隔离任务(专用定时会话)
隔离任务在会话
cron:<jobId> 中运行专用智能体轮次。关键行为:
- ✦提示以
[cron:<jobId> <任务名称>]为前缀,便于追踪。 - ✦每次运行都会启动一个全新的会话 ID(不继承之前的对话)。
- ✦如果未指定
delivery,隔离任务会默认以“announce”方式投递摘要。 - ✦
delivery.mode可选announce(投递摘要)或none(内部运行)。
对于嘈杂、频繁或"后台杂务"类任务,使用隔离任务可以避免污染你的主聊天记录。
负载结构(运行内容)
支持两种负载类型:
- ✦
systemEvent:仅限主会话,通过心跳提示路由。 - ✦
agentTurn:仅限隔离会话,运行专用智能体轮次。
常用
agentTurn 字段:- ✦
message:必填文本提示。 - ✦
model/thinking:可选覆盖(见下文)。 - ✦
timeoutSeconds:可选超时覆盖。
模型和思维覆盖
隔离任务(
agentTurn)可以覆盖模型和思维级别:- ✦
model:提供商/模型字符串(例如anthropic/claude-sonnet-4-20250514)或别名(例如opus) - ✦
thinking:思维级别(off、minimal、low、medium、high、xhigh;仅限 GPT-5.2 + Codex 模型)
注意:你也可以在主会话任务上设置
model,但这会更改共享的主会话模型。我们建议仅对隔离任务使用模型覆盖,以避免意外的上下文切换。优先级解析顺序:
- ✦任务负载覆盖(最高优先级)
- ✦钩子特定默认值(例如
hooks.gmail.model) - ✦智能体配置默认值
投递(渠道 + 目标)
隔离任务可以通过顶层
delivery 配置投递输出:- ✦
delivery.mode:announce(投递摘要)或none - ✦
delivery.channel:whatsapp/telegram/discord/slack/mattermost(插件)/signal/imessage/last - ✦
delivery.to:渠道特定的接收目标 - ✦
delivery.bestEffort:投递失败时避免任务失败
当启用 announce 投递时,该轮次会抑制消息工具发送;请使用
delivery.channel/delivery.to 来指定目标。如果省略
delivery.channel 或 delivery.to,定时任务会回退到主会话的“最后路由”(智能体最后回复的位置)。目标格式提醒:
- ✦Slack/Discord/Mattermost(插件)目标应使用明确前缀(例如
channel:<id>、user:<id>)以避免歧义。 - ✦Telegram 主题应使用
:topic:格式(见下文)。
Telegram 投递目标(主题/论坛帖子)
Telegram 通过
message_thread_id 支持论坛主题。对于定时任务投递,你可以将主题/帖子编码到 to 字段中:- ✦
-1001234567890(仅聊天 ID) - ✦
-1001234567890:topic:123(推荐:明确的主题标记) - ✦
-1001234567890:123(简写:数字后缀)
带前缀的目标如
telegram:... / telegram:group:... 也可接受:- ✦
telegram:group:-1001234567890:topic:123
工具调用的 JSON 模式
直接调用 Gateway网关
cron.* 工具(智能体工具调用或 RPC)时使用这些结构。CLI 标志接受人类可读的时间格式如 20m,但工具调用应使用 ISO 8601 字符串作为 schedule.at,并使用毫秒作为 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." }, "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 参数
json{ "jobId": "job-123", "patch": { "enabled": false, "schedule": { "kind": "every", "everyMs": 3600000 } } }
说明:
- ✦
jobId是规范字段;id可兼容使用。 - ✦在补丁中使用
agentId: null可清除智能体绑定。
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,自动清理)。 - ✦覆盖存储路径:配置中的
cron.store。
配置
json5{ cron: { enabled: true, // 默认 true store: "~/.openclaw/cron/jobs.json", maxConcurrentRuns: 1, // 默认 1 }, }
完全禁用定时任务:
- ✦
cron.enabled: false(配置) - ✦
OPENCLAW_SKIP_CRON=1(环境变量)
CLI 快速开始
一次性提醒(UTC ISO,成功后自动删除):
bashopenclaw cron add \ --name "Send reminder" \ --at "2026-01-12T18:00:00Z" \ --session main \ --system-event "Reminder: submit expense report." \ --wake now \ --delete-after-run
一次性提醒(主会话,立即唤醒):
bashopenclaw cron add \ --name "Calendar check" \ --at "20m" \ --session main \ --system-event "Next heartbeat: check calendar." \ --wake now
周期性隔离任务(投递到 WhatsApp):
bashopenclaw 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"
周期性隔离任务(投递到 Telegram 主题):
bashopenclaw 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"
带模型和思维覆盖的隔离任务:
bashopenclaw 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"
智能体选择(多智能体配置):
bash# 将任务绑定到智能体 "ops"(如果该智能体不存在则回退到默认智能体) 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
手动运行(调试):
bashopenclaw cron run <jobId> --force
编辑现有任务(补丁字段):
bashopenclaw cron edit <jobId> \ --message "Updated prompt" \ --model "opus" \ --thinking low
运行历史:
bashopenclaw cron runs --id <jobId> --limit 50
不创建任务直接发送系统事件:
bashopenclaw system event --mode now --text "Next heartbeat: check battery."
Gateway网关 API 接口
- ✦
cron.list、cron.status、cron.add、cron.update、cron.remove - ✦
cron.run(强制或到期)、cron.runs如需不创建任务直接发送系统事件,请使用openclaw system event。
故障排除
"没有任何任务运行"
- ✦检查定时任务是否已启用:
cron.enabled和OPENCLAW_SKIP_CRON。 - ✦检查 Gateway网关是否持续运行(定时任务运行在 Gateway网关进程内部)。
- ✦对于
cron调度:确认时区(--tz)与主机时区的关系。
Telegram 投递到了错误的位置
- ✦对于论坛主题,使用
-100…:topic:<id>以确保明确无歧义。 - ✦如果你在日志或存储的"最后路由"目标中看到
telegram:...前缀,这是正常的;定时任务投递接受这些前缀并仍能正确解析主题 ID。