快速开始
cron 如何工作
- Cron 在 Gateway 网关进程内运行,而不是在模型内运行。Gateway 网关必须保持运行,计划才会触发。
- 任务定义、运行时状态和运行历史会持久化到 OpenClaw 的共享 SQLite 状态数据库中,因此重启不会丢失计划。
- 每次 cron 执行都会创建一条后台任务记录。
- 一次性任务(
--at)默认会在成功后自动删除;传入--keep-after-run可保留它们。 - 单次运行的挂钟时间预算:设置时使用
--timeout-seconds。否则,隔离/分离的智能体轮次任务会先受 cron 自身 60 分钟 watchdog 限制,随后底层智能体轮次超时(agents.defaults.timeoutSeconds,默认 48 小时)才可能适用;命令任务默认为 10 分钟。 - Gateway 网关启动时,逾期的隔离智能体轮次任务会被重新调度,而不是立即重放,从而避免模型/工具引导工作进入渠道连接窗口。
- 如果你通过系统 cron 或其他外部调度器驱动
openclaw agent,即使 CLI 已经处理SIGTERM/SIGINT,也要用硬终止升级机制包装它。Gateway 网关托管的运行会请求 Gateway 网关中止已接受的运行;本地和嵌入式回退运行会收到相同的中止信号。对于 GNUtimeout,优先使用timeout -k 60 600 openclaw agent ...,而不是普通的timeout 600 ...—— 如果进程无法及时排空,-k值就是兜底。对于 systemd 单元,使用带宽限窗口(TimeoutStopSec)的SIGTERM停止信号,然后再执行最终终止。当原始 Gateway 网关运行仍处于活动状态时复用--run-id,重复运行会被报告为正在进行,而不是启动第二次运行。
任务对账
任务对账
Cron 任务对账首先由运行时拥有,其次由持久历史支撑:只要 cron 运行时仍跟踪该任务为正在运行,活动 cron 任务就会保持活动,即使旧的子会话行仍然存在。一旦运行时停止拥有该任务并且 5 分钟宽限窗口过期,维护检查会查看持久化运行日志和任务状态,匹配
cron:<jobId>:<startedAt> 运行。那里的终止结果会最终确定任务账本;否则 Gateway 网关拥有的维护可以将任务标记为 lost。离线 CLI 审计可以从持久历史恢复,但它自身空的进程内活动任务集合不能证明 Gateway 网关拥有的运行已经消失。计划类型
| 种类 | CLI 标志 | 描述 |
|---|---|---|
at | --at | 一次性时间戳(ISO 8601 或类似 20m 的相对时间) |
every | --every | 固定间隔(10m、1h、1d) |
cron | --cron | 5 字段或 6 字段 cron 表达式,可选 --tz |
on-exit | --on-exit | 监听的命令退出时触发一次(事件触发器;可跨轮次清理保留;可选 --on-exit-cwd) |
--tz America/New_York 可在该 IANA 时区解释不带偏移量的 --at 日期时间,或评估 cron 表达式。没有 --tz 的 cron 表达式使用 Gateway 网关主机时区。--tz 不能与 --every 或 --on-exit 一起使用。
整点重复表达式(分钟为 0 且小时字段为通配符)会自动错开最多 5 分钟,以减少负载峰值。使用 --exact 可强制精确计时,或使用 --stagger 30s 指定显式窗口(仅 cron 计划)。
日期和星期使用 OR 逻辑
Cron 表达式由 croner 解析。当日期字段和星期字段都不是通配符时,croner 会在任一字段匹配时匹配,而不是要求两者都匹配。这是标准 Vixie cron 行为。+ 星期修饰符(0 9 15 * +1),或按一个字段调度,并在任务的提示或命令中保护另一个字段。
载荷
每个任务都只携带一种载荷类型,由标志选择:| 载荷 | 标志 | 运行 |
|---|---|---|
| 系统事件 | --system-event <text> | 入队到主会话,本身不调用模型 |
| 智能体消息 | --message <text> | 模型支持的智能体轮次 |
| 命令 | --command <shell> 或 --command-argv <json> | Gateway 网关主机上的 shell/进程,不调用模型 |
智能体轮次选项
提示文本(隔离/当前/自定义会话任务必需)。
模型覆盖;必须解析为允许的模型,否则运行会因验证错误而失败。
每任务回退模型列表,例如
--fallbacks openai/gpt-5.5,openrouter/meta-llama/llama-3.3-70b-instruct:free。传入 --fallbacks "" 可执行没有回退的严格运行。在
cron edit 上,移除每任务回退覆盖,使任务遵循配置的回退优先级。不能与 --fallbacks 组合使用。在
cron edit 上,移除每任务模型覆盖,使任务遵循常规 cron 模型优先级(已存储的 cron 会话覆盖,否则为智能体/默认模型)。不能与 --model 组合使用。Thinking 级别覆盖(
off|minimal|low|medium|high|xhigh|adaptive|max)。在
cron edit 上,移除每任务 thinking 覆盖。不能与 --thinking 组合使用。跳过工作区引导文件注入。
限制任务可使用的工具,例如
--tools exec,read。--model 设置任务的主模型;它不会替换会话 /model 覆盖,因此已配置的回退链仍会应用在它之上。无法解析或不允许的模型会让运行以明确的验证错误失败,而不是静默回退到默认值。如果任务有 --model 但没有显式或已配置的回退列表,OpenClaw 会传递一个空的回退覆盖,而不是静默附加智能体主模型作为隐藏重试目标。
隔离任务的模型选择优先级,从高到低:
- 每任务载荷
model(显式配置;不允许的模型会让运行失败) - Gmail 钩子模型覆盖(仅当运行来自 Gmail 且该覆盖被允许时)
- 用户选择并存储的 cron 会话模型覆盖
- 智能体/默认模型选择
params.fastMode,隔离 cron 默认使用它;已存储的会话 fastMode 覆盖(然后是智能体 fastModeDefault)仍会在任一方向上优先于模型配置。自动模式使用模型的 params.fastAutoOnSeconds 截止值,默认为 60 秒。
如果运行遇到实时模型切换交接,cron 会使用切换后的提供商/模型重试,并为活动运行持久化该选择(以及任何新的凭证配置文件)。重试有上限:初始尝试加 2 次切换重试后,cron 会中止而不是循环。
在隔离运行开始前,OpenClaw 会检查已配置 api: "ollama" 和 api: "openai-completions" 提供商的可达本地端点,其 baseUrl 为 loopback、私有网络或 .local。此预检会遍历任务配置的回退链,并且只有在每个候选都不可达后才将运行标记为 skipped;--fallbacks "" 会将该遍历严格限制为主模型。宕机端点会将运行记录为 skipped 并附带清晰错误,而不是启动模型调用。结果按端点缓存 5 分钟(不是按任务或模型),因此许多到期任务共享一个失效的本地 Ollama/vLLM/SGLang/LM Studio 服务器时,只需一次探测,而不是形成请求风暴。跳过的预检运行不会递增执行错误退避;设置 failureAlert.includeSkipped 可选择接收重复跳过提醒。
命令载荷
命令载荷在 Gateway 网关调度器内运行确定性脚本,而不启动模型支持的轮次。它们在 Gateway 网关主机上执行,捕获 stdout/stderr,在 cron 历史中记录运行,并复用与智能体轮次任务相同的announce、webhook 和 none 投递模式。
命令 cron 是操作员管理员级的 Gateway 网关自动化表面,不是智能体
tools.exec 调用。创建、更新、移除或手动运行 cron 作业需要 operator.admin;计划命令稍后会在 Gateway 网关进程内作为该管理员编写的自动化执行。智能体 exec 策略(tools.exec.mode、审批提示、按智能体配置的工具允许列表)管控模型可见的 exec 工具,而不是命令 cron 载荷。--command <shell> 会存储 argv: ["sh", "-lc", <shell>]。使用 --command-argv '["node","scripts/report.mjs"]' 可在不经 shell 解析的情况下执行精确的 argv。可选的 --command-env KEY=VALUE(可重复)、--command-input、--timeout-seconds(默认 10 分钟)、--no-output-timeout-seconds 和 --output-max-bytes 用于控制进程环境、stdin 和输出边界。
投递的文本来自进程输出:非空 stdout 优先;如果 stdout 为空且 stderr 非空,则投递 stderr;如果两者都存在,cron 会发送一个小型 stdout: / stderr: 块。退出码 0 会将运行记录为 ok;非零退出、信号、超时或无输出超时会记录为 error,并可能触发失败提醒。只打印 NO_REPLY 的命令会使用常规 cron 静默令牌抑制,不会向聊天发回任何内容。
执行样式
| 样式 | --session 值 | 运行于 | 最适合 |
|---|---|---|---|
| 主会话 | main | 专用 cron 唤醒通道 | 提醒、系统事件 |
| 隔离 | isolated | 专用 cron:<jobId> | 报告、后台杂务 |
| 当前会话 | current | 创建时绑定 | 感知上下文的周期性工作 |
| 自定义会话 | session:custom-id | 持久命名会话 | 基于历史构建的工作流 |
主会话与隔离会话与自定义会话
主会话与隔离会话与自定义会话
主会话作业会将系统事件入队到 cron 所有的运行通道,并可选择唤醒 Heartbeat(
--wake now 或 --wake next-heartbeat)。它们可以使用目标主会话最近一次投递上下文来回复,但不会把常规 cron 轮次追加到人工聊天通道,也不会延长目标会话的每日/空闲重置新鲜度。隔离作业会以新会话运行一个专用智能体轮次。自定义会话(session:xxx)会跨运行保留上下文,从而支持每日站会这类基于先前摘要构建的工作流。主会话 cron 事件是自包含的系统事件提醒。它们不会自动包含默认 Heartbeat 提示中的 “Read HEARTBEAT.md” 指令;如果提醒需要查阅 HEARTBEAT.md,请在 cron 事件文本中明确说明。隔离作业中的“新会话”含义
隔离作业中的“新会话”含义
每次运行都有新的转录/会话 id。OpenClaw 会携带安全偏好(思考/快速/详细设置、标签、用户明确选择的模型/凭证覆盖),但不会从旧 cron 行继承环境会话上下文:频道/群组路由、发送或队列策略、提升权限、来源或 ACP 运行时绑定。如果周期性作业应有意基于同一会话上下文构建,请使用
current 或 session:<id>。子智能体和 Discord 投递
子智能体和 Discord 投递
当隔离 cron 运行编排子智能体时,投递会优先使用最终后代输出,而不是过期的父级临时文本。如果后代仍在运行,OpenClaw 会抑制该部分父级更新,而不是公告它。对于纯文本 Discord 公告目标,OpenClaw 会发送一次规范的最终助手文本,而不是同时重放流式/中间文本和最终答案。媒体和结构化 Discord 载荷仍会单独投递,因此附件和组件不会被丢弃。
投递和输出
| 模式 | 发生的事情 |
|---|---|
announce | 如果智能体未发送,则将最终文本回退投递到目标 |
webhook | 将完成事件载荷 POST 到 URL |
none | 无运行器回退投递 |
--announce --channel telegram --to "-1001234567890" 进行渠道投递。对于 Telegram 论坛主题,请使用 -1001234567890:topic:123;OpenClaw 也接受 Telegram 所有的 -1001234567890:123 简写。直接 RPC/配置调用者可以将 delivery.threadId 作为字符串或数字传入。Slack/Discord/Mattermost 目标使用显式前缀(channel:<id>、user:<id>)。Matrix 房间 ID 区分大小写;请使用精确的房间 ID,或使用来自 Matrix 的 room:!room:server 形式。
当公告投递使用 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、webhook 和 none 只控制智能体轮次结束后运行器如何处理最终回复。
当智能体从活跃聊天创建隔离提醒时,OpenClaw 会存储保留的实时投递目标,用于回退公告路由。内部会话键可能是小写;当前聊天上下文可用时,不会从这些键重建提供商投递目标。
隐式公告投递会使用已配置的渠道允许列表来验证并重路由过期目标。私信配对存储审批不是回退自动化接收者;如果计划作业应主动发送到私信,请设置 delivery.to 或配置渠道 allowFrom 条目。
失败通知
失败通知遵循单独的目标路径:cron.failureDestination为失败通知设置全局默认值。job.delivery.failureDestination按作业覆盖该值。- 如果两者都未设置,且作业已通过
announce投递,失败通知会回退到该主要公告目标。 delivery.failureDestination仅支持sessionTarget="isolated"作业,除非主投递模式是webhook。failureAlert.includeSkipped: true会让作业或全局 cron 警报策略加入重复跳过运行提醒。跳过的运行会保留单独的连续跳过计数器,因此不会影响执行错误退避。openclaw cron edit暴露按作业的提醒调优:--failure-alert/--no-failure-alert、--failure-alert-after <n>、--failure-alert-channel、--failure-alert-to、--failure-alert-cooldown、--failure-alert-include-skipped/--failure-alert-exclude-skipped、--failure-alert-mode和--failure-alert-account-id。
输出语言
Cron 作业不会从渠道、locale 或先前消息推断回复语言。请将语言规则放入计划消息或模板:{{language}} 等占位符已填充。如果输出混合多种语言,请明确规则,例如:“叙述文本使用中文,技术术语保留英文。”
CLI 示例
- 一次性提醒
- 周期性隔离作业
- 模型和思考覆盖
- Webhook 输出
- 命令输出
管理作业
openclaw cron run <jobId> 会在手动运行入队后返回。对于关机钩子、维护脚本或其他必须阻塞到队列运行完成的自动化,请使用 --wait;它会轮询返回的 runId(默认超时 10m,轮询间隔 2s),并在状态为 ok 时以 0 退出,在 error、skipped 或等待超时时以非零退出。
智能体 cron 工具会从 cron(action: "list") 返回紧凑作业摘要(id、name、enabled、nextRunAtMs、scheduleKind、lastRunStatus);使用 cron(action: "get", jobId: "...") 获取单个完整作业定义。直接 Gateway 网关调用者可以向 cron.list 传入 compact: true;省略它会保留带投递预览的完整响应。
openclaw cron create 是 openclaw cron add 的别名。新任务可以使用位置式计划("0 9 * * 1"、"every 1h"、"20m" 或 ISO 时间戳),后面跟位置式智能体提示。对 cron add|create 或 cron edit 使用 --webhook <url>,可将已完成运行的载荷 POST 到 HTTP 端点;webhook 投递不能与聊天投递标志(--announce、--channel、--to、--thread-id、--account)组合使用。在 cron edit 上,--clear-channel、--clear-to、--clear-thread-id 和 --clear-account 会分别取消设置这些路由字段(每个都会拒绝与其匹配的设置标志同时使用),这不同于 --no-deliver,后者只会禁用运行器兜底投递。
模型覆盖说明:
openclaw cron add|edit --model ...会更改任务选择的模型。- 如果模型被允许,该确切提供商/模型会进入隔离的智能体运行。
- 如果不被允许或无法解析,cron 会以明确的验证错误使该运行失败。
- API
cron.update载荷补丁可以设置model: null来清除已存储的任务模型覆盖。 openclaw cron edit <job-id> --clear-model会从 CLI 清除该覆盖(效果与model: null补丁相同),且不能与--model组合使用。- 已配置的 fallback 链仍然适用,因为 cron
--model是任务主模型,而不是会话/model覆盖。 openclaw cron add|edit --fallbacks ...会设置载荷fallbacks,替换该任务的已配置 fallback;--fallbacks ""会禁用 fallback 并使运行严格执行。openclaw cron edit <job-id> --clear-fallbacks会清除每任务覆盖。- 没有显式或已配置 fallback 列表的普通
--model不会静默落到智能体主模型作为额外重试目标。
Webhooks
Gateway 网关可以暴露 HTTP webhook 端点供外部触发器使用。在配置中启用:身份验证
每个请求都必须通过 header 包含 hook 令牌:Authorization: Bearer <token>(推荐)x-openclaw-token: <token>
POST /hooks/agent
POST /hooks/agent
运行隔离的智能体轮次:字段:
message(必填)、name、agentId、sessionKey(需要 hooks.allowRequestSessionKey=true)、idempotencyKey、wakeMode、deliver、channel、to、model、thinking、timeoutSeconds。Mapped hooks (POST /hooks/<name>)
Mapped hooks (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 作为 push 端点(--tailscale funnel|serve|off)。
Gateway 网关自动启动
当hooks.enabled=true 且已设置 hooks.gmail.account 时,Gateway 网关会在启动时启动 gog gmail watch serve 并自动续订 watch。设置 OPENCLAW_SKIP_GMAIL_WATCHER=1 可选择退出。
手动一次性设置
Gmail 模型覆盖
配置
retry 值是默认值:最多 3 次重试,使用 30s/60s/5m 退避,并重试全部五类瞬态类别。webhookToken 会在 cron webhook POST 中作为 Authorization: Bearer <token> 发送。
maxConcurrentRuns 会同时限制计划 cron 调度和隔离的智能体轮次执行,默认值为 8。隔离的 cron 智能体轮次内部使用队列专用的 cron-nested 执行通道,因此提高此值可让独立的 cron LLM 运行并行推进,而不是只启动它们的外层 cron 包装器。共享的非 cron nested 通道不会被此设置拓宽。
cron.store 是逻辑存储键和 Doctor 迁移路径,而不是要手动编辑的实时 JSON 文件。任务数据存储在 SQLite 中;请使用 CLI 或 Gateway 网关 API 进行更改。
禁用 cron:cron.enabled: false 或 OPENCLAW_SKIP_CRON=1。
Retry behavior
Retry behavior
一次性重试:瞬态错误(速率限制、过载、网络、超时、服务器错误)最多重试
retry.maxAttempts 次(默认 3),使用 retry.backoffMs(默认 30s、60s、5m)。永久错误会立即禁用任务。周期性重试:连续执行错误会按扩展计划退避(30s、60s、5m、15m、60m)。下一次成功运行后退避会重置。Maintenance
Maintenance
cron.sessionRetention(默认 24h,false 禁用)会修剪隔离运行会话条目。cron.runLog.keepLines 会限制每个任务保留的 SQLite 运行历史行数;maxBytes 为兼容较旧的文件后端运行日志而保留。Legacy store migration
Legacy store migration
升级时,运行
openclaw doctor --fix,将旧版 ~/.openclaw/cron/jobs.json、jobs-state.json 和 runs/*.jsonl 文件导入 SQLite,并使用 .migrated 后缀重命名它们。格式错误的任务行会从运行时跳过,并复制到 jobs-quarantine.json 供后续修复或审查。故障排查
命令阶梯
Cron not firing
Cron not firing
- 检查
cron.enabled和OPENCLAW_SKIP_CRON环境变量。 - 确认 Gateway 网关持续运行。
- 对于
cron计划,验证时区(--tz)与主机时区。 - 运行输出中的
reason: not-due表示手动运行是用openclaw cron run <jobId> --due检查的,并且该任务尚未到期。
Cron fired but no delivery
Cron fired but no delivery
- 投递模式
none表示不预期运行器兜底发送。当有聊天路由可用时,智能体仍可用message工具直接发送。 - 缺少投递目标或投递目标无效(
channel/to)表示出站已跳过。 - 对于 Matrix,复制的或旧版任务如果带有小写的
delivery.to房间 ID,可能会失败,因为 Matrix 房间 ID 区分大小写。将任务编辑为 Matrix 中精确的!room:server或room:!room:server值。 - 渠道身份验证错误(
unauthorized、Forbidden)表示投递被凭证阻止。 - 如果隔离运行只返回静默令牌(
NO_REPLY/no_reply),OpenClaw 会抑制直接出站投递和兜底队列摘要路径,因此不会向聊天发回任何内容。 - 如果智能体应自行给用户发消息,请检查该任务是否有可用路由(
channel: "last"且有先前聊天,或显式渠道/目标)。
Cron or heartbeat appears to prevent /new-style rollover
Cron or heartbeat appears to prevent /new-style rollover
- 每日重置和空闲重置的新鲜度不基于
updatedAt;请参阅 会话管理。 - Cron 唤醒、heartbeat 运行、exec 通知和 Gateway 网关记账可能会为路由/状态更新会话行,但它们不会延长
sessionStartedAt或lastInteractionAt。 - 对于在这些字段存在之前创建的旧版行,如果文件仍然可用,OpenClaw 可以从转录 JSONL 会话 header 中恢复
sessionStartedAt。没有lastInteractionAt的旧版空闲行会使用该恢复的开始时间作为其空闲基线。
Timezone gotchas
Timezone gotchas
- 不带
--tz的 cron 使用 Gateway 网关主机时区。 - 不带时区的
at计划会被视为 UTC。 - Heartbeat
activeHours使用已配置的时区解析。