
做AI应用开发的同学应该都有过这种体验模型跑demo的时候一切都很美好但只要一接进真实业务链路智能体就开始“掉链子”——要么多绕了两步才摸到目标接口要么直接卡在某个中间状态出不来甚至把参数填错一路错到底。问题不在于模型本身强不强而在于我们根本没有一套标准去回答一个非常基础的问题这个Agent到底能不能稳定地“触达”它该触达的地方我折腾了大半年最后沉淀了一个叫Agent-Reach的评测与探测方案。名字是我自己起的取“智能体可达性”的意思。它的核心不是给模型打分也不是跑几个benchmark看谁聪明而是专门回答三件事Agent在真实任务链路里能不能找到正确的工具、能不能记住中间状态、以及出错之后能不能自己爬出来。这篇文章就把我从零搭建Agent-Reach的完整过程、设计思路、踩过的坑全部摊开来讲。1. 项目核心思路为什么非要用“可达性”来度量Agent1.1 现有评测体系的通病都在测“智商”没人测“手脚”现在市面上的Agent评测大部分还是在测模型的“智商”维度比如推理能力、知识问答、代码生成。这类评测有一个共同前提任务都是一次性完成的模型回答完就结束了。但真实业务里的Agent根本不是这么工作的它要面对的是一个连续过程先读用户需求、再决定调哪个API、解析返回结果、判断下一步动作、失败后换个策略重试、最后把结果组织好交回给用户。这个过程中最关键的其实是“手和脚”的配合——也就是工具调用、状态跟踪、错误恢复这些执行层面的能力。我见过太多在榜单上分数很高的模型一旦给它接上十几个工具让它独立完成一个跨步骤的订单处理流程立刻原形毕露有的在第三步就忘了最初目标有的把A接口的返回结果硬塞给B接口做入参有的明明调用失败了还不重试、就那么傻等着。所以我做Agent-Reach的第一个决定就是评测的单元从“问题-回答”改成“任务-执行”。每个测试用例不再是一道题而是一个需要Agent连续调用多个工具、维护中间状态、最终才能完成的任务。只有用这种方式才能测出Agent在真实业务里的“手脚协调能力”。1.2 “可达性”这个词背后的三层含义“Reach”这个词不是随便起的它对应执行能力的三个递进层次第一层是工具可达即Agent能不能在给定的工具集合里准确选出当前这一步该用的工具并且把参数填对。这一层考验的是模型对工具描述的理解能力和参数映射的准确性属于最基础的单步能力。第二层是状态可达也就是Agent能不能在完成多步任务的过程中始终记住全局目标、当前进度、以及各个中间结果之间的关系。这一层是大多数Agent翻车最严重的地方因为一旦上下文变长模型很容易“丢失焦点”把子任务的目标当成最终目标。第三层是恢复可达即当前面的步骤失败时Agent能不能识别失败原因、调整策略、重新尝试最终仍然找到一条通往目标的路。这层能力在现有评测里几乎没人测但在生产环境中恰恰是最重要的——真实API不可能永远稳定服务超时、返回格式变化、权限校验失败都是家常便饭。我把这三层拆成三个关键的评测指标也就是下文会详细讲的Reach Rate、State Hold和Recovery Rate。Agent-Reach这套体系的所有设计都是围绕这三个层次展开的。1.3 Agent-Reach适用的人群和场景如果你只是玩玩AI画图、写写文案那这套东西对你来说太重了。但如果符合下面任一情况Agent-Reach大概率能帮上忙你在做Agent应用落地比如客服机器人、数据分析助手、自动化运维工具需要给Agent接一堆内部API或工具。你在选型需要对比不同的Agent框架或基础模型光靠几个demo演示没法判断谁在实际执行链路里更稳。你已经有Agent上线但线上总出各种“莫名其妙”的失败又不知道问题是出在模型本身还是你的工具编排。你在做Prompt工程或工具描述优化需要一个快速反馈环路来验证改动到底是变好了还是变差了。我在做的过程中几乎是把Agent-Reach当成一套“智能体体检设备”来用的每次调整Prompt、换模型、改工具描述都先跑一遍Reach测试集用数据说话。下面就把整个设计细节展开。2. 评测体系设计四个维度和一套指标计算逻辑2.1 维度A工具可达性Tool Reach这是最基础的一层测的是Agent能不能“看见并操作”正确的工具。我会为每个Agent准备一个模拟工具集每个工具都仿照真实业务里API的样子有明确的名称、描述、入参schema和出参格式。评测时Agent需要自主决定在什么时刻调用哪个工具、传什么参数。Tool Reach的计算公式是Tool Reach 正确工具调用次数 / 总工具调用次数这里“正确”有两个判定条件一是工具选对了二是在这个任务阶段调用它的时机是对的还是错的。比如一个“查询订单”的任务正确的链路是先调用“获取用户Token”再调用“查询订单详情”如果Agent先调了“查询订单详情”必然会因为缺少Token报错这种就算调用失败。这个指标需要特别小心一个陷阱重复调用惩罚。有的Agent遇到失败后会“疯狂重试”同一个错误工具连续调五六次。如果不做去重处理单次失败就占了五次错误调用Tool Reach的数值会被严重拉低但反映的其实是另一个维度的问题恢复策略不当。所以我在统计时做了限制同一个工具同一个参数组合在连续失败场景下只算一次错误多出来的重试计入另一个指标——无效动作率。2.2 维度B状态保持能力State Hold状态保持是我认为最核心的维度的原因在于真实业务任务的复杂度并不来自单步推理而来自多步之间的记忆连贯性。Agent需要在执行到第5步时还记得第1步拿到的订单ID、第3步算出来的折扣金额、以及最初用户到底想要什么。State Hold的评测思路比较直接给任务里埋“状态记忆点”在任务结束后要求Agent依据执行过程中的某个特定值回答问题。比如整个任务绕了很多圈最后问它最早查询的那个订单ID是什么或者第二步骤中系统返回的某个字段值是多少。如果Agent能准确回答说明它状态保持住了答错了说明它在执行过程中把关键信息丢了。实际操作时我倾向于用一套“动态断言”在评测配置里为每个任务预埋若干“断言点”每当模板任务流走到第N步时断言当前Agent上下文里是否还记录了关键变量。这样不仅能测最终结果还能定位到是哪一步开始丢状态的排查问题的时候比单纯看结果精准得多。2.3 维度C规划深度Plan Depth规划深度测的不是“规划的步骤多不多”而是“在关键分岔点上有没有做合理的路径判断”。我设计了若干带分岔的任务场景同一个用户请求可能对应两种合法的处理方式Agent需要根据某个条件比如用户等级、订单状态、库存数量来选择路径。比如一个退货处理任务如果订单状态是“已发货”Agent需要先走“申请退货审核”工具再走“创建退货单”工具如果订单状态是“未发货”则直接走“取消订单”工具。如果Agent无视状态信息直接用固定的工具序列Plan Depth的得分就会很低。这个维度解决了我之前一个很头疼的问题很多模型在简单任务里看起来很强但一遇到条件分支就开始乱串路径。它们的“规划”更接近模式匹配而不是真正的决策。Plan Depth就是专门把这个弱点暴露出来的。2.4 维度D容错恢复能力Recovery Rate这是Agent-Reach里我花最大力气设计的维度也是市面上同类评测几乎不覆盖的部分。真实环境里的工具调用不可能100%成功服务超时、数据格式变化、参数不合法都是日常。我专门设计了带故障注入的评测用例让Agent去完成一个“注定会失败”的步骤观察它如何反应。Recovery Rate的计算口径是Recovery Rate 最终完成任务数 / 总任务数但前提是整个任务过程中必然有一次或多次工具调用失败。我需要看到的是Agent能不能从失败中恢复继续寻找替代路径或者重试后最终完成任务。如果Agent遇到失败就直接放弃或者无限循环重试同一个错误操作Recovery Rate就会很低。这里我建议评测用例里故障注入的位置要有讲究最好分布在任务的不同阶段早期失败Agent还有充足剩余上下文和步骤、中期失败Agent已经积累了一堆中间状态、晚期失败Agent快要结束、之前的工作可能全部作废。不同阶段失败对Agent的打击是完全不同的晚期失败最能考验Agent的抗压能力。这也是Agent-Reach和其他评测框架最不一样的地方——它不是只测“顺利完成任务”的能力而是专门测“在逆境中还能不能完成任务”的能力。3. 实操过程从0到1搭建Agent-Reach评测管线3.1 第一步搭一套带状态的Mock工具服务做评测最忌讳用真实API。真实API有太多不可控变量网络抖动、限流、数据污染、权限变更这些都跟Agent本身的能力无关测出来的数据没法归因。所以我专门用一个Python服务来模拟整个工具环境每个工具都是一个POST接口内部维护一个小的状态机。以订单系统为例我会建这几个工具接口POST /tools/auth POST /tools/query_order POST /tools/calc_refund POST /tools/create_refund POST /tools/check_stock POST /tools/create_shipment每个工具之间都存在真实的依赖关系。比如query_order需要先通过auth获取tokencreate_refund必须依赖calc_refund算出来的金额如果你没算就直接创建接口会返回一个明确的业务错误“refund_amount_required”。这个设计的核心目的是让工具环境本身有“业务逻辑”Agent不能像调用独立函数那样乱序调用而是必须按照业务流程来。我还在每个mock工具里埋了一个可配置的错误开关通过请求头控制是否启用故障注入。app.post(/tools/query_order) def query_order(req: QueryOrderRequest): if fault_config.get(query_order).get(enabled): if fault_config[query_order][mode] timeout: time.sleep(8) raise TimeoutError if fault_config[query_order][mode] invalid_token: return {error: invalid_token, code: 40101} # 正常逻辑 return {order_id: req.order_id, status: shipped, ...}这一步是整个Agent-Reach的地基。Mock服务必须够“真”才有评测价值如果工具间的依赖关系都是假的测出来的“规划能力”就完全没有参考意义。3.2 第二步定义探针任务集Reach Probes我把评测用例称为“探针任务”每个任务都像一根探针专门探测Agent某一方面的执行能力。任务集分成四组对应前面说的四个评测维度每组十个任务左右。工具可达组的任务相对直接比如“查询订单号A2024001的物流状态并获取当前承运商联系方式”。任务里会故意放一个跟需求相近但无关的工具比如“查询订单号A2024001的支付记录”看Agent会不会被干扰。状态保持组的任务是长链条的比如“先查询订单A2024001计算退款金额创建退款单再把退款金额换算成美元格式”。中间会经过很多步骤最后要求Agent在总结里明确给出最原始的订单金额。这类任务的断言点埋得很深。规划深度组的任务是带条件分支的我会在任务描述里隐藏一个决定性条件比如用户消息里不经意地提到“这个订单昨天已经发货了”但返回给Agent的状态数据里已经包含了这个事实。看Agent是老老实实读取状态再决定路径还是按照默认流程走。容错恢复组的任务就要搭配故障注入了我会在任务执行到某个特定步骤时让mock服务返回一个“差错”观察Agent的反应。这组任务对Agent的打击最大但也最能暴露真实环境里的执行问题。3.3 第三步实现评测驱动循环和执行记录评测驱动逻辑我直接用一段可配置的Python脚本实现它会自动做下面几件事加载探针任务配置、启动Agent运行时、收集执行过程日志、执行断言、输出指标报告。Agent运行时这一步你可以用自己的框架LangGraph、Coze、Dify或者自研的都可以。Agent-Reach对外暴露的是一个统一接口只要你的Agent能接收一个任务描述字符串、返回一个执行日志对象就能接进来。执行日志是关键它必须包含每一步Agent的推理thought、调用了哪个工具、入参出参是什么、返回状态是成功还是失败、以及最终的回复文本。为了确保日志完整我强烈建议在Agent的工具调用层做一个统一的监控埋点别等到出了问题再去翻框架自带日志。def run_probe(agent, probe): loader ProbeLoader(probe) for step, action in enumerate(agent.stream(loader.task_text)): log_entry { step: step, thought: action.get(thought, ), tool: action.get(tool_name, ), args: action.get(tool_args, {}), result: action.get(tool_result, {}), status: action.get(status, unknown) } audit_trail.append(log_entry) return audit_trail, agent.final_response()整套评测流程我一般跑三轮以上因为LLM的输出有随机性单次运行结果不能代表真实水平。最终指标取多次运行的平均值同时记录标准差标准差过大本身就是问题——说明Agent行为不稳定这在生产环境里是致命的。3.4 第四步指标计算和报告生成所有探针任务跑完后脚本会汇总生成一份评测报告。报告包含三页第一页是总览列出当前Agent配置下的四个核心指标Tool Reach工具选择准确率、State Hold状态断言通过率、Plan Depth分支路径决策正确率、Recovery Rate故障环境下的任务完成率。旁边还会展示平均完成步数和无效动作率无效动作率是判断Agent执行效率的关键如果这个值很高说明Agent在“空转”做了大量无用功。第二页是单任务明细每个探针任务都有独立的执行日志和时间线可以逐步骤查看Agent每一步做了什么决策。排查具体问题基本都在这一页一眼就能看出是第几步开始跑偏的。第三页是对比视图支持把多次评测结果放在一起对比。比如要比较换了Prompt后的效果直接跑两轮Agent-Reach看指标是提升还是下降比拍脑袋判断靠谱一百倍。---------------------------------------------------------- | 指标 | v1.0 | v1.1 | v1.2 | 变化 | ---------------------------------------------------------- | Tool Reach | 82% | 88% | 90% | 8% | | State Hold | 61% | 70% | 75% | 14% | | Plan Depth | 55% | 68% | 72% | 17% | | Recovery Rate | 40% | 51% | 58% | 18% | ----------------------------------------------------------3.5 第五步回归测试和阈值告警Agent-Reach跑几次之后就不再只是“评测工具”了它变成一个完整的回归防线。我会把整套探针任务集固化到CI流程里每次改动Agent配置都自动跑一轮当某个核心指标跌破设定阈值时立刻报警。阈值怎么定我建议先跑10轮拿到基线后取“均值减两倍标准差”作为下限。比如Tool Reach稳定在88%左右、标准差3%那阈值就设在82%。低于这个值说明改动大概率引入了退化。这一步的价值在你迭代到后期会越来越明显。Agent应用的Prompt和工具配置动得非常频繁很多时候你以为改了一句话没问题实际上某个老任务的能力已经被悄悄削弱了。没有自动回归这些退化会藏在线上、藏在用户投诉里等你发现已经晚了。4. 常见问题与排查技巧实录4.1 Agent目标漂移跑着跑着就忘了自己最初要干什么这是我在Agent-Reach评测中遇到的最频繁的问题尤其是在长链路任务里。执行到第五步Agent的对话上下文里已经堆积了大量中间结果、工具返回的JSON、系统提示模型开始“迷失”在细节里把某个子任务的目标当成了最终目标。典型案例任务要求“查询订单状态并若已发货则创建物流提醒”Agent成功查到订单是已发货状态然后开始滔滔不绝地总结订单详情忘了还要“创建物流提醒”这一步。这就是典型的目标漂移。排查思路回到执行日志里找关键节点看那一步Agent的thought突然从任务导向变成了描述导向。一旦发现漂移我的处理方式往往不是换模型而是优化Prompt的结构把最终目标放在一个固定、显眼的区块里并明确要求“最终回复前必须检查是否已完成所有要求”。实测下来很稳State Hold指标能提升十几个百分点。4.2 参数幻觉工具调用参数的“看起来对实际是编的”第二个高频问题是参数幻觉。Agent选对了工具但填的参数是从别处“复制”过来的甚至直接编一个。比如查询订单时传了一个根本不存在的订单号或者把字符串类型的参数传成了对象结构。这类问题在Agent-Reach的工具可达指标上会明显暴露正确率不高。针对这个问题我做了几件事一是改写工具schema里的参数描述把关键参数的含义写得更具体二是在mock服务里增加参数合法性校验非法参数会返回明确的错误代码三是把参数生成和工具调用拆成两步让Agent先“推导”参数再执行调用而不是一步到位。做Agent-Reach这一轮优化时我最大的体会是“模型本身不理解业务含义它只是在做概率匹配。你能做的就是把业务规则通过工具描述和错误反馈一点点‘喂’给它。”4.3 恢复策略僵化要么不重试要么无限死循环故障注入任务里最让人抓狂的行为是Agent在失败后陷入无效循环。同一个工具、同一个参数反复调用七八次每次都得到一样的错误但它就是不肯换一条路。我见过一个Agent在create_refund工具连续报错“amount_mismatch”之后仍然坚持用同一个错误金额重试了11次最后时间耗尽任务失败。这个问题的根源在于模型的“过度自信”它不相信自己的输入有错反而认为是服务端的问题。处理方案一是在系统Prompt中强加“最多连续重试3次若错误类型相同必须尝试替换输入或调整策略”的规则二是在工具返回错误信息中直接携带“建议修改哪个参数”的提示引导Agent去改参数而不是无脑重试三是在评测指标里统计“同错误重试率”单独追踪这个问题。经过这轮改造Recovery Rate从40%左右提升到接近60%效果很明显。4.4 评测结果波动严重同一套配置两轮结果天差地别如果你发现Agent-Reach的评测结果很不稳定先别怀疑是评测代码有bug先看两个地方第一是模型温度设置。Agent评测我建议把temperature固定为0或非常低的值以保证输出相对确定。虽然无法完全消除随机性但可以把波动控制到可接受范围。第二是上下文里是否混入了随机内容。有些Agent框架会默认在每次执行时拼接当前时间、随机用户ID、环境变量等这些看似无关的细节会显著影响模型输出。为了方便复现我给Agent-Reach加了一个“会话种子”机制每次执行时注入固定的用户会话信息保证除了模型自身的随机性外其他变量全部可控。如果依然波动就重复跑5到10轮用均值和标准差来评估别单看一轮的结果就下结论。4.5 故障注入的副作用Mock服务状态污染故障注入虽然好用但也有个烦人的副作用——状态污染。比如上一个任务把某个订单设定为“已发货”状态下一个任务再查同一订单时就永远返回“已发货”导致Agent的路径决策被上一个任务的残留状态影响。解决方式是给每个探针任务设置独立的“沙箱订单号”。具体做法任务初始化时由脚本生成一个随机订单号做完这个任务就销毁互不干扰。这个方法虽然简单但能避免大量莫名其妙的评测误差。4.6 执行日志断裂查问题查到一半日志没了评测一个长任务时最大的痛苦是日志不完整。有时Agent调了工具但日志里没记录出参有时framework内部重试了但日志只记录了一次。这些情况会严重拖累问题归因。我的处理办法是在工具调用入口和出口分别加一层“包裹函数”不管调用成功还是失败都强制把入参、出参、耗时、错误堆栈完整记录到评测日志里。同时在Agent调用链路上埋一个“覆盖计数器”如果framework内部发生了重试也能从日志里看出总共尝试了几次。这类细节在评测搭建阶段就会想着“多一点无所谓”但真正定位问题时帮助巨大。5. 经验沉淀与后续扩展思路整套Agent-Reach体系从设计到跑通前后花了两个多月期间反复调整了探针任务的设计方式和指标计算口径。我个人在实际操作中最大的体会是做Agent评测最难的不是写代码而是定义清楚“什么算对”。工具调用的对错、状态保持的断言点、路径决策的标准每一个都需要结合真实业务场景来定没有一套通用答案。这也是Agent-Reach最核心的价值——它逼着你把模糊的“Agent表现好不好”翻译成一组明确的、可复现的、能追踪的具体指标。如果你准备在自己的项目里尝试我的建议是从小处开始先不用搭建全套Agent-Reach选3个你最在意的任务场景手动定义步骤和断言跑起来看到数据反馈再逐步扩展成完整评测体系。别想着一步到位Agent的能力本来就是分布在不同层面的一层一层测、一层一层补才是正常节奏。最后再分享一个小技巧每次模型升级或替换的时候第一时间跑Agent-Reach的核心探针任务集。你会发现有些新版模型在某些维度上反而不如旧版比如推理能力增强了但工具调用的格式遵循性下降了。这种跨版本的差异只有用统一的评测框架才看得见。Agent-Reach现在依然是我日常开发流程中不可或缺的一部分每次往那个目录里加一个新探针任务我心里就踏实一分。