给 Agent 加工具:先确定失败边界

发布时间:2026/7/21 14:34:38
给 Agent 加工具:先确定失败边界 文章目录1. 结论先行2. 为什么成功 demo 扛不住真实对话3. 一份最小失败契约4. 失败通常落在哪一层4.1 参数校验为什么要放在适配层5. 部分成功最容易被忽略的坑6. 重试策略的底线7. 适合马上做的和不适合一上来做的7.1 快速能做的改造清单和 MCP / function calling 的关系8. 常见误区9. 术语速查9.1 评审或上线前的验收问题10. 小结摘要给 Agent 接搜索、数据库、脚本执行一类工具时大家容易先写「调用成功返回什么」。线上真正耗时间的是超时、权限失败、参数不合法、部分成功时 Agent 会怎么说、会不会死循环重试。本文把失败契约写成可落地的检查清单并区分工具层、适配层、策略层和用户预期层。适合正在给 Agent / MCP / function calling 加工具的开发者。说明不同产品的工具协议细节会变本文讲工程约定不绑定某一家 SDK 版本。1. 结论先行先定义失败再定义成功。成功路径好写失败路径决定系统稳不稳。失败要可分类可重试、不可重试、需人介入别都当成再试一次。把错误变成结构化结果错误码、是否可重试、给模型看的短说明、给日志看的细节。重试必须有上限和退避否则工具抖动会被放大成费用和延迟雪崩。工具能调通 ≠ Agent 会用对还要约束何时允许调用。2. 为什么成功 demo 扛不住真实对话本地演示通常是工具总是在线参数总是合法返回总是完整 JSON用户场景里更常见第三方 API 偶发 429/5xx模型捏造了不存在的字段工具执行成功了一半写了库但通知失败用户以为已经帮我提交了实际只是查了状态如果只实现 happy pathAgent 会在失败时胡编、空转或重复调用。图1. 这些不是边角料而是工具接口的一部分。一个真实感很强的例子客服 Agent 调用「创建退款单」。上游超时后若返回值只有一句自然语言“好像失败了”模型可能再调一次造成重复退款若返回error_codeTIMEOUT, retryablefalse, side_effectunknown策略层就可以要求人工确认而不是自动重试。3. 一份最小失败契约每个工具建议至少写清字段作用error_code稳定枚举便于策略分支retryabletrue/false禁止模型自由发挥user_message可直接对用户说的短句log_detail仅日志含请求 id不含密钥timeout_ms超时阈值max_retries适配层重试上限side_effectnone / possible / done标明是否可能已产生副作用示例示意{ok:false,error_code:UPSTREAM_TIMEOUT,retryable:true,side_effect:unknown,user_message:上游服务超时请稍后重试或转人工,request_id:req_xxx}模型侧提示词里应写明遇到retryablefalse不要盲着重试side_effect不是none时禁止在未确认前再次执行写操作。4. 失败通常落在哪一层图2. 先定位层再改提示词或重装框架。层典型问题优先动作工具本身服务挂、权限、配额修凭证、熔断、降级适配/Schema参数类型、必填、枚举收紧 schema加校验Agent 策略该不该调、何时调改策略与权限不先怪工具用户预期以为已提交产品文案与确认步骤很多 Agent 很蠢的问题其实是适配层允许了过宽的参数或策略层允许在高风险操作上自动重试。4.1 参数校验为什么要放在适配层不要指望模型永远生成合法参数。适配层应校验必填与范围拒绝未知字段或明确忽略策略把校验失败映射成VALIDATION_ERROR, retryablefalse这样模型会被引导修正参数而不是把脏请求打到上游。5. 部分成功最容易被忽略的坑例如工单已创建但发邮件失败。若只返回一个布尔值Agent 无法解释状态。更稳妥返回明确状态机created/notified/failed_notify提供补偿接口或人工工单链接禁止在不确定时假装全部完成对用户可以说退款单已创建单号 xxx通知短信发送失败已转人工补发。这句话比含糊的失败有用得多。6. 重试策略的底线错误类型建议网络抖动、429、502有限次退避重试参数错误、权限拒绝不重试改输入或停超时且可能有副作用不自动重试写操作未知错误记日志降级或转人工退避要带抖动避免多会话同时打爆上游。总重试预算应写入契约而不是留给模型临场发挥。7. 适合马上做的和不适合一上来做的适合马上做为每个工具补齐错误码与retryable给超时和重试写死上限高风险操作转账、删数据、发公告强制确认给每个写工具标明side_effect不适合一上来做没失败契约就接一堆工具用再问一遍模型代替结构化错误让 Agent 在不可重试错误上循环调用把生产写权限和只读查询混在同一工具里且不分层级7.1 快速能做的改造清单若你已有三个以上工具不必重写框架按这个顺序补给每个工具返回值统一包一层okerror_coderetryableuser_message写操作补side_effect读操作固定为none适配层加超时超时默认retryabletrue且side_effectunknown除非你能证明请求未达上游策略提示词加三条硬规则不可重试不重试未知副作用不重做写操作连续失败转人工准备四个故障用例超时、401、参数缺失、上游 500全部要跑过做完这五步成功率未必立刻上升但失败时系统会变得可解释排障时间通常会明显下降。和 MCP / function calling 的关系协议解决的是怎么暴露工具失败契约解决的是工具坏了以后系统怎么表现。两者叠在一起才接近可运营。8. 常见误区误区更好的做法失败就返回一段自然语言同时给机器可读字段所有错误都重试三次按retryable分支工具越多 Agent 越强工具越多失败面越大只测成功样例用故障注入测超时与权限信任模型自己总结错误契约字段为准9. 术语速查术语含义失败契约对失败形态、字段、重试策略的事先约定可重试错误临时故障允许有限次重试适配层把外部 API 转成 Agent 可用的工具接口熔断连续失败后短时间停止调用上游副作用调用可能已改变外部状态9.1 评审或上线前的验收问题可以拿去问自己或问供应商工具超时后会不会自动再打一枪写接口权限失败时用户看到的是什么日志里能不能定位到请求 id部分成功有没有状态机还是一个布尔值糊弄过去连续失败是否会熔断熔断恢复条件是什么高风险操作有没有强制确认确认超时怎么处理五问答不清就还没到「可以放心把工具交给 Agent」的程度。连通性 demo 只能证明网络通不能证明失败可运营。10. 小结给 Agent 加工具工程上半场是连通下半场是失败怎么被理解、被限制、被恢复。先写失败契约成功路径反而好写也更接近可上线。