10.6 Cron定时任务

Cron 是 Gateway 内置的调度器。它持久化任务,在正确的时间唤醒代理,并可以选择将输出发送回聊天频道。如果您想要"每天早上运行"或"20分钟后提醒代理",cron 就是您需要的机制。

提示
Cron vs Heartbeat?查看 Cron 与心跳对比 了解何时使用哪种方式。

核心要点

  • Cron 运行在 Gateway 内部(不在模型内部)。
  • 任务持久化在 ~/.openclaw/cron/ 下,因此重启不会丢失调度。
  • 两种执行方式:
    • 主会话:将系统事件加入队列,然后在下一次心跳运行。
    • 隔离:在 cron:<jobId> 中运行专用的代理轮次,可选择交付输出。
  • 唤醒机制是一等公民:任务可以请求"立即唤醒"或"下次心跳"。

快速开始

创建一次性提醒,验证它存在,并立即运行:

openclaw cron add \
  --name "提醒" \
  --at "2026-02-01T16:00:00Z" \
  --session main \
  --system-event "提醒:检查 cron 文档草稿" \
  --wake now \
  --delete-after-run

openclaw cron list
openclaw cron run <job-id> --force
openclaw cron runs --id <job-id>

安排一个带交付的周期性隔离任务:

openclaw cron add \
  --name "晨报" \
  --cron "0 7 * * *" \
  --tz "America/Los_Angeles" \
  --session isolated \
  --message "总结隔夜更新。" \
  --deliver \
  --channel slack \
  --to "channel:C1234567890"

任务存储位置

Cron 任务默认持久化在 Gateway 主机的 ~/.openclaw/cron/jobs.json。Gateway 将文件加载到内存中,并在更改时写回,因此手动编辑仅在 Gateway 停止时安全。建议使用 openclaw cron add/edit 或 cron 工具调用 API 进行更改。

基础概念

任务(Jobs)

一个 cron 任务是一个存储记录,包含:

  • 调度(schedule):何时运行
  • 负载(payload):做什么
  • 交付(delivery):输出发送到哪里(可选)
  • 代理绑定(agentId):在特定代理下运行任务(可选);如果缺失或未知,网关将回退到默认代理。

任务通过稳定的 jobId 标识(CLI/Gateway API 使用)。在代理工具调用中,jobId 是规范的;传统的 id 为兼容性而接受。任务可以通过 deleteAfterRun: true 在成功的一次性运行后自动删除。

调度类型

Cron 支持三种调度类型:

  • at:一次性时间戳(epoch 毫秒)。Gateway 接受 ISO 8601 并强制转换为 UTC。
  • every:固定间隔(毫秒)。
  • cron:5字段 cron 表达式,带可选的 IANA 时区。

Cron 表达式使用 croner。如果省略时区,则使用 Gateway 主机的本地时区。

主会话 vs 隔离执行

主会话任务(系统事件)

主任务将系统事件加入队列,并可选择唤醒心跳运行器。它们必须使用 payload.kind = "systemEvent"

  • wakeMode: "next-heartbeat"(默认):事件等待下一次计划的心跳。
  • wakeMode: "now":事件触发立即的心跳运行。

当您希望正常的心跳提示 + 主会话上下文时,这是最佳选择。

隔离任务(专用 cron 会话)

隔离任务在会话 cron:<jobId> 中运行专用的代理轮次。

关键行为:

  • 提示以 [cron:<jobId> <任务名称>] 为前缀,便于追踪。
  • 每次运行都启动全新的会话 ID(没有先前对话的延续)。
  • 摘要发布到主会话(前缀 Cron,可配置)。
  • wakeMode: "now" 在发布摘要后触发立即的心跳。
  • 如果 payload.deliver: true,输出交付到频道;否则保持内部。

对于嘈杂、频繁或不应充斥主聊天历史的"后台任务",使用隔离任务。

负载形式

支持两种负载类型:

  • systemEvent:仅主会话,通过心跳提示路由。
  • agentTurn:仅隔离会话,运行专用的代理轮次。

常见的 agentTurn 字段:

  • message:必需的文本提示。
  • model / thinking:可选覆盖(见下文)。
  • timeoutSeconds:可选超时覆盖。
  • delivertrue 将输出发送到频道目标。
  • channellast 或特定频道。
  • to:频道特定目标(电话/聊天/频道 ID)。
  • bestEffortDeliver:避免在交付失败时任务失败。

模型和思考覆盖

隔离任务(agentTurn)可以覆盖模型和思考级别:

  • model:提供商/模型字符串(例如,anthropic/claude-sonnet-4-20250514)或别名(例如,opus
  • thinking:思考级别(offminimallowmediumhighxhigh;仅 GPT-5.2 + Codex 模型)

交付(频道 + 目标)

隔离任务可以将输出交付到频道。任务负载可以指定:

  • channelwhatsapp / telegram / discord / slack / mattermost(插件)/ signal / imessage / last
  • to:频道特定的接收者目标

Telegram 交付目标(主题/论坛线程)

Telegram 通过 message_thread_id 支持论坛主题。对于 cron 交付,您可以将主题/线程编码到 to 字段中:

  • -1001234567890(仅聊天 ID)
  • -1001234567890:topic:123(首选:显式主题标记)
  • -1001234567890:123(简写:数字后缀)

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 "下次心跳:检查电池。"

配置

{
  "cron": {
    "enabled": true,  // 默认 true
    "store": "~/.openclaw/cron/jobs.json",
    "maxConcurrentRuns": 1  // 默认 1
  }
}

完全禁用 cron:

  • cron.enabled: false(配置)
  • OPENCLAW_SKIP_CRON=1(环境变量)

存储与历史

  • 任务存储:~/.openclaw/cron/jobs.json(Gateway 管理的 JSON)。
  • 运行历史:~/.openclaw/cron/runs/<jobId>.jsonl(JSONL,自动修剪)。
  • 覆盖存储路径:配置中的 cron.store

故障排除

"什么都没运行"

  • 检查 cron 是否启用:cron.enabledOPENCLAW_SKIP_CRON
  • 检查 Gateway 是否持续运行(cron 在 Gateway 进程内运行)。
  • 对于 cron 调度:确认时区(--tz)与主机时区。

Telegram 交付到错误的位置

  • 对于论坛主题,使用 -100…:topic:<id> 使其显式且明确。
  • 如果您在日志或存储的"最后路由"目标中看到 telegram:... 前缀,这是正常的;cron 交付接受它们并仍然正确解析主题 ID。