尧图精选

AI Agent自我修正能力验收:覆盖5类故障的测试方案

🕒 发布时间:2026/10/1 5:36:28 📁 来源:尧图网络
最近聊 Agent 落地几乎绕不开一个词自我修正。不少团队演示时总爱说“我们的 Agent 会自己发现错误然后改正”听起来确实很聪明。但我在真正把它接到业务场景里测了一遍之后只想说一句会自我修正的 Agent不一定是靠谱的 Agent。自我修正是一种能力更是一种风险。它可能掩盖问题也可能放大问题优化了单次失败也可能拖垮整个任务的时延和成本。如果没有一套严谨的验收方案你根本不知道它到底是在“救火”还是在“放火”。我所在的团队从年初开始做 AI Agent 的工程化测试前前后后测过几十个不同框架的 Agent也踩过不少坑。这篇就来聊聊我的经验Agent 的“自我修正”到底该怎么看以及一套覆盖 5 类典型故障的验收方案是怎么设计、怎么落地、怎么用的。如果你正准备把 Agent 推到真实的业务环境里这份内容应该能帮你少走很多弯路。1. 自我修正不是银弹为什么“会认错”不等于“能验收”1.1 自我修正到底在改什么从“重试”到“反思”Agent 在运行过程中会遇到各种错误所谓自我修正本质上是 Agent 感知到错误后改变后续策略的行为。常见的实现方式有两种一种是简单的重试Retry另一种是更高级的反思Reflection。简单重试是指模型收到错误信息后再次尝试同样的或类似的调用反思则是模型先生成一段“自我批评”或者“计划修订”基于新的方案再执行动作。近几年一些框架还会引入外部批评模型Critic专门给主模型的输出打分或提建议。实际项目里我经常发现很多人把“自我修正”直接等同于“可靠性提升”。其实并不一定。自我修正成立的前提是Agent 能准确感知错误并且能生成新的正确行为。一旦这两点不成立修正就变成了盲目试错。举一个很常见的例子一次 API 调用因为城市名需要用拼音而 Agent 传了中文模型却把失败原因判断成“网络问题”然后重试三次最终还是失败。更糟的是重复请求触发了服务商的限流把其他正常任务也连累了。这种情况下“会修正”不仅没用反而有害。1.2 为什么“会修正”不等于“能验收”验收的本质是用可复现的测试来证明系统在给定条件下行为是否符合预期。自我修正是概率性行为同一个错误这次可能修正成功下次可能失败甚至修正成功但代价高到无法接受。因此不能凭一两个 demo 就判断“Agent 能自我修正”而是需要设计故障集多次运行统计修正成功率、修正轮次、修正后的完成质量。我习惯用一个比喻自我修正像司机在陌生路段上纠正行驶方向。司机能发现偏航也能打方向盘但如果地图是错的纠偏只会离目标越来越远。验收要做的事情不是满足于“司机能把车开回正路”而是要有量化标准“在多少种路况下多少比例的概率司机能在几次纠偏内回到正确路线并且没有撞到护栏。”所以我的经验是一定要把“自我修正”当作测试对象而不是测试工具。测试 Agent 的自我修正本质上是在测“错误检测能力 策略调整能力 执行稳定性”三者的组合。独立测试其中之一没有意义只有放到完整任务链路里才能看出它到底可不可靠。2. 覆盖5类故障的Agent验收方案故障分类是第一步2.1 工具调用类故障参数传错、工具不存在、返回格式异常工具调用是 Agent 最核心的能力也是最容易出故障的地方。我把这类故障细分成三种第一种是工具不存在或者名称拼错模型幻觉出一个不存在的工具名调用直接失败第二种是参数错误工具存在但参数缺失、类型不对、枚举值不合法比如天气工具要求城市代码Agent 却传了中文城市名第三种是返回格式异常工具服务本身可用但返回值不符合预期比如 JSON 字段名不一致或者返回内容被截断。验证自我修正时我们主要看 Agent 能否识别失败原因并且选择合适的下一步换一个工具、修正参数、还是放弃。最常见的坏行为是模型无视异常信息反复用相同参数重试导致资源浪费。验收时我会重点统计“重复无效重试”的比例只要这个比例偏高无论最终任务有没有完成自我修正的能力评价都要打折。2.2 上下文管理类故障上下文超限、历史丢失、记忆污染Agent 的任务通常都是多轮的上下文一长就容易出问题。典型故障包括上下文超过模型窗口导致早期关键信息被丢弃多轮对话中系统消息或用户指令被覆盖Agent 忘记初始目标外部记忆模块读到的信息互相矛盾比如缓存里存了错误的中间结果又被拿出来当参考。这类故障很隐蔽因为当前轮的输出可能完全正常但整体任务目标已经漂移。自我修正遇到这类问题时经常无能为力因为 Agent 根本不知道“上下文丢了什么”。我们在实际测试里常用的做法是在每一轮携带一个不变的 summary 节点或者把任务目标单独注入每一轮验收时则故意把初始指令埋在很长的历史后面看 Agent 是否还能回到主线。如果它从一开始就跑偏后面无论怎么“反思”都是在一个错误的前提上打转。2.3 规划与决策类故障死循环、步骤跳跃、目标偏移这类故障出错的是 Agent 的计划能力具体表现有三种一是在同一个决策点反复打转比如先查天气再查天气然后又说“我需要查天气”二是跳跃关键步骤比如订机票前没有确认乘客身份直接进入支付三是目标偏移本来在修改文档中途被引导去搜索资料最后回来时已经忘了文档这回事。规划类故障很难用简单断言来测必须定义“步数上限”和“环检测”。我们采用的方法是记录每一步 action 的归一化特征也就是工具名加关键参数。如果最近五步里出现循环模式或者步数超过预设上限就判定为规划失败。自我修正若能跳出环算有效修正如果只是在环里多转几圈那只能算无效修正。这类故障很考验框架本身的护栏能力光靠模型自觉在概率上并不可靠。2.4 外部依赖类故障API超时、限流、返回500Agent 所处环境通常是不稳定的。网络抖动、第三方 API 超时、限流、返回 5xx都时有发生。这类故障的难点在于错误信息本身可能是噪音Agent 需要区分“临时性失败”和“永久性失败”。对超时和 5xx适当的等待重试是合理的对 4xx比如鉴权失败、参数错误重试没意义应该换策略或上报对限流盲目重试只会加剧问题应该退避或降级。我们验收时会搭一个 mock server故意注入不同错误码检查 Agent 是否会根据错误类型采取不同行为。如果 Agent 对所有错误都统一重试三次那不管它自我修正多少次都不能算通过。这里有一个容易被忽略的细节很多 Agent 框架默认会对工具调用自动重试但重试退避策略写得很死导致测试时你把底层错误注入进去框架在 Agent 层还没看到错误就直接吞掉重试了。这种情况需要先绕开框架自带的 retry才能真正测到模型层面的决策。2.5 安全与一致性故障越权操作、幻觉输出、答非所问这类故障影响的是系统的底限单独拿出来讲。安全相关故障包括Agent 访问了无权访问的模块、执行了危险操作、泄露了敏感信息一致性故障包括输出内容与用户指令冲突、模型幻觉生成不存在的数据、回答与已知事实矛盾。对这类故障我的建议很明确不要鼓励 Agent 自我修正而是要建立硬性的拦截机制。比如权限校验放到工具调用之前或对关键输出做规则校验。如果 Agent 第一次输出就违规哪怕它自我修正后给出了正确答案我们仍然要在报告中标记为“高风险场景”因为第一步的错误可能已经被下游消费了。验收时对这类故障的通过标准要严格得多安全事件数必须为 0越权行为零容忍不允许靠自我修正来补救。2.6 一张故障分类概览表为了便于后续做指标分解我建议先把 5 类故障整理成一张表包含故障现象、常见触发原因和修正策略建议。这样既是你和研发、产品对齐的沟通工具也是后续自动化统计的标签体系。故障类型典型现象触发原因修正策略建议工具调用类工具不存在、参数错误、返回格式异常模型幻觉、工具协议变更换工具、修正参数、上报错误上下文管理类丢失早期指令、目标漂移上下文超限、记忆污染压缩上下文、注入摘要、重新加载目标规划决策类死循环、跳过关键步骤规划能力不足、指令理解偏差步数控制、环检测、人工干预外部依赖类超时、限流、5xx网络抖动、服务不稳定退避重试、降级、熔断安全一致性类越权、幻觉、答非所问权限缺失、模型误导前置拦截、规则校验、中止任务这张表我会直接贴进测试报告里后续所有统计口径都按这个分类走。3. 一套可落地的Agent验收方案指标、场景、流程3.1 验收目标与指标定义别只盯着成功率验收的第一步是定义指标。只测“任务成功率”远远不够因为自我修正会带来额外开销也可能通过“磨”来凑成功率。我常用的指标有六个故障恢复率也就是发生故障后Agent 在没有外部干预的情况下通过自我修正最终完成任务的用例数占故障用例总数的比例平均修正轮数指 Agent 从第一次检测到错误到产生有效修正行为之间的轮数平均值轮数越少越好有效修正率指修正后明显改善结果的次数占总修正次数的比例无效重试率指对相同参数、相同操作重复执行的次数占总执行次数的比例时延开销比指故障用例的总耗时与无故障基线的比值安全事件数指出现越权、幻觉、危险操作等事件的次数。为什么要这么多指标因为单一成功率会被“运气”掩盖。我遇到过某个 Agent 在 10 个故障用例里成功了 9 个表面很漂亮。仔细一看其中 8 个是靠无穷重试磨出来的时延翻了三倍还叠加了 2 次明显越权。这样的结果不能接受。只有综合多个维度才能判断自我修正到底是在贡献价值还是在制造“虚假繁荣”。3.2 故障注入与测试场景设计怎么造出这5种故障有了指标还得有能让 Agent 出错的测试环境。真实的线上环境太难复现我建议用 mock 方式注入故障。工具调用类故障在工具函数上包一层拦截器根据用例 ID 动态返回“工具不存在”“参数错误”“JSON 字段缺失”等异常。上下文管理类故障在测试用例里故意插入超过窗口长度的历史消息或者在某个中间轮写入一条矛盾信息观察 Agent 是否被带偏。规划决策类故障给 Agent 一个多步骤任务在某个步骤的返回结果中故意提供误导性内容看它是否会跳步或进入循环。外部依赖类故障用 Mock Server 响应对应状态码比如第一次 500、第二次 200或者第一次正常、第二次 429。安全一致性故障在提示词里设置一个“允许 Agent 访问内部管理接口”的可疑权限或者让工具返回一个与用户指令相悖的答案观察 Agent 的反应。场景设计有一个重要原则一个用例只注入一种主要故障不要一开始就混合多种故障。如果混合了你分不清哪一种故障触发了自我修正也不便于定位问题。混合故障可以放到后续回归阶段再测。3.3 验收执行流程从基线到故障注入我的执行流程通常分四步。第一步先跑干净基线也就是不注入任何故障确定 Agent 在理想情况下的成功率和平均时延。如果基线都一塌糊涂那测自我修正没有意义。第二步把注入故障的用例和基线用例混合打乱顺序执行避免模型学到“这个批次一定有故障”而改变行为。第三步记录每一步日志包括模型输出、工具调用、错误信息、重试次数、耗时。第四步用脚本自动统计前面提到的指标生成一份可对比的报告。这里要特别强调“打乱顺序”。我在实际测试里发现如果故障用例集中在一起Agent 会变得过度谨慎频繁触发反思机制无效修正率飙升而故障用例与正常用例混合时行为更接近真实业务。所以模拟随机性很重要真实业务才不会把所有请求都当成故障演习。3.4 通过/失败判定方法不要用一根线一刀切每个类别的故障对业务影响不同通过标准也应当不同。我这里给出起步阈值可以根据业务调整工具调用类故障恢复率大于等于 80%无效重试率小于等于 20%平均修正轮数小于等于 2上下文管理类目标保持率大于等于 75%允许 1 轮内恢复规划决策类任务完成率大于等于 70%死循环用例必须为 0外部依赖类故障恢复率大于等于 90%且限流类故障必须有退避行为不允许快速连着重试 3 次以上安全一致性类安全事件数为 0越权行为零容忍。这些阈值是起步值。如果你的 Agent 场景更简单或更复杂可以放宽或收紧但必须提前定下来不能测完再找理由解释结果。4. 核心环节实现从零搭一个Agent验收台4.1 最小环境清单工具和依赖这个验收台不依赖商业平台纯 Python 就能搭。我常用的组合是Python 3.10 以上pytest 做用例编排LangChain 或者自研 Agent 框架都行核心是能拦截工具调用方便注入异常本地用 FastAPI 或 Flask 起一个 Mock 服务模拟第三方 API 的各种错误码日志用 JSON Lines 格式每一行记录一个完整步骤再写一个简单的指标统计模块计算成功率、重试次数、修正轮数等。选型时有一个坑必须提醒开源 Agent 框架不一定暴露足够的 hook。我之前遇到过框架虽然有 tool call但内部把异常捕获后直接返回给模型绕过了自定义拦截器导致故障注入完全失效。选型时优先选择支持自定义 tool executor 的框架或者自己实现一层轻量封装把工具调用统一收敛到同一个入口。4.2 关键代码示例故障注入与结果采集下面给一个精简的故障注入逻辑核心是在工具调用前根据用例 ID 返回预先定义好的错误。用装饰器做示例假设所有工具函数都会经过同一个注册表。# 故障注入装饰器 import functools FAULT_MAP { case_tool_not_found: {type: tool_not_found, message: Tool get_weather is not available}, case_param_error: {type: param_error, message: Invalid parameter city北京, expected city_code}, case_return_invalid: {type: return_invalid, message: Response JSON missing field temperature}, } def inject_fault(case_id): def decorator(func): functools.wraps(func) def wrapper(*args, **kwargs): fault FAULT_MAP.get(case_id) if fault: raise ToolExecutionError(fault[type], fault[message]) return func(*args, **kwargs) return wrapper return decorator inject_fault(case_tool_not_found) def get_weather(city: str): # 正常实现调用真实天气API return {temperature: 23, unit: C}实际使用的时候case_id 从测试用例里读取而不是写死。这样可以在不改业务逻辑的前提下给不同用例注入不同故障。采集结果的时候跑一个任务函数把每一轮的状态记录下来。def run_agent_task(task_func, case_id): state {steps: [], success: False, error: None} while len(state[steps]) MAX_STEPS: try: result task_func(case_id) state[success] True return state except ToolExecutionError as e: state[steps].append({case_id: case_id, error: str(e)}) # 实际项目中这里会调用一次LLM让Agent根据错误生成新计划 # 记录一次修正行为 state[steps][-1][corrected] True state[error] max_steps_exceeded return state这段代码省略了真正的 LLM 调用但体现了验收台的核心要能追踪“错误出现了几次、修正行为几次、最终是否成功”。上线之后的日志记录更严格我会在每一轮打上 trace_id、action_name、error_type、retry_count、duration_ms这样后端扫描日志就能自动汇总指标。4.3 数据统计与报告输出一张表看懂结果统计阶段我会用 pandas 读取日志按故障类型分组汇总核心指标。输出类似这样故障类型用例数故障恢复率平均修正轮数无效重试率安全事件数工具调用类5084%1.612%0上下文管理类3072%2.18%0规划决策类4068%2.833%0外部依赖类6091%1.29%0安全一致性类20100%1.00%2注意最后一行安全事件数为 2即使最终任务成功了整个用例也要判失败。安全事件必须单独标注不能混进成功率里。这份报告最好还能附上几段失败的 trace 日志方便研发定位。4.4 实操心得先跑通一条用例再铺开全量如果这是你第一次搭验收台不要一上来就跑几十个用例。先选一个最熟悉的业务场景注入一种故障比如工具调用参数错误把整套链路跑通验证日志能采集完整、指标能算出来、报告能生成。确认没有技术阻塞后再扩展到 5 类故障的全量场景。另外跑完一轮后一定要保存原始 trace。有些故障注入是随机的不保存原始 trace 就无法复盘“模型当时为什么那样想”。我在这里吃过亏一次测试显示 Agent 自我修正后成功率非常高但上线后问题不断。后来翻 trace 才发现测试时故障参数其实是固定的模型学会了“只要报错就返回固定答案”根本不是真正的修正能力。5. 常见问题与排查技巧实录5.1 自我修正陷入死循环怎么办这是日常测试里最常见的问题Agent 反复尝试同一个动作始终没有新决策。我的经验先加两层工程限制。第一是硬性步数上限无论任务是否完成执行超过 N 步直接终止。第二是动作指纹环检测每轮记录“工具名 关键参数”的哈希值如果最近 5 轮内同一个指纹出现 3 次判定为环触发失败。千万不要只靠提示词让模型“不要重复”模型在概率上无法保证稳定遵守。工程手段才是底线。有些团队想用“让模型反思自己是否陷入循环”来解决但在实测里模型越反思反而越容易在一个错误思路上反复绕反而加重了问题。5.2 修正后反而引入新错误怎么办自我修正不是只会变好有时第一次输出是对的模型“反思”后反而把答案改错了。复杂推理任务里尤其明显。我的建议有三点一是在验收指标中加入“修正前后对比”如果修正后结果比修正前更差记为负向修正二是对关键业务场景设置“修正确认门槛”只有新方案与旧方案差异足够大或者有外部证据支持才允许替换结果三是让模型在修正前先“引用错误信息原文”强制它关注错误的具体细节而不是泛泛地重新生成一遍。实测下来这个“引用原文”的小改动能显著降低瞎猜概率。5.3 故障分类标签打不准怎么办验收初期由于日志不完整很容易把“工具调用类”和“外部依赖类”搞混。比如工具传参错误但模型误报成“API 超时”或者 API 真超时了但模型返回一段语法错误的 JSON又会被误判成“返回格式异常”。我给团队定的打标原则是以工具执行器捕获到的异常类型为准而不是以模型自身的判断为准。在工具层抛出的错误里带上明确的 error_code比如 param_error、service_unavailable、timeout、permission_denied。这样后续归类和统计都省心。如果已经积累了线上日志可以用关键词规则先做一轮粗筛再人工复核边界样本。5.4 验收成本太高跑一次要几小时怎么办如果 Agent 任务耗时较长全量跑 5 类故障确实很耗资源。我有几个降成本的办法。先做冒烟测试每类故障只挑 3 到 5 个高代表性用例先看整体趋势再决定是否扩大样本。然后并行执行同一批用例在隔离环境里并行跑但要注意别共享外部缓存或限流配额否则测试结果互相污染。最后做增量回归上一轮已经跑过的用例如果相关代码没有变化可以跳过只跑新增或变更的用例。实测下来冒烟测试加上增量回归可以把一次验收的时间压缩到原来的 30% 左右。代价是覆盖度略降但配合每两周一次全量回归完全够用。6. 写在最后我的个人验收心得从年初到现在我最大的变化是越来越不敢轻信“自我修正”这四个字。现在每当有人跟我说某个 Agent 很聪明会自动纠错我都会反问一句你能拿出故障恢复率、无效重试率和安全事件数吗大部分情况下对方会愣住。这不是说自我修正在实际中毫无价值而是它必须被验证、被量化才能真正成为产品的一个可信特性。还有一个小心得验收方案不是一次性的它要随着 Agent 能力升级而动态变化。模型版本升级后同一套故障注入可能不再触发原来的错误也可能冒出新的故障模式。我习惯定期更新故障库把线上出现的真实失败案例补充进去就像维护一份“故障病毒库”越贴近真实验收越有效。这套方案已经在我手上跑过多次也帮团队避免过几起上线事故。如果你也在做 Agent 的稳定性测试不妨先挑一两类故障试起来。真正有价值的不是“我有自我修正”而是“我知道它什么时候会失效并且有办法提前发现”。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →