Cron 是 Gateway 内置的调度器。它会持久化作业,在正确的时间唤醒 agent,并且可以将输出返回到聊天频道或 webhook 端点。Documentation Index
Fetch the complete documentation index at: https://openclaw.zhcndoc.com/llms.txt
Use this file to discover all available pages before exploring further.
快速开始
Cron 的工作方式
- Cron 运行在 Gateway 进程内(不在模型内)。
- 作业定义持久化在
~/.openclaw/cron/jobs.json,因此重启不会丢失计划。 - 运行时执行状态会持久化在旁边的
~/.openclaw/cron/jobs-state.json。如果你在 git 中跟踪 cron 定义,请跟踪jobs.json并将jobs-state.json加入 gitignore。 - 在拆分之后,较旧的 OpenClaw 版本可以读取
jobs.json,但可能会把作业视为新的,因为运行时字段现在位于jobs-state.json中。 - 当 Gateway 正在运行或已停止时编辑了
jobs.json,OpenClaw 会将变更后的计划字段与待处理的运行时槽位元数据进行比较,并清除过时的nextRunAtMs值。仅格式化或仅键顺序重写会保留待处理槽位。 - 所有 cron 执行都会创建 后台任务 记录。
- 在 Gateway 启动时,已过期的独立 agent-turn 作业会被重新调度到 channel-connect 窗口之外,而不是立即回放,因此 Discord/Telegram 启动和 native-command 设置在重启后仍能保持响应。
- 一次性作业(
--at)默认会在成功后自动删除。 - 独立 cron 运行会尽最大努力在运行完成时关闭其
cron:<jobId>会话所跟踪的浏览器标签页/进程,因此分离的浏览器自动化不会留下孤儿进程。 - 独立 cron 运行还会防止过时的确认回复。如果第一个结果只是一个中间状态更新(
on it、pulling everything together以及类似提示),并且没有后代子 agent 运行仍然负责最终答案,OpenClaw 会在交付前再提示一次以获取真实结果。 - 独立 cron 运行优先使用嵌入式运行中的结构化执行拒绝元数据,然后回退到已知的最终摘要/输出标记,例如
SYSTEM_RUN_DENIED和INVALID_REQUEST,因此被阻止的命令不会被报告为成功运行。 - 独立 cron 运行还会将运行级别的 agent 失败视为作业错误,即使没有生成回复载荷也是如此,因此模型/提供方失败会增加错误计数并触发失败通知,而不是将作业清除为成功。
- 当独立 agent-turn 作业达到
timeoutSeconds时,cron 会中止底层 agent 运行,并给予其一个短暂的清理窗口。如果运行未能完成收尾,Gateway 拥有的清理会在 cron 记录超时之前强制清除该运行的会话所有权,因此排队的聊天工作不会被遗留在一个过时的处理会话之后。
Cron 的任务协调首先由运行时拥有,其次才由持久历史支持:只要 cron 运行时仍然将该作业视为正在运行,活动的 cron 任务就会保持存活,即使旧的子会话行仍然存在。一旦运行时不再拥有该作业并且 5 分钟宽限期已过,维护检查会针对匹配的
cron:<jobId>:<startedAt> 运行去查看持久化运行日志和作业状态。如果这些持久化历史显示了终态结果,任务账本就会据此完成;否则,由 Gateway 拥有的维护可以将任务标记为 lost。离线 CLI 审计可以从持久历史中恢复,但它不会把自己进程内空的活动作业集合视为 Gateway 拥有的 cron 运行已消失的证明。计划类型
| 类型 | CLI 标志 | 描述 |
|---|---|---|
at | --at | 一次性时间戳(ISO 8601 或相对时间,如 20m) |
every | --every | 固定间隔 |
cron | --cron | 5 字段或 6 字段 cron 表达式,可选 --tz |
--tz America/New_York 可按本地墙钟时间调度。
每小时整点的重复表达式会自动错峰,最多延迟 5 分钟,以减少负载峰值。使用 --exact 强制精确时间,或使用 --stagger 30s 指定明确的窗口。
月中的日期和星期采用 OR 逻辑
Cron 表达式由 croner 解析。当“月中的日期”和“星期”字段都不是通配符时,croner 在任一字段匹配时就会认为匹配——而不是两个都匹配。这是标准的 Vixie cron 行为。+ 星期修饰符(0 9 15 * +1),或者只在一个字段上调度,并在作业的提示或命令中对另一个条件进行守卫。
执行样式
| 样式 | --session 值 | 运行位置 | 最适合 |
|---|---|---|---|
| 主会话 | main | 下一个 heartbeat turn | 提醒、系统事件 |
| 独立 | isolated | 专用 cron:<jobId> | 报告、后台杂务 |
| 当前会话 | current | 创建时绑定 | 具备上下文感知的重复工作 |
| 自定义会话 | session:custom-id | 持久命名会话 | 基于历史构建的工作流 |
主会话 vs 独立 vs 自定义
主会话 vs 独立 vs 自定义
主会话 作业会入队一个系统事件,并可选地唤醒 heartbeat(
--wake now 或 --wake next-heartbeat)。这些系统事件不会延长目标会话的每日/空闲重置新鲜度。独立 作业会以新的会话运行一个专用 agent turn。自定义会话(session:xxx)会在多次运行之间保留上下文,从而支持诸如每日站会这类基于之前总结继续推进的工作流。“新鲜会话”对独立作业意味着什么
“新鲜会话”对独立作业意味着什么
对于独立作业,“新鲜会话”意味着每次运行都会有一个新的 transcript/session id。OpenClaw 可能会沿用一些安全偏好,例如 thinking/fast/verbose 设置、标签,以及用户明确选择的模型/认证覆盖项,但它不会继承来自旧 cron 行的环境对话上下文:频道/群组路由、发送或排队策略、提升权限、来源或 ACP 运行时绑定。当重复作业应有意基于同一对话上下文构建时,请使用
current 或 session:<id>。运行时清理
运行时清理
对于独立作业,运行时收尾现在包括对该 cron 会话尽最大努力进行浏览器清理。清理失败会被忽略,因此实际的 cron 结果仍然优先。独立 cron 运行还会通过共享的运行时清理路径,处置为作业创建的任何捆绑 MCP 运行时实例。这与主会话和自定义会话的 MCP 客户端收尾方式一致,因此独立 cron 作业不会在多次运行之间泄漏 stdio 子进程或长期存在的 MCP 连接。
子 agent 和 Discord 交付
子 agent 和 Discord 交付
当独立 cron 运行协调子 agent 时,交付也会优先使用最终的后代输出,而不是过时的父级中间文本。如果后代仍在运行,OpenClaw 会抑制那条部分父级更新,而不是把它宣布出去。对于仅文本的 Discord announce 目标,OpenClaw 只发送一次规范的最终助手文本,而不会同时重放流式/中间文本载荷和最终答案。媒体和结构化 Discord 载荷仍会作为单独载荷交付,因此附件和组件不会被丢弃。
独立作业的载荷选项
提示文本(独立模式必需)。
模型覆盖;为该作业使用所选的允许模型。
thinking 级别覆盖。
跳过 workspace bootstrap 文件注入。
限制作业可使用的工具,例如
--tools exec,read。--model 会使用所选的允许模型作为该作业的主模型。它与聊天会话中的 /model 覆盖不同:当作业主模型失败时,配置的后备链仍然适用。如果请求的模型不被允许或无法解析,cron 会以明确的验证错误失败该运行,而不是静默回退到作业的 agent/default 模型选择。
Cron 作业还可以携带载荷级别的 fallbacks。存在时,该列表会替换该作业的配置后备链。若希望只尝试所选模型的严格 cron 运行,请在作业载荷/API 中使用 fallbacks: []。如果作业有 --model 但既没有载荷后备也没有配置后备,OpenClaw 会传递一个显式的空后备覆盖,以便不会把 agent 主模型附加为隐藏的额外重试目标。
独立作业的模型选择优先级为:
- Gmail hook 模型覆盖(当运行来自 Gmail 且该覆盖被允许时)
- 每个作业的载荷
model - 用户选择的已存储 cron 会话模型覆盖
- Agent/default 模型选择
params.fastMode,独立 cron 会默认使用它。已存储的会话 fastMode 覆盖仍然会在任一方向上压过配置。
如果独立运行遇到实时模型切换交接,cron 会使用切换后的提供方/模型重试,并在重试前为当前运行持久化该实时选择。当切换还携带新的认证配置文件时,cron 也会为当前运行持久化该认证配置文件覆盖。重试次数有限:在初始尝试加 2 次切换重试之后,cron 会中止,而不是无限循环。
在独立 cron 运行进入 agent runner 之前,OpenClaw 会检查已配置的 api: "ollama" 和 api: "openai-completions" 提供方的可达本地提供方端点,其中 baseUrl 为 loopback、私有网络或 .local。如果该端点不可用,运行会被记录为 skipped,并带有清晰的提供方/模型错误,而不是启动一次模型调用。端点结果会缓存 5 分钟,因此许多使用同一个已失效本地 Ollama、vLLM、SGLang 或 LM Studio 服务器的到期作业会共享一次小型探测,而不是制造请求风暴。被跳过的 provider-preflight 运行不会增加执行错误退避;当你希望重复收到跳过通知时,请启用 failureAlert.includeSkipped。
交付与输出
| 模式 | 会发生什么 |
|---|---|
announce | 如果代理没有发送,则回退将最终文本交付给目标 |
webhook | 将完成事件载荷 POST 到一个 URL |
none | 不进行运行器回退交付 |
--announce --channel telegram --to "-1001234567890"。对于 Telegram 论坛主题,请使用 -1001234567890:topic:123;直接 RPC/config 调用者也可以将 delivery.threadId 作为字符串或数字传入。Slack/Discord/Mattermost 目标应使用显式前缀(channel:<id>、user:<id>)。Matrix 房间 ID 区分大小写;请使用精确的房间 ID,或使用来自 Matrix 的 room:!room:server 形式。
当 announce 交付使用 channel: "last" 或省略 channel 时,带有提供方前缀的目标(例如 telegram:123)可以在 cron 回退到会话历史或单个已配置频道之前选择频道。只有已加载插件声明的前缀才是提供方选择器。如果 delivery.channel 是显式指定的,则目标前缀必须命名同一提供方;例如,channel: "whatsapp" 配合 to: "telegram:123" 会被拒绝,而不会让 WhatsApp 将 Telegram ID 解释为电话号码。channel:<id>、user:<id>、imessage:<handle> 和 sms:<number> 等目标种类和服务前缀仍然是频道拥有的目标语法,而不是提供方选择器。
对于独立作业,聊天交付是共享的。如果聊天路由可用,即使作业使用 --no-deliver,代理也可以使用 message 工具。如果代理发送到了已配置/当前目标,OpenClaw 会跳过回退 announce。否则,announce、webhook 和 none 只控制运行器在代理轮次结束后如何处理最终回复。
当代理从活动聊天创建一个隔离提醒时,OpenClaw 会为回退 announce 路由存储保留的实时交付目标。内部会话键可能是小写;当当前聊天上下文可用时,不会根据这些键重建提供方交付目标。
隐式 announce 交付会使用已配置的频道允许列表来验证并重定向过时目标。DM 配对存储中的批准不是回退自动化接收者;当计划作业应主动发送到某个 DM 时,请设置 delivery.to 或配置频道的 allowFrom 条目。
失败通知遵循单独的目标路径:
cron.failureDestination设置失败通知的全局默认值。job.delivery.failureDestination可按作业覆盖该设置。- 如果两者都未设置,且作业已经通过
announce交付,那么失败通知现在会回退到该主 announce 目标。 delivery.failureDestination仅在sessionTarget="isolated"的作业上受支持,除非主要交付模式是webhook。failureAlert.includeSkipped: true可让作业或全局 cron 告警策略纳入重复的跳过运行告警。跳过运行会保留单独的连续跳过计数,因此不会影响执行错误退避。
CLI 示例
- 一次性提醒
- 循环隔离作业
- 模型与思考覆盖
Webhooks
Gateway 可以为外部触发器暴露 HTTP webhook 端点。在配置中启用:认证
每个请求都必须通过请求头包含 hook token:Authorization: Bearer <token>(推荐)x-openclaw-token: <token>
POST /hooks/agent
POST /hooks/agent
运行一个隔离的代理轮次:字段:
message(必填)、name、agentId、wakeMode、deliver、channel、to、model、fallbacks、thinking、timeoutSeconds。映射 hook(POST /hooks/<name>)
映射 hook(POST /hooks/<name>)
自定义 hook 名称通过配置中的
hooks.mappings 解析。映射可以使用模板或代码转换,将任意载荷转换为 wake 或 agent 动作。Gmail PubSub 集成
通过 Google PubSub 将 Gmail 收件箱触发器连接到 OpenClaw。前置条件:
gcloud CLI、gog(gogcli)、已启用的 OpenClaw hooks、用于公共 HTTPS 端点的 Tailscale。向导设置(推荐)
hooks.gmail 配置,启用 Gmail 预设,并使用 Tailscale Funnel 作为推送端点。
Gateway 自动启动
当hooks.enabled=true 且设置了 hooks.gmail.account 时,Gateway 会在启动时运行 gog gmail watch serve 并自动续订 watch。设置 OPENCLAW_SKIP_GMAIL_WATCHER=1 可选择退出。
手动一次性设置
Gmail 模型覆盖
管理作业
模型覆盖说明:
openclaw cron add|edit --model ...会更改作业选择的模型。- 如果该模型被允许,那么确切的提供方/模型会进入隔离代理运行。
- 如果它不被允许或无法解析,cron 会以明确的验证错误使运行失败。
- 已配置的回退链仍然适用,因为 cron 的
--model是作业主模型,而不是会话/model覆盖。 - 载荷
fallbacks会替换该作业已配置的回退;fallbacks: []会禁用回退并使运行严格执行。 - 如果没有显式或已配置的回退列表,普通
--model不会作为静默的额外重试目标回落到代理主模型。
配置
maxConcurrentRuns 同时限制计划中的 cron 派发和隔离代理轮次执行。隔离 cron 代理轮次在内部使用队列专用的 cron-nested 执行通道,因此提高该值可让彼此独立的 cron LLM 运行并行推进,而不只是启动它们各自外层的 cron 包装器。共享的非 cron nested 通道不会因该设置而扩展。
运行时状态侧车文件由 cron.store 派生:像 ~/clawd/cron/jobs.json 这样的 .json 存储会使用 ~/clawd/cron/jobs-state.json,而不带 .json 后缀的存储路径会追加 -state.json。
如果你手动编辑 jobs.json,请不要将 jobs-state.json 纳入源代码管理。OpenClaw 使用该侧车文件保存待处理槽位、活动标记、上次运行元数据,以及调度器判断外部编辑的作业何时需要新的 nextRunAtMs 的调度身份信息。
禁用 cron:cron.enabled: false 或 OPENCLAW_SKIP_CRON=1。
重试行为
重试行为
一次性重试:瞬态错误(速率限制、过载、网络、服务器错误)最多重试 3 次,采用指数退避。永久错误会立即禁用。循环重试:重试之间采用指数退避(30 秒到 60 分钟)。退避会在下一次成功运行后重置。
维护
维护
cron.sessionRetention(默认 24h)会清理隔离运行会话条目。cron.runLog.maxBytes / cron.runLog.keepLines 会自动清理运行日志文件。故障排除
命令阶梯
Cron 未触发
Cron 未触发
- 检查
cron.enabled和OPENCLAW_SKIP_CRON环境变量。 - 确认 Gateway 持续运行。
- 对于
cron调度,验证时区(--tz)与主机时区是否一致。 - 运行输出中的
reason: not-due表示已使用openclaw cron run <jobId> --due检查手动运行,但该任务当时还未到执行时间。
Cron 已触发但未发送
Cron 已触发但未发送
- 传递模式
none表示不期望有 runner 回退发送。只要存在聊天路由,agent 仍可使用message工具直接发送。 - 缺少/无效的传递目标(
channel/to)表示已跳过外发。 - 对于 Matrix,复制的或旧版任务如果
delivery.to房间 ID 使用了小写,可能会失败,因为 Matrix 房间 ID 区分大小写。请将任务编辑为 Matrix 中精确的!room:server或room:!room:server值。 - 渠道认证错误(
unauthorized、Forbidden)表示传递被凭据阻止。 - 如果隔离运行只返回静默令牌(
NO_REPLY/no_reply),OpenClaw 会抑制直接外发,也会抑制回退的排队摘要路径,因此不会向聊天中发布任何内容。 - 如果应由 agent 自行向用户发送消息,请检查该任务是否具有可用路由(
channel: "last"且存在先前聊天,或显式的 channel/target)。
Cron 或心跳似乎阻止了 /new-style rollover
Cron 或心跳似乎阻止了 /new-style rollover
- 每日和空闲重置的新鲜度不基于
updatedAt;参见 会话管理。 - Cron 唤醒、heartbeat 运行、exec 通知以及 gateway 记账可能会更新会话行用于路由/状态,但它们不会延长
sessionStartedAt或lastInteractionAt。 - 对于在这些字段存在之前创建的旧版记录,如果转录 JSONL 的会话头仍然可用,OpenClaw 可以从中恢复
sessionStartedAt。没有lastInteractionAt的旧版空闲记录会使用恢复出的开始时间作为其空闲基准。
时区注意事项
时区注意事项
- 不带
--tz的 Cron 使用 gateway 主机时区。 - 不带时区的
at调度将被视为 UTC。 - Heartbeat 的
activeHours使用已配置的时区解析。