OpenClaw Cron 排障:agentTurn 定时任务可能把 [object Object] 发给模型,而不是你的提示词
OpenClaw News 编辑部
最新 issue 显示:部分 agentTurn 类型的 cron 任务,真正送到 LLM 的并不是你配置好的提示词字符串,而是 [object Object]。
这会形成一种很隐蔽的故障:
- cron 任务创建成功
- jobs 配置里 message 看起来也是对的
- 任务也确实触发执行了
- 但模型响应的却不是你的调度指令,而是序列化污染后的内容
来源:
- Issue: openclaw/openclaw#54579
这个问题在现场会怎么表现
报告中的最小案例是:
- 配置 cron message 为
Say: HELLO WORLD
但任务执行后,最终表现却指向 [object Object],而不是预期中的字符串内容。
这基本说明故障点很可能出现在下面这条链路中间:
- cron job 定义落盘之后
- Gateway 读取并执行 cron payload 时
- 构造最终发给 LLM 的请求之前
为什么这个问题值得优先处理
这不是简单的“输出文案不对”。
如果你用 cron 驱动自动化代理,它会直接影响:
-
定时任务执行目标失真
- 提醒、日报、巡检、总结类任务可能都在“按时触发”,但没有做对事。
-
误判为模型或渠道故障
- 你可能会以为是模型变笨了、提示词失效了、供应商不稳定了,但真实问题可能是 message 在 Gateway 内部就被污染了。
-
关联症状更难排查
- 原始报告还提到 Telegram DM 会出现“显示 typing 但最终不回消息”的现象,可能是同一路径上的异常外溢。
如何确认你遇到的是同一类回归
如果同时满足以下几点,就很像是同一个问题:
- cron payload 类型是
agentTurn - 你在任务配置里看到的 message 字符串是正确的
- 任务触发后,输出明显围绕
[object Object],或者像是根本没收到原始提示词 - 换模型、换 provider 后依然复现
建议用一个极简、可判定的测试:
- 新建一个只做单一输出的 cron 任务。
- 提示词写成:
Reply with exactly: HELLO WORLD。 - 手动触发一次运行。
- 如果结果没有返回
HELLO WORLD,反而出现[object Object]或明显偏离,基本就可以锁定为该序列化问题。
现有报告已经排除了什么
原始报告者已经做过较大范围的隔离测试,仍然复现:
- 清空 agent sessions
- 禁用 channels
- 禁用 plugins
- 禁用 hooks
- 更换模型
- 切换到干净 workspace
最关键的一点是:jobs.json 里的 message 仍然是正确字符串。
这会把怀疑范围明显收窄到:Gateway 的 cron 执行链路,而不是模型供应商,也不是创建任务那一步。
临时绕过方案
1)关键任务先不要继续依赖 cron agentTurn
如果这个任务和运营、提醒、自动分发直接相关,建议先别押在 agentTurn cron 上,避免“任务看起来在跑,实际上没跑对”。
2)必须执行的调度先外置
原始报告的临时方案是:
- 用
launchd负责定时 - 用外部 CLI 直接调用模型
- 再用
openclaw message send做消息投递
如果是 Linux 环境,思路也一样:
- 用系统调度器触发脚本
- 把“调度”和“消息投递”拆开,先保证关键任务能稳定执行
3)测试提示词尽量做成“唯一正确答案”
例如:
Reply with exactly: HELLO WORLDReturn only the word OK
这种测试方式比长提示词更容易看出序列化是否被污染。
维护者接下来大概率要看的位置
根据当前证据,更值得优先排查的点包括:
- cron payload 的反序列化
- cron payload 对象转换成 agent/session 请求的过程
agentTurn执行时 LLM request 的组装逻辑
这是基于现有证据的技术判断,不是已经确认的最终根因。
如果你要补充 issue,最好带上这些信息
- OpenClaw 版本与 commit hash
- cron payload 的具体类型
- 你配置的原始 message 字符串
- jobs 定义文件里是否仍保留正确字符串
- 同样提示词在 cron 之外是否正常
- 多个模型/provider 是否都出现同样污染
修复前先把 cron payload 链路拆成 4 段
看到 LLM 收到 [object Object] 时,不要只盯着 prompt。值班时先按这 4 段收敛:
- cron 触发层:记录 cron job 名称、触发时间、是否是补跑或并发触发,确认同一任务有没有被重复投递。
- agentTurn 入参层:保存传给 agentTurn 的原始 payload,尤其是
message、content、input这几个字段到底是字符串还是对象。 - 序列化层:确认对象是在 cron wrapper 里被隐式转成字符串,还是进入 LLM adapter 前才变成
[object Object]。 - 副作用层:标记这次 cron 是否已经发消息、写外部 API、提交代码或触发部署,避免修复后重复执行同一批动作。
这 4 段能把“模型胡说”改写成明确的数据形状回归,也能帮助读者判断应该修 cron 入口、agentTurn 合约,还是 adapter 的输入防护。
修复后重新打开 cron 前,先做 3 个回归验证
即使补丁已经把 [object Object] 修掉,也不要马上恢复所有生产 cron。先做 3 个小验证:
- 同一 jobs 定义复测:保留原来的 job 配置,只把 message 改成
Reply with exactly: HELLO WORLD,确认 Gateway 实际送进 LLM 的仍是字符串。 - 真实任务影子运行:把生产提示词复制成一个不会写外部系统的 shadow job,确认摘要、消息投递和日志里的 payload 都一致。
- 恢复节奏分批打开:先恢复只读巡检或提醒类 cron,再恢复会发消息、写 API、提交代码或触发部署的任务。
这样做能避免一次序列化修复变成第二次批量副作用事故。对搜索 cron agentTurn [object Object] fixed but should I re-enable jobs 的读者来说,最重要的不是“补丁已合并”,而是确认恢复后的每一次定时任务都收到正确字符串。
![OpenClaw Cron 排障:agentTurn 定时任务可能把 [object Object] 发给模型,而不是你的提示词](/_next/image?url=%2Fimages%2Fnews%2Fcovers%2Ftutorial.png&w=1920&q=75)