Agent Seer:基于MCP自动合成智能体评测用例的新方法
Agent 类的应用最难回答的往往不是“模型的模型有多聪明”而是“它到底能不能把事情办成”。这句话放在 2025 年的技术圈几乎成了每个做过智能体落地的人的共同感概。模型层面的推理能力可以用一堆公开 benchmark 衡量但 Agent 一旦接上工具、开始多轮调用、操作外部系统评测就变成了一个比开发还要贵的工程问题手工写用例费时线上场景覆盖不全模型稍微升级一次又要重新回归。“Agent Seer”这个方向想解决的恰好就是这个瓶颈把 MCPModel Context Protocol模型上下文协议规范中机器可读的工具定义当作评测用例的“锚点”自动合成智能体评测集。它的核心判断是与其靠人脑想象 Agent 会遇到什么场景不如让工具的输入输出 Schema 变成场景生成的“事实来源”。工具定义了系统对外能做什么Agent 的所有有效行为都必须落在这些定义之内那么围绕工具定义自动生成评测任务自然比人工拍脑袋列需求覆盖得更完整、迭代得更快。这篇文章不会只停留在概念层面。我会把它拆开讲清楚为什么现有 Agent 评测让人头疼、MCP 规范为什么适合做“评测生成器”、Agent Seer 的自动合成流程是怎样的以及你在自己的项目中如何用一个最小可运行的管道把这套思路落地。看完之后你至少能判断自己的 Agent 项目该不该往这个方向投入。1. 这篇文章真正要解决的问题先给一个结论Agent 评测的瓶颈不是“没有评测工具”而是“评测用例的生产方式错了”。现在团队做 Agent 应用普遍状态是这样的一开始靠产品经理或开发同学手工写任务场景比如“帮我在日历上安排一个会议”之类的描述然后让 Agent 去跑人工判断结果对不对。场景少的时候还行一旦工具数量上升到几十个、跨工具组合的用例达到上百条就会陷入三个困境人力成本高。每条用例既要有任务描述又要有预期结果还要考虑边界条件。只有真正懂业务的工程师才能写而他们通常是最忙的人。覆盖率难以保证。人工写用例天然偏向“常想到的路径”遗漏的是那些低频但关键的组合场景比如工具超时、参数类型异常、中间步骤失败后的重试行为。回归成本高。MCP 工具一调整新增参数、改字段名、拆分工具手工维护的测评用例就得跟着改而且改没改完、漏没漏很难查出来。Agent Seer 的思路说白了就是把“写评测用例”这个动作从“人写”变成“根据 MCP 工具定义自动生成”。它并不是要取代人工判断而是让工具定义成为生成评测集的输入。系统读取 MCP 服务器暴露的 tools、resources 和 prompts用 LLM 结合这些规格去生成带明确断言条件的任务然后再通过执行器和断言器回放判断 Agent 是否真的完成了目标。如果你是一个开始搭建智能体评测体系、正在研究评测方法的工程师或者团队准备用 Dify、Coze 这类平台做企业工具集成这篇文章的控制重点正好是你现在会踩的坑。2. 为什么 Agent 评测这么难从一个常见的误判说起很多人第一次接触 Agent 评测会本能地把它理解成“更复杂的模型评测”。这个出发点就错了。模型测评让你给一句话模型吐出回复答案用规则或分类器比对就行。但 Agent 的产出是一个“行为轨迹”——它读了哪些上下文、按什么顺序调用了哪几个工具、工具返回异常后有没有改正这些都影响任务结果。只盯着最后一句回复通常会漏掉真正的失败点。稍微熟悉一点的人会提出第二个方案那我把工具调用是否成功当作断言总行了吧这个方案同样不完整。工具调用成功只代表“动作执行了”不代表“目标达成了”。比如一个天气预报 Agent 成功调用了天气查询 API却把“明天”当成“今天”查了工具层是成功的任务却是失败的。所以 Agent 评测实际要覆盖三层能力评测层级核心问题常见断言方式常见坑任务可用性用户目标最终是否达成最终状态、返回值校验只看最后输出忽略过程错误工具可用性工具选择、参数生成、调用顺序是否正确工具调用序列校验调用成功但参数语义错误规划可用性中途错误能否恢复、路径是否合理多步轨迹分析用固定脚本导致模型“背答案”另一个经常被忽略的问题是“用例污染”。如果用固定的任务描述反复测试大模型可能记不住答案但测试人员会在迭代中不知不觉把“预期结果”透露在提示词里Agent 只需要在输出里复现关键词就能骗过简单断言。这也是为什么 Agent 评测非常需要“动态生成”的能力——每次生成的用例在细节上有变化模型无法靠背题通过。理解了这三层结构之后Agent Seer 的真正落脚点就比较清楚了它不是把评测押在哪一层而是用 MCP 规范把三层需要的输入和断言全部结构化生成形成一条自动化的生产链。3. MCP 到底是什么不只是模型调用工具的标准要理解 Agent Seer先把 MCP 这个基础设施说清楚。MCPModel Context Protocol是一个开放协议用来解决大模型应用接入外部工具和数据时的重复劳动问题。在没有 MCP 之前每个智能体框架都要自己写一套工具调用协议参数格式不统一认证方式也各写各的有了 MCP 之后工具提供方只要按标准暴露一个 MCP Server支持 MCP 的客户端就可以直接调用。从实现视角看MCP 主要有几个组成Host承载大模型交互的应用比如 Claude Desktop或你自己的 Web 应用。Client在 Host 内部与 MCP Server 建立连接的一端负责发送请求。Server暴露能力的一端连接着具体的外部系统数据库、日历、代码仓库、浏览器。工具Tools可以被模型直接调用的函数每个工具都有名称、描述、输入 SchemaJSON Schema。资源Resources可以被模型读取的上下文信息比如文件内容、数据库查询结果。提示词Prompts预先写好的可复用指令模板方便业务方把操作流程固化下来。对 Agent Seer 来说最有价值的是 MCP Server 里那一份份机器可读的工具定义。因为它们不是给人看的 Markdown 文档而是有完整结构的 JSON Schema字段类型、必填项、枚举值、描述信息一目了然。传统 API 文档和 MCP 工具定义在这件事上有本质差别对比维度传统 API 文档MCP 工具定义格式Markdown / PDF人读为主JSON Schema机器可解析更新方式人工维护易滞后随 Server 代码发布强制同步评测可用性需要自己抽字段、写解析器直接作为 LLM 生成的输入语义完整度靠文档作者自觉有约定字段和结构约束换句话说MCP 让“工具能力”变成了一种结构化的、可程序化消费的资产。这份资产正是自动生成评测用例的理想输入它描述的是系统能力的全集而我们要做的就是从这个全集里有策略地采样出测评场景。4. Agent Seer 的核心方法从规范到用例的自动合成现在进入正题。Agent Seer 自动合成评测的流程可以拆成五步扫描读取一个或多个 MCP Server 的工具定义、资源描述和提示词得到结构化清单。解析从 JSON Schema 中提取关键信息包括参数名、类型、必填性、枚举范围、描述语义。合成交给 LLM结合工具描述生成候选任务场景、预期行为和断言条件。筛选用规则和有向性检查去掉重复、无效、不可执行的用例保证评测集质量。执行与回归在受控环境中运行 Agent记录工具调用轨迹用断言器判断结果。这五步里最关键的有四个设计点。4.1 用 JSON Schema 做“变量槽”工具定义中的 inputSchema 不是摆设。比如一个日历工具的 inputSchema 里有date字符串、title字符串必填、duration_minutes整数枚举。合成器可以把它变成一组自然语言变量槽日期、会议标题、时长。这样生成出来的任务就不是一句固定话术而是带有随机参数的任务模板请帮我在 {任意未来工作日} 创建一个标题为 {随机项目名} 的会议时长 {30 或 60} 分钟。每次评测时变量槽里的具体值都可以替换从而避免模型记住答案。4.2 用组合场景突破单工具覆盖单个工具的任务相对容易Agent Seer 的价值更体现在“跨工具组合场景”。比如日历工具有创建会议的能力通讯录工具有查同事邮箱的能力那就可以自动合成“先查张三邮箱再给他发一封会议邀请”的组合任务。组合场景越多越接近真实业务评测价值也越高。合成器可以根据工具之间的语义关联比如邮件发送工具需要一个联系人地址参数而通讯录查询工具正好能产出这个地址自动拼装。4.3 断言不只看最终结果还看工具调用序列很多评测系统只检查 Agent 输出的字符串。Agent Seer 更建议把“工具调用轨迹”作为一等观察对象。比如一个“删除服务器指定文件”的任务即使最终结果返回成功你也应该断言它确实调用了目标删除工具而不是调成另一个语义相近的“归档”工具。在实现时可以把断言拆成三层 JSON 结构final_result最终结果是否符合、tool_calls关键工具的调用是否发生、sequence调用顺序是否合理。4.4 让 LLM 生成场景但用规则防止幻觉LLM 生成评测场景的优势是速度快、表达自然隐患是可能编造不存在的参数值或者生成与工具实际能力无关的幻想场景。所以 Agent Seer 的筛选环节不能交给纯 LLM 自由发挥必须叠加规则检查生成的每个任务里用到的所有工具名称必须出现在 MCP 清单中用到的参数名必须能在 inputSchema 中找到必填参数不能缺失。这其实是一种“LLM 生成 规则制衡”的工程组合也是这一类评测生成器落地时的共性设计。4.5 一个最小示例从工具定义到评测用例以一个日历工具为例假设 MCP Server 暴露了这样的工具定义{ name: create_calendar_event, description: 在指定日历中创建一条新日程, inputSchema: { type: object, properties: { date: { type: string, description: 会议日期格式 YYYY-MM-DD }, start_time: { type: string, description: 开始时间格式 HH:mm }, title: { type: string, description: 日程标题 }, duration_minutes: { type: integer, enum: [15, 30, 60], description: 会议时长 }, attendees: { type: array, items: { type: string }, description: 参会人邮箱列表 } }, required: [date, start_time, title] } }合成器读入这份定义后生成的任务可能是{ task_id: eval_calendar_0001, task_desc: 今天是 2025-06-01请帮我创建一个在 2025-06-10 上午 10:00 开始、时长 30 分钟的会议标题为‘Agent 评测复盘’不需要参会人。, expected: { final_result: { type: success, message_contains: [已创建, 2025-06-10 10:00] }, tool_calls: { create_calendar_event: { count: 1 } }, sequence: [create_calendar_event] } }这个用例的新鲜之处在于任务描述里的关键参数是从 Schema 的枚举和格式约束里采样出来的参数语义和工具定义强绑定。模型没法“之前见过这道题”因为每次执行时可以把日期、标题、时长重新随机化。5. 动手实现一个最小 Agent 评测管道这一节我们落地一个简化版。目标是让你在当前项目里直接照搬思路而不是依赖某个未公开的神秘框架。整个实现用 Python 编写核心依赖只需要一个能调用 LLM 的 SDK以及标准库就能完成 JSON 处理。5.1 环境准备Python 3.9 以上能访问一个 LLM APIOpenAI 兼容接口即可一个 MCP Server 的工具清单可以静态 JSON 文件pip 安装openai或requests如果团队已经用了 Dify、Coze 等智能体平台也可以用平台的接口替代这里的 LLM 调用部分。5.2 第一步读取 MCP 工具定义实际项目中工具清单可以通过 MCP Client 动态拉取为了演示我们先用一个静态 JSON 文件代替# load_tools.py import json def load_tools(pathmcp_tools.json): with open(path, r, encodingutf-8) as f: return json.load(f) if __name__ __main__: tools load_tools() for tool in tools: print(tool[name], -, tool[description])mcp_tools.json示例[ { name: query_weather, description: 查询指定城市指定日期的天气情况, inputSchema: { type: object, properties: { city: {type: string, description: 城市名}, date: {type: string, description: 日期格式 YYYY-MM-DD} }, required: [city, date] } }, { name: send_email, description: 发送一封文本邮件, inputSchema: { type: object, properties: { to: {type: string, description: 收件人邮箱}, subject: {type: string}, body: {type: string} }, required: [to, subject, body] } } ]这一步的核心作用把工具定义集中到一个可编程的结构化集合后续合成器只依赖它。5.3 第二步合成评测任务合成器接一个大模型。提示词里放工具清单 JSON要求它输出符合格式的评测任务。需要严格约束结构解析时用 JSON Schema 校验# generate_tasks.py import json import random from openai import OpenAI client OpenAI() # 这里按你的 key 环境变量配置 def build_synthesizer_prompt(tools: list) - str: return f 你是智能体评测用例生成器。根据下面的 MCP 工具定义生成 5 个评测任务。 要求 1. 所有任务必须基于给定的工具能力不得臆造不存在的工具。 2. 任务描述要自然、有多样性关键参数要具体。 3. 断言中必须包含 expected.final_result 和 expected.tool_calls。 4. 输出必须是 JSON 数组不要输出其他文本。 工具定义 {json.dumps(tools, ensure_asciiFalse, indent2)} def parse_tasks_llm(raw: str): text raw.strip() if text.startswith(): text text.strip() if text.startswith(json): text text[4:] return json.loads(text) def synthesize(tools, num5): resp client.chat.completions.create( modelgpt-4o-mini, # 按你实际可用的模型调整 messages[{role: user, content: build_synthesizer_prompt(tools)}], temperature0.7, ) return parse_tasks_llm(resp.choices[0].message.content)生成结果如果不符合 JSON 结构直接丢弃走重试不要硬解析。这一步在工程上叫“结构容错”必须写。5.4 第三步规则筛选LLM 生成的用例还要过一层规则。常见的检查项包括任务描述中提到的工具名是否在tools中expected.tool_calls的 key 是否真的存在对应工具断言中的参数名是否存在于inputSchema.properties必填参数是否出现在任务描述或隐含上下文中这条过滤逻辑的价值在于它能防止一条“看起来不错但根本无法执行”的用例混进评测集避免后续回归全部失败时无法定位是模型问题还是用例问题。5.5 第四步执行器与断言执行器负责把任务输入给 Agent并记录工具调用轨迹。这里用一个最小桩实现# run_evaluation.py import json def call_agent(task_desc: str, tools: list) - dict: 这里接入你的 Agent 或智能体平台 API。 返回值建议规范化 { final_output: 自然语言输出, tool_calls: [ {name: query_weather, arguments: {city: 北京, date: 2025-06-10}} ] } # 演示用直接调用大模型做工具选择 from openai import OpenAI client OpenAI() tool_descriptions [ {type: function, function: { name: t[name], description: t[description], parameters: t[inputSchema] }} for t in tools ] resp client.chat.completions.create( modelgpt-4o-mini, messages[{role: user, content: task_desc}], toolstool_descriptions, tool_choiceauto, ) msg resp.choices[0].message calls [] if msg.tool_calls: for tc in msg.tool_calls: calls.append({ name: tc.function.name, arguments: json.loads(tc.function.arguments) }) return {final_output: msg.content or , tool_calls: calls} def check_assertion(run_result, expected): checks {final_result: False, tool_calls: False} # 检查最终输出 if message_contains in expected.get(final_result, {}): text run_result.get(final_output, ) checks[final_result] all( kw in text for kw in expected[final_result][message_contains] ) # 检查工具调用 call_names [c[name] for c in run_result.get(tool_calls, [])] expected_calls expected.get(tool_calls, {}) checks[tool_calls] all( call_names.count(name) 1 for name in expected_calls.keys() ) return all(checks.values())断言的输出建议做成 JSON 报告方便后续统计和可视化{ task_id: eval_calendar_0001, passed: true, duration_ms: 3200, tool_calls_actual: [query_weather], failed_checks: [] }5.6 运行整个评测执行时写一个循环即可python run_evaluation.py --tools mcp_tools.json --cases generated_cases.json命中失败时优先看两个地方第一Agent 是否真的发起了工具调用第二工具调用的参数是否与 Schema 不一致。这两个问题能覆盖大部分失败场景。6. 如何验证评测集的质量反向检验与冲突检测自动生成用例最大的隐忧是“看似丰富实则无效”。所以评测集本身也要被评测。这一节给出一套可落地的质量检验方法。6.1 正向检验覆盖率用两个数字衡量工具覆盖率生成的用例里至少出现一次的工具数 / 工具总数。目标通常是 90% 以上。参数覆盖率每个工具的必填参数中被评测用例覆盖到的比例。参数覆盖率比工具覆盖率更难达标也更接近真实业务。计算工具覆盖率的方式很简单扫描所有用例的expected.tool_calls键与工具清单做并集比较即可。6.2 反向检验随机基线最有效的一招是构造一个“什么工具都不调用的基线 Agent”让它去回答评测任务。如果这个基线也能通过大部分用例说明用例本身设计有问题要么预期结果藏在任务描述里要么断言太宽松。这个基线不需要多复杂直接用一个大模型 API不给任何工具定义只给任务描述输出自然语言然后跑同样的断言器。通过率最好趋近于 0。如果超过 20%评测集就该回炉重造了。6.3 冲突检测合成器在生成用例时可能产出语义冲突的任务。比如一个用例要求“查询北京 2025-06-10 天气”另一个用例却隐含着“拒绝查询工作日之外的天气”两个用例在同一套工具下会得出矛盾行为。这类冲突很难自动完全消除比较务实的做法是把生成的用例集提交到人工审核队列但只抽查 10% 而不是 100% 全审动态抽样的逻辑可以简单按“随机 覆盖最少参数”来选。6.4 防止目标泄漏目标泄漏是指任务描述里把答案直接给出来了。比如“请把会议标题设置为‘Agent 评测复盘’”而预期结果又恰好断言“输出包含‘Agent 评测复盘’”。这不能完全避免但可以加一条规则任务描述和断言中的关键词如果重复度超过阈值就自动替换参数或重写任务。7. 常见问题与排查思路在工程实践里自动合成评测用例会遇到一系列具体问题。下面按“问题现象 — 可能原因 — 排查方式 — 解决方案”列成表格问题现象可能原因排查方式解决方案生成的任务 JSON 频繁解析失败LLM 输出被 Markdown 包裹或夹杂说明文字打印原始输出查看开头符号增加解析容错剥离代码块标记、提取首个[到末个]工具覆盖率长期低于 60%合成提示词里工具列表太长模型被高热度工具吸引统计生成任务中的工具分布按工具分组分批生成每组随机挑选工具子集最后合并用例在回归时大面积失败工具定义有改动旧用例使用了已废弃的参数对比评测集版本与 MCP 规格版本把评测集版本与 MCP Server 版本绑定工具变更时自动触发重新合成Agent 调用工具成功但结果错误参数类型合法但语义错误如“明天”解析成错误日期检查参数快照对比输入日期与任务日期在代理执行时记录每个工具调用的参数 JSON断言时按语义字段校验而不仅是格式随机基线通过率过高断言只看最终输出关键词且关键词泄露在任务描述中运行随机基线统计通过率增加工具调用断言收紧最终结果关键词约束生成任务多但重复度高随机种子固定、或者变量槽采样范围太窄检查合成器的随机性来源每次合成前随机重置种子并增强日期、城市、人名等变量池超时导致误判多工具链接场景下真实耗时长Agent 还没返回就被判失败看耗时分布和失败率交叉对比区分“超时失败”和“执行失败”两种结果超时单独标记这些问题的共性是评测体系运行一段时间后就会出现“虚假通过”和“虚假失败”。虚假通过会让发布的 Agent 带病上线虚假失败会让团队天天追着模型优化却原来是用例本身写错了。所以质量检验环节绝不是可选项。8. Agent 评测落地的最佳实践最后这部分是给真正打算在团队里落地这套方法的工程负责人的建议。8.1 评测环境必须隔离用 MCP 规范生成评测用例时千万不要直接连生产 MCP Server。评测过程的工具调用会产生真实副作用发邮件、建日程、删数据。必须在沙箱环境里启动 MCP 测试实例用模拟数据源。特别是涉及删除、写入、支付类工具时测评环境要预置测试数据并且执行后可以一键重置。8.2 分层设计评测集评测规模一大全部跑的耗时和成本会迅速上升。建议按三层结构管理冒烟层固定 20 条核心主链路用例每次改动都跑确保 Agent 基本可用。关键层覆盖核心工具和跨工具组合每日或每次发版前跑。回归层全量自动生成的用例集可以每周批量执行或者按工具变更范围定向执行。8.3 评测集版本与 MCP 规格版本绑定这条最容易被忽视。工具定义变化一次旧评测集就可能失效一半。在仓库里用同一个 commit 管理 MCP 工具声明文件和评测集生成配置工具有变更时CI 自动触发“重新扫描 → 重新生成 → 重新审核抽查”流程而不是等人发现用例坏了再修。8.4 记录每一次工具调用的入参和出参Agent 评测一旦出现失败最大的痛点是没有现场。在设计评估框架时一定要把每次执行的完整轨迹落盘任务描述、模型输出、每个工具调用的参数、每个工具返回的结果、耗时、token 数。有了这些数据排查失败时才能区分问题出在模型选择、参数生成还是工具端异常。8.5 逐步扩大动态合成比例如果团队还没有自动化基础不建议一步到位全量自动生成。更稳妥的路径是先用手工用例同时搭建 MCP 工具清单和生成管道把自动生成的用例先放在“旁路”只做统计不上线拦截等对比验证自动用例与手工用例的判定一致性超过 95% 之后再逐步提升自动生成用例的比例。8.6 成本控制全量评测最贵的是模型调用费。可以按“工具组合难度”动态抽层单工具用例全跑双工具组合按 50% 抽样三工具组合按 20% 抽样。测试完记录本轮通过率通过率高时降采样通过率低时放大采样让成本花在刀刃上。9. 总结与后续探索Agent Seer 最值得借鉴的是把“MCP 规范”当成评测用例的事实来源。工具定义本来就是系统能力的边界把这个边界用成评测生成的约束和输入比让评测工程师凭空设计场景更可持续、更贴近真实。它不是取代人工而是把人工从“反复写用例”中解放出来专注于审查高风险场景和分析失败轨迹。你可以先从一个小工具集开始把你最核心的两个 MCP 工具定义整理成 JSON写一个生成器加一层规则过滤再接上你的 Agent跑一个最小回归。这一步跑通后再逐步叠加跨工具组合、动态变量池、随机基线和 CI 集成。后续值得继续深入的方向有三个跨多个 MCP Server 的复杂场景自动组合、基于工具调用日志的失败用例自动补全、以及把生成式评测和在线错误监控打通。评测这件事做扎实了Agent 从 demo 到生产的最后一公里才能真正走通。