Cron与心跳? 请参阅 Cron与心跳,以获取关于何时使用每种机制的指导。Cron是网关内置的调度器。它会持久化作业,在正确的时间唤醒代理,并可选择性地将输出发送回聊天中。 如果你想实现“每天早上运行一次”或“在20分钟后唤醒代理”,那么Cron就是你要使用的机制。
简而言之
- Cron 在网关内部运行(而非在模型内部)。
- 作业会在
~/.openclaw/cron/下持久化,因此即使重启,计划也不会丢失。 - 支持两种执行方式:
- 主会话:将系统事件加入队列,并在下一次心跳时执行。
- 隔离:在
cron:<jobId>中运行一个专用的代理回合,并可选择性地传递输出。
- 唤醒被视为一等公民:作业可以请求“立即唤醒”或“在下一次心跳时唤醒”。
适合初学者的概览
可以将 cron 作业看作:何时运行 + 做什么。- 选择计划
- 一次性提醒 →
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 会从存储中移除成功的一次性作业。
概念
作业
Cron 作业是一个存储记录,包含:- 计划(何时运行),
- 负载(要执行的内容),
- 可选的 交付(输出应发送到何处)。
- 可选的 代理绑定(
agentId):在特定代理下运行作业;如果未指定或未知,网关将回退到默认代理。
jobId 标识(用于 CLI/网关 API)。在代理工具调用中,jobId 是规范;为兼容性保留了旧版 id。作业在成功完成一次性运行后,可通过 deleteAfterRun: true 自动删除。
计划
Cron 支持三种计划类型:at:一次性时间戳(自纪元以来的毫秒数)。网关接受 ISO 8601 并强制转换为 UTC。every:固定间隔(毫秒)。cron:带有可选 IANA 时区的 5 字段 cron 表达式。
croner。如果未指定时区,则使用网关主机的本地时区。
主会话与隔离执行
主会话作业(系统事件)
主会话作业会将系统事件加入队列,并可选择性地唤醒心跳运行程序。它们必须使用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。 - 当存在
to时,使用deliver: false来保持输出在内部。
- Slack/Discord/Mattermost(插件)目标应使用显式前缀(例如
channel:<id>、user:<id>),以避免歧义。 - Telegram 主题应使用
:topic:格式(见下文)。
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: false(配置)OPENCLAW_SKIP_CRON=1(环境)
网关 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)与主机时区一致。
- 对于论坛主题,使用
-100…:topic:<id>,使其明确且无歧义。 - 如果你在日志或存储的“最后路由”目标中看到
telegram:...前缀,这是正常的;