跳到主要内容
黯羽轻扬每天积累一点点

Agent Engineering 爆火之后,我学到的 5 个工程教训

免费2026-07-03#AI#AI

Agent Engineering 被炒得火热,但真正落地时处处是坑。本文分享我在真实项目中撞上的 5 个工程教训:工具架构设计、权限最小化、循环检测、MCP 边界管理、以及何时该收手。

从一次失控的 Agent 调用开始

三个月前,我接手了一个 AI agent 项目:让 agent 自动管理客户工单系统,包括读取工单、分配负责人、发送回复。听起来很简单,对吧?结果上线第一天,agent 在一个循环里连续调用了 37 次“重新分配”API,把同一个工单转了 37 个人,客户直接投诉到 CEO 那里。那一刻我意识到,Agent Engineering 不是写几个 prompt 就完事的——它需要体系化的工程思考。

以下是我在后续重构中学到的 5 个核心教训。

1. 工具架构不要只写 schema,要写“约束”

最初我定义工具函数时,只写了函数名、参数、返回类型。比如 assign_ticket(ticket_id, assignee_id)。结果 agent 经常传入不存在的 assignee_id,或者把工单 assign 给已离职的人。

真正改变我判断方式的结论是:工具 schema 必须包含业务语义的约束

我的做法:

  • 在参数描述里写上“请确保 assignee_id 是当前在职员工”这类规则。
  • 更彻底地,在参数级别加枚举或验证 regex。例如 assignee_id 只允许数字,长度固定为 6。
  • 如果参数依赖外部数据,比如“只能 assign 给你的直属下属”,那就在工具代码里先查数据库做校验,返回清晰错误而非让 agent 猜。

踩坑修正前,我的 schema 只有 5 行;修正后,每个工具的描述平均增加到 15 行,并且内置了参数校验。代价是多了些代码,但 agent 调用失败率从 23% 降到了 4%。

终端中 agent 连续工具调用的日志输出,显示循环检测触发的警告

2. 权限管控必须从“默认允许”改为“显式拒绝”

很多 agent 框架默认 agent 能调用所有注册的工具。我早期也是——结果 agent 自动调用了“删除工单”接口,误删了一个非测试工单。

教训:agent 权限范围应该小到不能再小,然后逐步放宽

可以执行的做法:

  • 用一个配置文件或数据库表,显式列出每个 agent 允许执行的操作。
  • 在工具注册阶段,用装饰器或中间件做权限检查。比如 @require_permission('ticket:assign')
  • 对于危险操作(删除、修改金额、发送外部通知),加二次确认步骤,让 agent 生成“预执行”请求,人工确认后才真正执行。

我后来在重构中添加了一个“权限清单”对象,agent 启动时加载,每次工具调用前都校验。这个改动让误操作降为零。但注意:权限清单本身需要定期审计,因为业务角色会变化。

笔记本电脑上显示的 Agent 权限清单截图,列出各操作允许/拒绝状态

3. 循环不会自己消失,你必须主动检测并打断

前面提到那个 37 次重新分配就是循环导致的。agent 发现工单状态不对,认为自己“应该重新分配”,分配后状态不变,于是继续分配。

循环是 Agent Engineering 最常见的失败场景。解决方案不复杂:

  • 步骤计数器:在一次 agent 运行中,限制总步骤数(比如最多 20 步)。超过就强制结束并返回中间结果。
  • 状态指纹检测:记录每次状态快照,如果检测到重复状态,说明可能陷入循环,触发断点。
  • 内置去重逻辑:有些循环是因为 agent 重复调用相同参数的工具。你可以在工具调用层缓存最近的调用(比如最近 5 个调用 hash),发现重复就返回“已执行,无需重复”。

具体做法:我写了一个 LoopDetector 类,维护一个最近 10 个状态指纹的队列。每次工具调用后,计算当前状态 hash 并对比,如果重复率超过阈值,就中断并输出警告。这个机制上线后,循环导致的故障减少了 90%。

4. MCP 是双刃剑:能扩展能力,也可能引入幻象依赖

MCP(Model Context Protocol)是 agent 获取外部上下文的好方法,比如连接数据库、文件系统、Web API。但我在尝试 MCP 时,发现 agent 经常依赖 MCP 中未明确说明的数据,导致推理偏差。

一个典型问题:agent 从 MCP 获取了用户最近订单列表,但 MCP 返回的数据中混入了已取消的订单。agent 没有过滤,直接拿已取消订单的状态作为用户活跃度的判断依据。

我的教训:MCP 的数据必须自带过滤和解释。数据源返回什么,agent 就用什么,你不会希望 agent 去盲猜数据可靠性。

解决方法:

  • 在 MCP 集成时,为每个数据字段加上“数据来源说明”和“有效期”。
  • 返回数据时,附带一个“数据质量标签”,比如“最近 1 小时已更新”、“可能包含已取消订单”。
  • 如果可能,在工具函数里预先做数据清洗。例如“获取用户订单”工具内部就过滤掉已取消的订单。

引入这些后,agent 基于 MCP 的决策准确率提升明显。但也要注意:不要给 MCP 过度加工数据,否则可能掩盖真实问题。

5. 当你发现投入产出比下降时,及时换路线

不是所有问题都适合用 agent 解决。我在项目中遇到过这样的场景:花了两周优化 agent 对某个特定工单类型的处理,准确率只从 80% 提高到 82%。而如果改用传统规则+简单的分类模型,一天就能达到 95%。

如何判断是否该换路线?

  • 边际收益:如果每次优化只提升不到 1% 而已,且代码复杂度暴涨,那就收手。
  • 失败模式:如果 agent 的失败是随机的(比如不同场景下错误原因完全不一样),那很可能该场景不适合 agent,改用确定性方案。
  • 可测试性:如果难以构造测试用例来验证改进效果,说明问题可能太模糊,agent 只会碰运气。

我的决策原则:如果在 3 次迭代内无法将关键指标(如成功率)提升到可接受水平,就停下来——先用一个简单方案兜底,然后花时间理解根本原因,而不是盲目堆 prompt。

适合什么场景继续投入?

  • 任务有明确模式但规则复杂,比如工单分类、邮件回复。
  • 你需要 agent 自主决策,但失败代价可控,比如推荐内容、生成草稿。
  • 你具备工程化能力,能做好工具定义、权限、循环检测。

什么时候该换路线?

  • 任务完全随机或无规律,比如用户输入毫无模式。
  • 失败代价极高,比如金融交易、医疗诊断。
  • 你无法控制 agent 的输入输出格式,比如集成外部不可控 API。

如果你现在想开始,最值得先照抄的一步

找一个真实但低风险的任务(比如内部工单的自动分配),先手动完成一次 agent 搭建全流程:注册工具、设置权限、加入循环检测、测试 10 个场景。然后记录失败数据。不要追求完美,第一个版本越简单越好——因为你会重写的。

我在这个过程中最大的感受是:Agent Engineering 的成功不在于 agent 多聪明,而在于它的工程约束有多严谨。

评论

暂无评论,快来发表你的见解吧

提交评论