#心跳与定时任务的疑问

1 messages · Page 1 of 1 (latest)

woeful kestrel
#

关于心跳和定时任务触发的请求会将工作区注入到上下文吗,我使用的时候发现心跳和定时任务触发的内容总是不太聪明,并且连一些约定都不记得了。可以使用私聊渠道的会话去触发定时任务吗

定时任务中的会话,主会话和隔离会话有什么区别
执行内容,发布消息到主时间线和运行助手任务(隔离)有什么区别
投递,其中发布摘要(默认)、webhook和无(仅内部),又代表什么意思

kind bayBOT
#

先给结论,这块确实容易绕。最好再贴一下 openclaw --version,因为这部分最近改动挺多。按当前 docs/main,核心是:

1) 会把“工作区”注入上下文吗?

会,但不是把整个工作区目录都塞进去。
注入的是 workspace 里的 bootstrap files,比如 AGENTS.mdSOUL.mdUSER.mdHEARTBEAT.md 等,不是任意文件。

  • Heartbeat 默认是 main session turn,所以它默认有:
    • 主会话历史
    • workspace bootstrap files
  • 但如果你开了:
    • heartbeat.lightContext: true只保留 HEARTBEAT.md
    • heartbeat.isolatedSession: true不带之前聊天历史
  • Cron:
    • session=isolated → 跑在独立 cron:<jobId> 会话里,不继承主聊天历史
    • --light-contextcron 的 bootstrap context 会直接变空

所以你感觉它“不太聪明、记不住约定”,最常见就是:

#
  1. 约定只写在聊天里,没写进 AGENTS.md / HEARTBEAT.md
  2. heartbeat 开了 isolatedSession
  3. cron 用了 isolated
  4. cron 还开了 --light-context

2) 可以用私聊渠道的会话触发定时任务吗?

可以,但不是用 main

你要区分:

  • main = agent 的主会话
  • 私聊/群聊/频道 session = 某个具体聊天上下文

如果你想让 cron 复用某个私聊 session 的上下文,要用:

  • sessionTarget = current
    在“创建任务的那个会话”里绑定当前 session
#
  • session:<sessionKey>
    显式绑定某个已知 session key

一个重要细节:
current 只有在“有当前聊天上下文”时才会解析成功。
如果你是在纯 CLI/headless 环境里创建,没有当前 session,它会回退成 isolated

3) 定时任务里的“主会话” vs “隔离会话”

主会话(main)

  • 不是独立 agent run
  • 是往主时间线塞一个 system event
  • 然后由 heartbeat / 主会话去处理
  • 适合提醒、触发器、让主脑子接着干

隔离会话(isolated)

  • 真正启动一次独立 assistant run
  • 会话是 cron:<jobId>
#
  • 默认不带主聊天历史
  • 适合日报、总结、批处理、后台任务

如果你希望“更聪明、更记得约定”,通常优先:

  • 把长期规则写进 AGENTS.md
  • 把 heartbeat 专用规则写进 HEARTBEAT.md
  • 需要连续记忆时,不要用 isolated,改用 currentsession:<...>

4) “发布消息到主时间线” vs “运行助手任务(隔离)”

这是“执行内容”的区别,不是投递区别。

发布消息到主时间线

  • 本质是 systemEvent
  • 把一段文字投到主会话
  • 更像“提醒主会话下一轮去做事”

运行助手任务(隔离)

#
  • 本质是 agentTurn
  • 直接跑一次独立 assistant task
  • 用你写的 prompt 当任务输入

简化理解:

  • 想“提醒主会话做某事” → 选 发布消息到主时间线
  • 想“现在就单独跑个任务” → 选 运行助手任务(隔离)

5) 投递里的“发布摘要 / webhook / 无”

这是“执行完以后,结果往哪送”。

发布摘要(默认)

  • 把运行结果摘要发到聊天里
  • 这是 isolated agentTurn 常见默认值

webhook

#
  • 执行完成后,往一个 URL 发 HTTP POST
  • 适合接自己系统

无(仅内部)

  • 任务照跑
  • 但不往聊天/Webhook 发结果
  • 结果只留在内部记录 / task ledger

6) 为什么 heartbeat / cron 会显得笨

我基本可以确定就是“上下文少了”,不是你错觉。

优先检查这几个点:

  1. AGENTS.md 里有没有你说的那些“约定”
  2. HEARTBEAT.md 有没有写 heartbeat 专用规则
  3. heartbeat 有没有开:
    • lightContext: true
#
  • isolatedSession: true
  1. cron 有没有用:
    • session=isolated
    • --light-context
  2. 有没有给 heartbeat / cron 单独配了更弱的 model

我建议你怎么配

  • 要聪明、记得上下文
    heartbeat 用主 session,cron 用 current / session:<...>
  • 要省 token
    heartbeat 才开 isolatedSession + lightContext
  • 要稳定遵守规则
    把规则写进 AGENTS.md,不要只放在聊天历史里

文档:

woeful kestrel
#

我cron任务配置为
主会话
发布消息到主时间线
投递选择无(仅内部)

点击执行,运行历史显示已跳过,disabled,是什么问题
还有我选择主会话后,投递只能选择无(仅内部)或者webhook,那么选无(仅内部)能收到消息吗

kind bayBOT
#

这次基本能定位了。

你这个组合:

  • 主会话
  • 发布消息到主时间线
  • 投递 = 无(仅内部)

本质上不是“cron 自己发消息”,而是:

  1. cron 往 main session 塞一个 system event
  2. 然后尝试唤醒 heartbeat 去处理它

所以如果运行历史里是 skipped / disabled,很大概率是:

1) heartbeat 被关了

按源码,main session + wake now 会去跑一次 heartbeat。

#

如果 heartbeat 返回 disabled,这个 cron run 就会记成 skipped / disabled

最常见就是这里被设成了:

agents.defaults.heartbeat.every: "0m"

或者对应 agent 的 heartbeat 被禁用了。


2) 如果这是一次性任务(at

一次性任务在 ok / skipped 后会被自动停用,避免死循环。
所以你可能会同时看到:

  • 这次 run 是 skipped
#
  • job 现在变成了 disabled

你问的第二个点

选了“主会话”后,投递只有 “无” 或 “webhook”,为什么?

因为 “发布摘要(announce)”是给隔离 assistant run 用的
而你现在选的是:

  • 主会话
  • system event

这不是一个独立 assistant task,所以没有“给这个独立任务发摘要到聊天”的路径。


#

那“无(仅内部)”能收到消息吗?

默认不能指望收到 cron 自己发出的消息。

无(仅内部) 的意思就是:

  • cron 不做外部投递
  • 不往聊天发 summary

你最多只能期待:

  • 这个 system event 被 main session/heartbeat 处理后
  • heartbeat 再决定发一条消息出来

所以如果:

  • heartbeat 是禁用的
  • 或 heartbeat 的 target 不是可投递目标
#
  • 或这次 heartbeat 没真的跑起来

那你就不会收到消息


可以这样理解

你的当前配置适合

“往主脑子里塞一句提醒,等它下一轮自己处理”

不适合

“定时到了,直接给我发一条消息”

如果你想要定时到了就稳定给你回消息,更适合用:

  • 隔离会话
#
  • 运行助手任务(隔离)
  • 发布摘要(默认)

我建议你怎么选

想直接收到消息

选:

  • 隔离会话
  • 运行助手任务(隔离)
  • 发布摘要(默认)

想只是给主会话加个内部提醒

选:

#
  • 主会话
  • 发布消息到主时间线
  • 无(仅内部)

但前提是 heartbeat 不能关,否则这个提醒没人处理。


先查这几个

麻烦贴一下这几个输出,我就能直接告诉你是哪一类:

openclaw --version
openclaw cron runs --id <jobId> --limit 20
openclaw system heartbeat last
woeful kestrel
#

如果选主会话,和运行助手任务(隔离),又是什么意思呢

kind bayBOT
#

这个组合其实是不成立的,可以直接理解成“选项打架了”。

源码里的硬限制是:

sessionTarget="main" 只能systemEvent
sessionTarget="isolated" | "current" | "session:..." 只能agentTurn

也就是:

合法组合只有两类

| 会话                         | 执行内容       | 含义                                                   |
| -------------------------- | ---------- | ---------------------------------------------------- |
| 主会话                        | 发布消息到主时间线  | 往 main session 塞一条 system event,让 heartbeat / 主会话去处理 |
| 隔离 / current / 自定义 session | 运行助手任务(隔离) | 真正启动一次 assistant run                                 |
#

───

所以你问的这个

“主会话 + 运行助手任务(隔离)”是什么意思?

严格说,没意义,属于无效组合
它不是“让主会话跑一个隔离任务”,而是:

• 前半句要求它走 main session
• 后半句又要求它走 agentTurn / isolated run

这两个方向是冲突的。

如果 UI 里暂时让你选到了,可以把它当成:

• 前端还没完全拦住

#

• 但后端语义上不支持

───

你可以这么记

选“主会话”

你就是在说:

不要单独跑任务,
只是往主会话脑子里塞一句话。

所以执行内容必须是:

发布消息到主时间线

#

───

选“运行助手任务(隔离)”

你就是在说:

现在单独开一个任务自己跑。

所以会话必须是:

隔离
• 或 current
• 或 session:xxx

───

最简单的口诀