Agent 系统为什么这么难调试?问题往往不在模型,而在执行层

60 阅读3分钟

最近一段时间我在做几个 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,
多看看执行到底发生了什么。