Cron 任务(Gateway 调度器)
Cron vs Heartbeat? 有关何时使用每个功能的指导,请参阅 Cron vs Heartbeat。
Cron 是 Gateway 的内置调度器。它持久化任务,在正确的时间唤醒代理, 并可以选择将输出传递回聊天。
如果您想要*"每天早上运行这个"或"在 20 分钟后提醒代理"*, cron 就是这种机制。
TL;DR
- Cron 在 Gateway 内部运行(不在模型内部)。
- 任务持久化在
~/.clawdbot/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/Gateway API 使用)。 在代理工具调用中,jobId 是规范的;为兼容性接受旧的 id。 任务可以通过 deleteAfterRun: true 在成功的一次性运行后自动删除。
计划
Cron 支持三种计划类型:
at:一次性时间戳(自纪元以来的毫秒数)。Gateway 接受 ISO 8601 并强制转换为 UTC。every:固定间隔(毫秒)。cron:5 字段 cron 表达式,带有可选的 IANA 时区。
Cron 表达式使用 croner。如果省略时区,则使用 Gateway 主机的 本地时区。
主会话与隔离执行
主会话任务(系统事件)
主任务将系统事件加入队列,并可选地唤醒心跳运行器。 它们必须使用 payload.kind = "systemEvent"。
wakeMode: "next-heartbeat"(默认):事件等待下一个计划的心跳。wakeMode: "now":事件触发立即的心跳运行。
当您想要正常的心跳提示 + 主会话上下文时,这是最佳选择。 请参阅 Heartbeat。
隔离任务(专用的 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:形式(见下文)。
Telegram 传递目标(主题 / 论坛线程)
Telegram 通过 message_thread_id 支持论坛主题。对于 cron 传递,您可以将 主题/线程编码到 to 字段中:
-1001234567890(仅聊天 ID)-1001234567890:topic:123(首选:明确主题标记)-1001234567890:123(简写:数字后缀)
带有前缀的目标如 telegram:... / telegram:group:... 也被接受:
telegram:group:-1001234567890:topic:123
存储和历史记录
- 任务存储:
~/.clawdbot/cron/jobs.json(Gateway 管理的 JSON)。 - 运行历史记录:
~/.clawdbot/cron/runs/<jobId>.jsonl(JSONL,自动修剪)。 - 覆盖存储路径:配置中的
cron.store。
配置
{
cron: {
enabled: true, // 默认 true
store: "~/.clawdbot/cron/jobs.json",
maxConcurrentRuns: 1 // 默认 1
}
}完全禁用 cron:
cron.enabled = false(配置)CLAWDBOT_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"
代理选择(多代理设置):
```bash
# 将任务固定到代理 "ops"(如果该代理缺失则回退到默认)
openclaw cron add --name "运维扫描" --cron "0 6 * * *" --session isolated --message "检查运维队列" --agent ops
# 在现有任务上切换或清除代理
openclaw cron edit <jobId> --agent ops
openclaw cron edit <jobId> --clear-agent
手动运行(调试):
```bash
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 "下一个心跳:检查电池。"Gateway API surface
cron.list,cron.status,cron.add,cron.update,cron.removecron.run(force or due),cron.runsFor immediate system events without a job, useopenclaw system event.
Troubleshooting
“Nothing runs”
- Check cron is enabled:
cron.enabledandCLAWDBOT_SKIP_CRON. - Check the Gateway is running continuously (cron runs inside the Gateway process).
- For
cronschedules: confirm timezone (--tz) vs the host timezone.
Telegram delivers to the wrong place
- For forum topics, use
-100…:topic:<id>so it’s explicit and unambiguous. - If you see
telegram:...prefixes in logs or stored “last route” targets, that’s normal; cron delivery accepts them and still parses topic IDs correctly.