设计一个可靠的 Agent:从"能跑"到"敢用"
Agent 的难点从来不是调用工具,而是如何处理不确定性、失败与边界。
第一次写 Agent 的人,通常会在一天之内跑通一个”能查天气、能搜索、能发邮件”的 demo,然后陷入一种错觉:这东西好像快成了。
真正的工程问题从第二天才开始。
确定性优先
Agent 的核心矛盾在于:我们用一个概率性的系统,去执行要求确定性的任务。
缓解这个矛盾的第一原则是:把能确定的都确定下来。
- 参数的格式校验,用 schema 而不是靠模型自觉
- 状态的流转,用状态机而不是靠 prompt 描述
- 需要精确计算的地方,交给代码而不是模型
让模型负责它擅长的(理解意图、生成内容),让代码负责它擅长的(校验、计算、执行)。
工具设计的三条经验
工具是 Agent 的手。手的设计不好,大脑再聪明也没用。
第一,工具要少而精。 十个功能相近的工具,会让模型在”选哪个”上浪费大量 token,而且经常选错。宁可做一个参数更多、但语义清晰的工具。
第二,错误信息要写给模型看。 传统的错误处理是给开发者看的,但 Agent 场景下,错误信息是模型的输入:
{
"error": "INVALID_DATE",
"message": "日期必须是 YYYY-MM-DD 格式,你传入的是 '下周三'。请先换算成具体日期。",
"retryable": true
}
这样的错误信息,模型看到之后能自己纠正。而 Error: invalid input 只会让它继续犯错。
第三,破坏性操作要显式确认。 删除、支付、发送这类不可逆操作,不应该让模型自主决定。
关于循环与终止
Agent 的本质是一个循环:思考 → 行动 → 观察 → 再思考。
这个循环必须有明确的终止条件,否则会出现三种典型故障:
- 死循环:反复调用同一个工具,永远得不到想要的结果
- 过早停止:任务没完成就认为完成了
- 无限膨胀:每轮都”再确认一下”,成本失控
我通常会给循环加三道保险:
- 步数上限:硬性限制最多迭代 N 轮
- 预算上限:累计 token 或费用超过阈值就中断
- 重复检测:连续的相同动作直接判定为失败
可观测性
Agent 的调试难度远高于普通程序,因为你无法通过读代码知道它下一步要做什么。
所以轨迹记录(trace)是必需品,不是奢侈品。每一次思考、每一次工具调用、每一次返回,都要被记录下来,并且能够回放。
没有 trace 的 Agent 开发,基本等于闭着眼睛修车。
最后
我对 Agent 的判断标准很简单:
不是说它能做什么,而是它在做不到的时候会怎么表现。
一个会承认”我无法完成这个任务”的 Agent,比一个自信地给出错误结果的 Agent,价值高出一个量级。