行业资讯

AI Agent评估实战:从Evals到持续验证的可靠工程

发布时间:2026/8/27 10:53:14
AI Agent评估实战:从Evals到持续验证的可靠工程 AI Agent 的可靠性问题本质上不是“写完提示词再人工检查一遍”而是如何对每一次多步决策做持续验证。这也是 “Do Not Trust, Continuously Verify” 这句工程原则真正要解决的问题。Agent 不再是单次问答它会规划、调用工具、读取结果、调整下一步动作最后才给出答案。任何一个环节出错最终结果都可能错而且这种错误经常是安静的、不报异常的、看起来完全正常的。把 Agent 交给用户的团队如果只是靠“抽查几个例子感觉还行”迟早会在工具调用错误、状态理解偏差或幻觉答案上付出代价。这篇文章会从 AI Agent 评估Evals的核心概念讲起然后搭建一个最小可运行的评估系统再讨论指标选择、常见排查路径以及如何把评估接进开发和发布流程。读完以后你可以用同样的思路为自己的 Agent 建立一套“不信任 持续验证”的质量基线而不是停留在“能不能跑通 Demo”这个层面。1. 为什么 AI Agent 需要“零信任 持续验证”1.1 Agent 与普通 LLM 应用在验证上有什么本质差异普通 LLM 应用通常是一个“问题进来答案出去”的映射关系。你可以把输入、输出放到一起人工判断这一条回答是否正确或者用一组离线问题集计算准确率。这个模式虽然也有幻觉和格式不稳定但验证边界相对清楚。AI Agent 不一样。Agent 的核心不是模型输出而是“决策链”。它需要决定调用哪个工具、传入什么参数、如何解释工具返回的结果、是否已经完成目标、要不要换一种策略。整个过程是循环的模型产出意图系统执行动作环境或工具返回状态模型再基于新状态继续决策。这个循环里任何一个节点出错都会被后续步骤放大。举例来说一个客服 Agent 在处理“用户申请退款”时正确顺序是先查订单是否存在再判断订单是否符合退款条件然后调用退款接口最后返回结果。如果 Agent 跳过了查询直接调用退款接口即使最终返回的文案看起来正常也是严重错误。这种错误在单次对话的人工抽查里很难被发现因为你只看到了最终回复看不到它内部到底是按什么路径走到这一步的。这就是 AI Agent 评估的第一个关键转向你不能只评估“回答得对不对”还要评估“过程对不对”。1.2 传统软件测试经验为什么不能直接套用传统软件测试依赖确定性。同一个输入同一个函数在相同环境下应该产生相同输出。你可以写单元测试、集成测试用断言精确判断结果。Agent 没有这种确定性。即使固定同一个 Prompt、同一个模型版本多次运行也可能产生不同的工具调用顺序甚至完全不同的最终答案。模型版本、温度参数、工具返回内容、上下文长度、随机种子都可能影响 Agent 的轨迹。这意味着评估结果不能只跑一次必须多次采样统计通过率而不是用单次结果断言“这个 Agent 是好的”。下面的表格可以更清楚地看出差异对比维度传统软件普通 LLM 应用AI Agent输出确定性确定概率性概率性且路径复杂验证对象函数返回值和状态变化单次回答内容工具调用过程、中间状态、最终答案断言方式单元测试断言人工或模型评估规则评估 过程还原 模型评估错误传播局部异常较易定位错误集中在回答错误可能被后续步骤放大回归成本较低中等高需要多次采样和成本预算所以AI Agent 的质量保障不能只靠“测试”更准确地说要靠“评估”用一批有代表性的任务用例让 Agent 反复执行用规则、模型、人工结合的方式判断过程中的行为和最终输出的好坏。1.3 “Do Not Trust, Continuously Verify” 在工程上意味着什么这句原则的第一层含义是不要默认 Agent 是可信的。用户、工具、上游系统都不应该因为“Agent 看起来懂了”就信任它。你需要在代码层面假设它可能出错比如参数传错、工具选错、提前给出结论、无视工具结果继续胡说。第二层含义是验证不是发布前做一次就够而是持续进行。Agent 的依赖方很多任何一个变化都会引入新的行为漂移。这部分在工程上可以拆成三个阶段离线评估在发布之前用固定评估集跑一遍 Agent计算通过率、工具调用错误率、最终答案正确率。集成回归在 CI 或发布流水线里跑核心用例防止代码改动或 Prompt 调整让旧功能回归。在线监控生产环境记录 Agent 的实际轨迹通过用户反馈、结果标注、规则告警把新问题回流到评估集。这套体系不是一次建完的而是先有小规模的用例集再逐步覆盖更多真实场景。接下来的章节会先解决一个最小问题如何搭建一套能跑的 Agent 评估系统。2. 评估 AI Agent 前先对齐 5 个核心概念2.1 Agentic Eval评估对象不是一次回答而是完整任务过程“Agentic Eval” 是 AI Agent 评估的统称。和传统 LLM 评估不同它把评估对象从“最终文本”扩展到“一次任务执行的完整过程”。一个任务可以表示成给定一个目标Agent 从初始状态出发经过多轮工具调用最终达到某个终止状态。推荐的做法是把一个评估样本定义成结构化的 Eval Case包含以下几个字段task给 Agent 的任务描述。expected_tools完成这个任务预期会调用到的工具。forbidden_tools这个任务不应该调用的工具比如“用户只查询时禁止调用退款接口”。expected_keywords最终答案中必须出现的信息。tags场景标签比如“天气查询”“退款”“多城市对比”。这些字段服务于两类检查最终结果是否正确执行路径是否合理。2.2 TrajectoryAgent 是怎么走到最终答案的Trajectory也就是轨迹是 Agent 在完成任务过程中留下的每一步记录。一条完整轨迹通常包含模型请求、工具调用参数、工具返回结果、中间思考或状态、最终答案。为什么要关注轨迹因为最终答案正确不代表过程正确。一个 Agent 可能先执行了危险操作再修正回来也可能调用了 5 次工具但最优路径只需要 2 次甚至可能忽略工具返回的错误用幻觉数据拼出一个看似合理的答案。在评估系统里轨迹是核心数据。它决定了你能不能复现问题、能不能知道错误发生在哪一步、能不能判断 Agent 是否遵循了安全规则。因此Agent Runner 必须记录结构化事件而不是只返回最终字符串。2.3 Tool Call工具调用是否被正确选择和执行工具调用是 Agent 与外部世界交互的通道。它包含三部分工具名、参数、返回值。评估工具调用时要关注的不只是“最终调用了哪些工具”还要关注是否调用了正确工具参数是否符合预期调用顺序是否合理是否在工具返回错误后正确处理是否调用了被禁止的工具。在实际评估中工具调用顺序很重要。比如“先查天气再计算温差”和“先计算后查天气”可能结果相同但有些场景顺序就是硬约束。“先查订单再退款”绝对不能反。所以评估用例里最好同时记录“必须出现的工具”和“必须遵守的顺序”。2.4 LLM-as-Judge用模型评估模型什么时候可靠LLM-as-Judge 是指用一个大模型作为评估器去判断另一个 Agent 的输出是否合格。它的优点是能处理开放式任务不像规则那样死板。但它的可靠性取决于三件事评估 Prompt 是否清晰、评估模型能力是否足够、被评估任务的答案是否有一个可判断的标准。使用 LLM-as-Judge 时建议让它输出结构化结果比如{ verdict: PASS, score: 90, reason: Agent 查询了北京 2025-01-01 和 2025-01-02 两天的天气并正确计算温差 7 摄氏度。 }结构化输出便于后续汇总和排查也能减少模型“说了很多但结论模糊”的问题。注意LLM-as-Judge 并不是万能标准。对于有硬性规则的任务例如必须调用某个工具规则评估更可靠对于开放式写作或语义相似度判断LLM-as-Judge 更合适。2.5 Pass/Fail 与评分粒度评估结果不一定只有“通过/不通过”两档。为了定位问题建议至少有三个层级结果是否成功Agent 是否在最大步数内给出了最终答案。答案是否合格最终答案是否包含关键信息是否有幻觉是否符合用户意图。过程是否合规是否严格按照预期工具顺序执行是否出现多余调用是否安全。你可以把一次评估最终输出成四个状态PASS、FAIL_INVALID、FAIL_OUTPUT、FAIL_PROCESS。这种粒度能帮助团队快速判断是模型理解出了问题还是工具链路出了问题还是最终回答质量出了问题。3. 搭建一个最小可运行的 Agent 评估系统3.1 环境准备先让演示代码跑起来再接真实模型这一节会用 Python 写一个最小系统。它不依赖外部大模型也能运行因为我会提供一个 mock 生成器用于演示评估流程。这样你不需要配置 API Key也不需要担心网络问题就能理解完整闭环。环境要求项目建议Python 版本3.9 及以上第三方库无强依赖接真实模型时安装 openai 或对应 SDK操作系统Windows / macOS / Linux 均可如果你要接真实模型需要准备模型服务的 API Key并确认 SDK 版本。需要注意不同版本的 SDK 在方法名和返回值结构上可能有差异落地时要以你使用的 SDK 文档为准。3.2 先写一个可观测的 Agent RunnerAgent Runner 的职责是执行任务并记录轨迹。它的输入是任务描述、工具表和 LLM 调用函数输出是包含事件列表和最终答案的结构体。# agent_runner.py from dataclasses import dataclass, field from enum import Enum from typing import Any, Callable, Dict, List, Optional class EventType(str, Enum): TOOL_CALL tool_call TOOL_RESULT tool_result FINAL_ANSWER final_answer dataclass class Event: type: EventType content: Any metadata: Dict[str, Any] field(default_factorydict) dataclass class AgentResult: events: List[Event] final_answer: str steps: int usage: Dict[str, Any] field(default_factorydict) def run_agent( task: str, tools: Dict[str, Callable], llm: Callable, max_steps: int 5, ) - AgentResult: task: 用户任务 tools: 工具名到工具函数的映射 llm: 根据对话消息返回动作的函数 messages [{role: user, content: task}] events: List[Event] [] for step in range(1, max_steps 1): response llm(messages) event_type response.get(type) if event_type final_answer: content response.get(content, ) events.append(Event(EventType.FINAL_ANSWER, content)) return AgentResult(eventsevents, final_answercontent, stepsstep) if event_type tool_call: tool_name response.get(tool) args response.get(args, {}) events.append( Event( EventType.TOOL_CALL, {tool: tool_name, args: args}, ) ) tool_func tools.get(tool_name) if tool_func is None: result f工具不存在: {tool_name} else: try: result tool_func(**args) except Exception as exc: result f工具执行异常: {exc} events.append(Event(EventType.TOOL_RESULT, result)) messages.append( { role: tool, name: tool_name, content: result, } ) continue # 未知响应类型按异常处理便于在评估中发现协议错误 events.append(Event(EventType.FINAL_ANSWER, 模型返回了无法识别的动作)) return AgentResult(eventsevents, final_answer模型返回了无法识别的动作, stepsstep) events.append(Event(EventType.FINAL_ANSWER, 达到最大步数仍未产出最终答案)) return AgentResult(eventsevents, final_answer达到最大步数仍未产出最终答案, stepsmax_steps)这里的核心设计是“可观测”。不要只在内部调工具而是把每一次模型返回、工具调用、工具结果、最终答案全部记录成事件。后续评估器就是基于这些事件工作。3.3 定义两个演示工具和一个 mock LLM为了演示多步决策我们准备两个工具查天气和计算温差。工具本身是模拟的但接口结构和真实工具一致。# tools.py import ast import operator def get_weather(city: str, date: str) - str: weather_data { (北京, 2025-01-01): {temperature: 5}, (北京, 2025-01-02): {temperature: -2}, (上海, 2025-01-02): {temperature: 8}, } data weather_data.get((city, date)) if not data: return f未查询到 {city} 在 {date} 的天气数据 return f{city}在{date}的温度是{data[temperature]}摄氏度 def calculate(expression: str) - str: # 只允许安全的四则运算实际项目里不建议直接执行任意表达式 allowed_ops { ast.Add: operator.add, ast.Sub: operator.sub, ast.Mult: operator.mul, ast.Div: operator.truediv, ast.USub: operator.neg, } def eval_node(node): if isinstance(node, ast.Expression): return eval_node(node.body) if isinstance(node, ast.Constant) and isinstance(node.value, (int, float)): return node.value if isinstance(node, ast.BinOp): left eval_node(node.left) right eval_node(node.right) op allowed_ops.get(type(node.op)) if op is None: raise ValueError(不支持的运算符) return op(left, right) if isinstance(node, ast.UnaryOp) and isinstance(node.op, ast.USub): return -eval_node(node.operand) raise ValueError(不支持的表达式) try: tree ast.parse(expression, modeeval) result eval_node(tree.body) return str(result) except Exception as exc: return f计算失败: {exc} TOOLS { get_weather: get_weather, calculate: calculate, }mock LLM 的职责是模拟“根据对话历史决定下一步动作”。它的规则很简单先查 2025-01-01 的天气再查 2025-01-02 的天气然后计算温差最后提交答案。# mock_llm.py def mock_llm(messages): text str(messages) if tool_result not in text: return { type: tool_call, tool: get_weather, args: {city: 北京, date: 2025-01-01}, } if text.count(temperature) 2: return { type: tool_call, tool: get_weather, args: {city: 北京, date: 2025-01-02}, } if calculate not in text: return { type: tool_call, tool: calculate, args: {expression: 5 - (-2)}, } return { type: final_answer, content: 北京2025年1月2日与2025年1月1日相比温差为7摄氏度。, }这个 mock 的价值在于让评估流程在无网络环境下稳定跑通。真实项目里你需要把mock_llm换成真实模型接入函数但 Runner、事件结构、评估器都可以复用。3.4 定义评估用例集和规则评估器评估用例集是整个体系的基石。一个用例至少要包含任务描述、预期工具调用、最终答案关键词、禁止工具。# eval_cases.py from dataclasses import dataclass, field from typing import List dataclass class EvalCase: case_id: str task: str expected_tools: List[str] expected_keywords: List[str] forbidden_tools: List[str] field(default_factorylist) tags: List[str] field(default_factorylist) EVAL_CASES [ EvalCase( case_idweather-001, task查询北京2025-01-01和2025-01-02两天的天气并计算温差。, expected_tools[get_weather, get_weather, calculate], expected_keywords[7摄氏度, 温差], forbidden_tools[], tags[天气, 计算], ), EvalCase( case_idweather-002, task只查询北京2025-01-02的天气不要做计算。, expected_tools[get_weather], expected_keywords[-2摄氏度], forbidden_tools[calculate], tags[天气, 禁止动作], ), ]注意expected_tools里的顺序在严格评估中很重要。上面的用例要求先查两次天气再计算。下面的规则评估器先检查“必须出现的工具”再检查顺序再检查关键词。# evaluator.py from typing import Dict, List def _tool_call_sequence(result) - List[str]: return [ event.content[tool] for event in result.events if event.type.value tool_call ] def rule_evaluate(case, result): detail {} tool_seq _tool_call_sequence(result) missing_tools [t for t in case.expected_tools if t not in tool_seq] forbidden_used [t for t in case.forbidden_tools if t in tool_seq] # 检查顺序预期工具列表必须是实际调用序列的子序列 seq_pass True idx 0 for tool in tool_seq: if idx len(case.expected_tools) and tool case.expected_tools[idx]: idx 1 if idx ! len(case.expected_tools): seq_pass False missing_keywords [ kw for kw in case.expected_keywords if kw not in result.final_answer ] pass_ ( not missing_tools and not forbidden_used and seq_pass and not missing_keywords ) detail[tool_seq] tool_seq detail[missing_tools] missing_tools detail[forbidden_used] forbidden_used detail[seq_pass] seq_pass detail[missing_keywords] missing_keywords return pass_, detail这里有一个细节如果用例要求工具按顺序出现规则评估器需要做“子序列匹配”而不是简单判断集合包含关系。否则[calculate, get_weather, get_weather]也会被误判为通过。3.5 实现 LLM 评估器并输出综合报告规则评估能覆盖硬性约束但最终答案是否自然、是否满足用户真实意图仍需要模型判断。下面实现一个 LLM-as-Judge 的骨架。演示时用mock_judge代替真实模型生产环境换成模型调用。# judge.py def format_trajectory(result) - str: lines [] for event in result.events: if event.type.value tool_call: content event.content lines.append(fCALL {content[tool]}({content[args]})) elif event.type.value tool_result: lines.append(fRESULT {event.content}) else: lines.append(fFINAL {event.content}) return \n.join(lines) def mock_judge(case, result): final_answer result.final_answer if 7摄氏度 in final_answer and 温差 in final_answer: return {verdict: PASS, score: 90, reason: 答案包含温差信息} return {verdict: FAIL, score: 30, reason: 答案缺少温差关键词} def llm_judge(case, result, judge_fn): trajectory format_trajectory(result) prompt f 任务{case.task} 最终答案{result.final_answer} 执行轨迹 {trajectory} 请判断 Agent 是否完成了任务。要求 1. 只能输出 JSON。 2. verdict 字段只能是 PASS 或 FAIL。 3. score 是 0 到 100 的整数。 4. reason 要说明关键判断依据。 return judge_fn(case, result, prompt)真实的llm_judge会把 prompt 发给模型并解析 JSON。上面的mock_judge主要用于跑通流程。如果你需要同时看“规则评估”和“模型评估”的结果可以在报告里分别展示避免用一个单一结论掩盖问题。# run_eval.py from eval_cases import EVAL_CASES from evaluator import rule_evaluate from judge import mock_judge, llm_judge from tools import TOOLS from agent_runner import run_agent from mock_llm import mock_llm def run_eval(): print(f{case_id:16}{pass:8}{rule:8}{judge:8}) for case in EVAL_CASES: result run_agent( taskcase.task, toolsTOOLS, llmmock_llm, max_steps5, ) rule_pass, rule_detail rule_evaluate(case, result) judge_result llm_judge(case, result, mock_judge) print( f{case.case_id:16} f{str(rule_pass and judge_result[verdict] PASS):8} f{str(rule_pass):8} f{judge_result[verdict]:8} ) print(f 轨迹: {rule_detail[tool_seq]}) print(f 最终答案: {result.final_answer}) print() if __name__ __main__: run_eval()运行python run_eval.py你会看到类似下面的报告case_id pass rule judge weather-001 True True PASS 轨迹: [get_weather, get_weather, calculate] 最终答案: 北京2025年1月2日与2025年1月1日相比温差为7摄氏度。 weather-002 True True PASS 轨迹: [get_weather] 最终答案: 北京2025年1月2日的温度是-2摄氏度到这里最小评估系统就形成了闭环Agent 执行任务、记录轨迹、规则评估、模型评估、输出报告。下一步要解决的是这些结果到底该怎么解读以及怎样避免指标自我欺骗。4. 评估指标怎么选才不容易自我欺骗4.1 最终答案指标只看准确率会漏掉很多问题最终答案指标最容易理解也最容易让人产生“已经够了”的错觉。常见的有答案正确率假设有固定参考答案判断 Agent 最终回答是否命中。关键词命中率检查答案中是否出现必须包含的信息比如城市、日期、数值。LLM 打分用模型对答案质量打分适合开放式任务。幻觉率最终答案中出现了工具返回结果里不存在的信息属于严重问题。这些指标必须搭配过程指标使用。否则会出现一种典型情况答案字符串命中但 Agent 根本没有调用任何工具只是倒背了标准答案。这在真实业务中非常危险。4.2 过程指标工具调用是否合理、是否安全过程指标重点回答下面这些问题必需工具调用完整率expected_tools中有多少工具被实际调用。禁止工具触发次数比如只允许查询时是否错误触发了写操作。调用顺序正确率实际调用序列是否匹配预期子序列。工具出错率工具抛出异常或返回错误状态的比例。多余调用率与完成任务无关的工具调用次数。过程指标的优势在于可以定位到具体失败点。如果 Agent 最终答案正确但过程违规你应该把这条用例标记为FAIL_PROCESS而不是PASS。尤其是涉及支付、退款、删除、修改配置等高风险操作时过程正确比答案华丽重要得多。4.3 成本与延迟指标一个“全对”但贵到没法用的 Agent 也不合格Agent 每多一次工具调用就会多一次模型请求成本和延迟都会上升。评估时建议记录平均步数Agent 完成一个任务平均需要几轮决策。总 Token 消耗输入 Token 和输出 Token 分别统计。平均延迟从任务开始到最终答案返回的耗时。重试次数工具失败后模型是否反复尝试同样错误的参数。这些指标不应该单独决定通过率但可以用于容量评估和优化。比如某条用例通过率不低但平均步数从 3 增加到 6就应该检查是不是工具描述不够清晰或者模型在同一个错误上反复打转。4.4 指标速查表指标类型指标名称计算方式适用场景注意点最终答案正确率命中参考答案的用例数 / 总用例数有明确标准答案的任务答案可能等价但文字不同最终答案关键词命中率包含全部关键词的用例数 / 总用例数信息抽取型任务关键词过于宽松会虚高最终答案LLM 打分评估模型输出的 0-100 分数开放式任务评估 Prompt 需固定过程工具调用完整率调用过的必需工具数 / 预期工具总数多步骤任务只算集合不算顺序会漏判过程禁止工具触发次数统计非法调用次数高风险操作场景应设置零容忍成本平均步数总步数 / 用例数性能优化步数不是越少越好成本Total Token所有请求 Token 之和成本评估不同模型计费不同选指标的原则是先用少量高价值指标建立基线再逐步增加。不要在一开始就追求十几个指标否则团队会不知道优化哪个。5. 常见问题与排查路径5.1 LLM-as-Judge 评分不稳定现象是同一条用例跑三次评估模型一次给 90 分一次给 60 分一次给 80 分。常见原因有三个评估 Prompt 没有给出明确的评分标准评估模型能力不足评估结果没有做多采样聚合。排查路径固定评估模型的温度参数必要时设为 0。在评估 Prompt 中给出 PASS/FAIL 的明确标准并附上正反例。同一用例跑 3 到 5 次计算通过率或平均分而不是用单次结果定论。对争议样本抽样人工标注确认是 Agent 问题还是 Judge 问题。如果 Judge 持续不稳定建议对高风险用例使用规则评估加人工抽检不要完全依赖模型评估。5.2 评估集太少或分布偏了只有 10 条用例时Agent 很容易“过拟合”到评估集上只要针对这 10 条调整 Prompt 就能刷高通过率但线上真实任务完全跑不通。处理方式是把评估集分成两类训练集思维下的“开发集”和“测试集”。开发集用于日常调试测试集应该包含开发过程中从未见过的任务类型。测试集最好从真实用户日志、工单、对话记录中采样再脱敏清洗。随着线上新问题出现不断补充新用例同时控制用例增长的优先级先覆盖高频场景再覆盖高风险场景。5.3 黄金答案写得不到位规则评估依赖关键词但“正确答案”不只有一种表达。比如“温差为7摄氏度”和“温差是7度”语义等价但关键词完全不同。这种现象会导致 Agent 明明正确却被判失败。改进方式多写几个等价关键词例如[7摄氏度, 7度, 温差7]。对开放任务不要只靠关键词要用 LLM-as-Judge 做语义判断。把“人工确定标准答案”变成“人工标注一批历史正确样本”再让 Judge 学习或参考这些样本。5.4 工具调用时序导致评估误判有些评估代码只检查工具集合不检查顺序。结果是 Agent 先调用退款接口再调用查询接口也会被判 PASS。这是过程评估最大的坑。解决方式很简单对于顺序敏感任务在用例中增加expected_tool_order或在规则评估中做子序列匹配。上一节给出的rule_evaluate已经体现了这个思路。需要补充的是错误场景也要纳入评估比如用户只要求查询时Agent 调用了计算工具应该被判 FAIL。5.5 离线评估通过但线上失败离线评估用的是固定日期、固定历史消息、固定工具 mock。线上是真实时间、真实用户、真实数据。Agent 的任务描述稍微一变工具返回结构稍微调整行为就可能完全不同。建议把线上流量按一定比例接入“影子评估”把真实用户任务输入到 Agent但高风险动作不真正执行只记录轨迹然后离线评估结果。另外线上工具返回值变化后需要立刻用最近的真实样本跑一遍回归避免 Agent 基于旧字段格式解析数据。下面的表格汇总了这些问题的排查重点问题现象常见原因排查方式处理建议Judge 分数忽高忽低评估标准模糊、温度过高固定温度重复采样明确评分标准多采样聚合评估集通过率高但线上差评估集太小或分布偏分析线上真实任务分布从真实日志补充用例正确结果被判失败黄金答案关键词太窄检查失败样例扩大等价关键词引入 LLM 判断顺序错误被判通过只检查工具集合打印调用序列加入子序列匹配离线通过线上失败mock 与真实环境差异对比线上轨迹影子评估 真实样本回归6. 从评估到持续验证把 Evals 接入开发和发布流程6.1 离线评估集先于 Agent 改动存在很多团队是先开发 Agent再临时凑几个测试用例验证。这个顺序反了。推荐做法是在写第一版 Agent 之前先根据需求文档和真实用户日志整理出第一批评估用例。哪怕只有 20 条也比没有强。用例集建立后每次 Prompt 改动、工具逻辑改动、模型版本升级都要跑一遍完整评估。评估通过率不是唯一的发布标准还要看变化趋势。如果你的改动让 A 场景通过率提升但 B 场景明显下降就要在发布说明里写清楚而不是直接 Merge。6.2 在 CI 里跑 Agent 回归Agent 评估可以像单元测试一样放进 CI。关键是要控制两个成本评估用例数量和每次评估的 Token 消耗。一个常见的做法是分两层快速回归集每天或每次 PR 运行用例少、模型较小、mock 工具多用于发现明显断裂。完整评估集合并前或发布前运行用例覆盖全部高风险场景使用接近生产的模型和工具。下面是一个简化版 CI 命令示例python run_eval.py --cases eval_cases.json --max-steps 5 --samples 3如果是 GitHub Actions可以给每个 PR 跑快速回归集发布 Tag 时跑完整评估集。这样不会让“评估”变成发布前的一个可有可无的步骤而是像编译和单测一样自然。6.3 生产环境中的在线监控与反馈回流离线评估再完善也无法覆盖所有线上情况。生产环境需要做三件事第一记录真实轨迹。每个用户请求和 Agent 交互至少要保存任务描述、模型动作、工具调用、工具结果、最终答案。这是后续排查问题的原始证据。第二设置自动化告警。比如高风险工具被错误调用、工具返回错误但 Agent 仍然继续生成答案、用户明确表达不满但 Agent 没有转人工都应该触发告警。第三把线上问题回流到评估集。客服投诉、用户评分低、业务部门反馈的异常案例经过脱敏和标注后补进离线评估集。这个回流机制是整个“持续验证”的闭环关键。6.4 最小可行评估体系的迭代顺序如果你刚开始建设 Agent 评估体系不要想着一步到位。可以按下面的顺序迭代先记录轨迹让 Agent Runner 输出结构化事件这是所有评估的基础。建立 20 到 50 条核心用例覆盖最高频、最高风险的业务场景。跑通规则评估检查工具调用、禁止动作、关键词命中。加入 LLM-as-Judge对开放式答案做质量判断。多次采样并通过率统计把 Agent 的随机性纳入评估。接入 CI每次改动自动跑快速回归。接线上反馈用真实问题持续扩充评估集。如果你现在只做一步最值得做的是“记录轨迹”。因为只有知道 Agent 每一步做了什么你才有资格讨论它是否可信。AI Agent 的信任不是靠“模型大小”或“Demo 效果”获得的而是靠一套能持续发现问题的验证机制积累出来的。一个没有评估集的 Agent 项目规模越大风险越不可控。与其在线上出现事故后复盘不如从今天就开始为每个关键任务建立用例让“不信任 持续验证”成为你的默认工程姿态。