投递(deliver)的含义
Cron 任务后台独立运行,没有等待回复的用户。Agent 跑完后结果默认只写入 session 文件。 投递 = 把 Agent 的回复主动推送到某个聊天 channel。
两条投递路径
路径 1:Agent 自己用 message 工具发
Agent 执行过程中主动调用 message 工具,直接发到目标 channel。
路径 2:Runner Fallback(--announce)
Agent 跑完后,如果它没有自己发消息,Runner 把最终回复文本作为兜底发出去。
--no-deliver 只关掉路径 2,不影响路径 1。
Runner Fallback(—announce)详解
核心逻辑
Agent turn 结束
↓
Runner 检查:Agent 有没有发到"已配置/当前目标"?
├── 发了 → 跳过 announce fallback(不重复发)
└── 没发 → 执行 announce,把最终回复文本发出去
三种投递模式
| 模式 | 行为 |
|---|---|
announce(isolated 默认) | Agent 没发 → Runner 把最终回复发到目标 channel |
webhook | 把完整事件 payload POST 到一个 URL |
none | Runner 不发任何东西 |
投递目标解析顺序
1. 显式指定:--channel telegram --to "123456789"
2. channel: "last" → 从 session 历史找上次聊天的 route
3. 单个已配置的 channel(只有一个时自动选)
4. provider-prefixed target:to: "telegram:123" 可以隐式选 channel
边界行为
- 抑制中间状态:Agent 第一个回复只是
"on it"等过渡语时,OpenClaw 重新提示一次要真正的结果再投递 - NO_REPLY 静默:Agent 回复
NO_REPLY时,Runner 同时抑制直接投递和 fallback,什么都不发 - 子 Agent 场景:投递优先用最终子 Agent 的输出,子 Agent 还在跑时父 Agent 的中间更新被压制
- 白名单验证:announce 投递用 channel 的
allowFrom白名单验证目标
查看投递诊断
openclaw cron show <job-id> # 预览投递路由
openclaw cron runs --id <job-id> # 历史运行的投递诊断
# 包含:intended target / resolved target / message-tool sends / fallback use / delivered state—best-effort-deliver
控制投递目标无法解析时的行为:
| 标志 | 行为 |
|---|---|
--best-effort-deliver | 路由解析失败 → 降级为 session-only 执行(任务照常跑,结果只写 session) |
--no-best-effort-deliver | 路由解析失败 → 直接返回 INVALID_REQUEST,任务不执行 |
适合开启:任务本身有价值(写文件、更新记忆),即使发不出消息也没关系。 适合关闭(严格模式):任务目的就是发消息,发不出去应该报错而不是静默成功。
WebChat 无 channel 场景:cron 结果回写 session
问题
WebChat 是 internal session,没有外部 channel。announce 的外部投递路径对它无效。
bestEffortDeliver=true 的文档明确说明:webchat session 就是”无法解析外部投递路由”的典型场景。
方案一:--session main(外部 CLI 创建 cron)
openclaw cron add \
--name "my-task" \
--at "20m" \
--session main \
--system-event "任务完成,结果是:xxx" \
--wake now \
--delete-after-run工作原理:
cron 触发
↓
把 system-event 注入到 main session 的消息队列
↓
--wake now 立即唤醒 heartbeat
↓
Agent 在 main session 里处理这条 system-event
↓
回复出现在 WebChat 的同一个 session 里
方案二:--session current(Agent 在对话中自己创建 cron)
openclaw cron add \
--name "follow-up" \
--at "30m" \
--session current \
--message "检查任务是否完成"current 在创建时绑定到当前活跃的 session,结果回到同一个 session。
main vs current 的本质区别
main:固定——无论在哪个 session 里创建 cron,永远指向该 agent 的主 session。current:快照——创建时把当前活跃的 session ID 记录下来,之后每次触发都回到这个 session。
两种方案对比
--session main | --session current | |
|---|---|---|
| 适合 | 外部触发的 cron(CLI 创建) | Agent 在对话中自己创建的 cron |
| 绑定时机 | 固定绑定 main session | 创建时绑定当前 session |
| 结果去向 | main session(WebChat 默认就是这个) | 创建时所在的那个 session |
| 多 agent 场景 | 需要指定 --agent <id> | 自动继承当前 agent |
| 口诀 | ”回到主入口" | "回到我这里” |
相关官方文档
- automation-cron — Cron 基础
- cli-cron —
openclaw cronCLI 参考 - cron-ws-protocol — Cron WS 协议