最近一段时间我在做几个 Agent 相关的项目,说实话,有点沮丧。
一开始我和大多数人一样,把注意力都放在模型和规划上:
prompt、intent、planner、executor、memory,一层一层往上叠。
但项目越往后走,越觉得哪里不对。
Planner 看起来是对的,但系统还是会崩
最让我困惑的一类问题是这样的:
- Planner 输出的步骤看起来完全合理
- 参数也不是明显缺失
- 单步测试都能跑
- 但整个任务在执行过程中就是会失败
而且失败方式也都不一样。
有时候卡在第二步,有时候是第三步;
你重跑一次,失败位置还会变。
日志里通常只剩下一句类似:
tool execution failed
基本等于什么都没说。
我一开始以为是模型不稳定
最开始,我以为是模型的问题。
把模型从本地开源qwen换成了deepseek、缩短上下文、改 prompt,
甚至怀疑是不是 memory 或者cache记住了失败的用例污染了流程。
但折腾了很久之后,我发现一个事实:
就算 planner 输出一模一样,执行结果也可能不一样。
这时候我才开始意识到,问题可能不在“planner”,而在“executor”。
执行层的问题,比我想象的隐蔽得多
后来调试执行层才发现:
- 引入的参数补救,参数不完整时,尝试“补一下”,参数完整它有时候也补救
- 执行失败时,自动 retry
- 工具报错时,被 catch 掉只留一句 warning
- 有些操作失败了,但系统继续往下跑
从“成功率”角度看,这些设计看起来很贴心。
但从调试角度看,简直是灾难。
你永远不知道系统刚才到底做了什么。
有一刻我意识到:这根本没法 debug
有一次我在本地 debug 一个 Agent,已经凌晨两点多了。
我看着一堆日志,反复 replay 对话,
却完全无法确定:
- 哪一步真正失败了
- 是参数错了,还是策略拦了
- 还是中间被 retry 掩盖了
那一刻我意识到一件事:
如果执行层语义不清晰,这类系统是没法负责任地上线的。
后来简化了执行层
我索性把执行层单独拎出来,给自己定了几条非常死板的规则:
- 参数不全,直接失败,移除参数补救
- 不允许自动补参数
- 不允许 silent retry
- 所有执行步骤必须留下可回放的 trace
因为回退了很多看上去有用的东西,参数补救、planner验证
任务成功率明显下降,
以前“差不多能跑”的,现在全失败。
但奇怪的是,debug 反而变简单了。
失败变多了,但失败变“清楚”了
现在当一个任务失败时,我至少知道:
- 失败发生在哪一步
- 为什么失败
- 能不能完整复现这次失败
这听起来好像是基本要求,
但在之前的 Agent 系统里,其实很难做到。
我现在越来越觉得,执行层被严重低估了
我花了很多时间讨论模型、planner、memory,
但执行层往往只是:
- 一层工具调用封装
- 一段 try / catch
- 一个兜底 retry
可现实是,执行层是唯一真正触碰现实世界的地方。
如果这里的语义是模糊的,
系统迟早会在真实环境里出问题。
写在最后
我不确定这是不是一个“通用结论”,
也不确定是不是我自己的工程背景导致的偏见。
但至少在我做过的几个 Agent 项目里,
真正难、真正痛苦、真正影响上线质量的,
往往都集中在执行层。
如果你最近也在被 Agent 的“莫名其妙失败”折磨,
也许值得暂时少调一点 prompt,
多看看执行到底发生了什么。