编码 Agent 质量飞轮:自动化评估五阶段流程
Google 为编码 Agent 提供自动化质量评估工具,包含数据准备、测试、评分等阶段。解决 Prompt 调整导致线上回归的问题。
Google 为编码 Agent 提供自动化质量评估工具,包含数据准备、测试、评分等阶段。解决 Prompt 调整导致线上回归的问题。
工程化提升 Agent 质量,而不是凭感觉检查
你已经发布了一个 Agent。它能正常工作。你调整了一处 prompt,修复某位用户反馈的问题,并在尝试的三个示例中看到了更好的效果。但有一个问题让你夜不能寐:我是不是因此破坏了另外十个场景?
从“在少数示例中看起来更好”到“在生产环境中确实表现更好”,这道鸿沟正是构建 Agent 的日常现实。大多数团队都在某个地方保存了一些 eval 用例,也都会调整 prompt。但很少有团队能以足够严谨的方式把两者连接起来,从而确定一次修改究竟真正改善了指标,还是仅仅改善了感觉。
最可怕的故障并不是那些声势浩大的问题,而是那些看上去仍在正常工作的 Agent——回答充满自信,计划读起来也没问题——实际上却在悄无声息地误解用户真正的目标。在 Cloud Next '26 上,我们将 Agent 质量描述为一个由三个阶段组成的飞轮:Build & Test → Ship & Monitor → Learn & Refine,并展示了其中的基础构件。今天,我们进一步补上面向开发者的实践路径:一个安装到 coding agent 中,并由它代你驱动的 skill。
这个飞轮,包括其方法论和作为核心的 AutoRaters,建立在我们评估和改进自有模型及第一方 Agent 时所采用的相同原则之上。其中,AutoRaters 由我们与 Google DeepMind 密切合作开发。
这个 skill 以 Build & Test 这一快速迭代循环为中心,并将其展开为五个具体阶段。它并不局限于这个阶段:同样的流程也可以针对生产环境的 traces 运行,而且随着时间推移,飞轮中会有越来越多的部分纳入其中。第一次运行时,请依次完成这些阶段;之后循环执行第 2~5 阶段,直到达到质量目标:
Prepare Data:根据现有的 OTel traces、手工编写的用例或合成场景构建评估数据集。
Run Inference:让 Agent 在数据集上执行并生成 traces;如果你已经有 traces,可以跳过这一步。
Grade:使用 Google 的自适应 AutoRaters——能够对 trace 评分并解释原因的模型评审器——或你自己的自定义指标,对 traces 进行评分。这是唯一一个每次都必须执行的阶段。
Analyze Failures:阅读 rubric verdicts,理解用例失败的原因;如果失败用例达到十个或更多,则使用 Automatic Loss Analysis 对其进行聚类。
Optimize & Iterate:应用有针对性的修复,重新执行第 2~4 阶段,并与之前的 baseline 比较。
大多数失败用例都需要经历多轮迭代,指标才会真正发生变化,而这个 skill 将这种严谨性编码进了工作流程。
优化器与评估器始终保持解耦:无论是谁提出修复方案——你的 coding agent、自动化优化器,还是你本人——都不能为这次修复评分。Gemini Enterprise Agent Platform GenAI evaluation service 会独立完成评分。如果让优化器自我评分,它最终学会的会是如何操纵指标,而不是如何真正改进 Agent。这个看似微小的架构选择,实际影响远比表面上更重要。
它是一套运行在 coding agent 内部的方法论与编排机制:它会针对目标选择合适的指标,运行 GenAI evaluation service,读取 verdicts,提出修复方案,并比较修改前后的结果。
自主运行。它负责提出方案,由你批准。它采用 human-in-the-loop 模式,而不是完全放手不管。
一种 ground truth 来源。内置的 AutoRaters 并不只是用模型给答案打分。面对一个多轮对话 Agent,它们会从对话中提取用户意图,为具体用例生成专属 rubrics,根据每一项标准验证 trace,并对多次采样结果进行多数投票。这套机制很复杂,但本质上仍然基于模型:应当把评分视为很强的方向性信号;相比将某个孤立数字当作绝对成绩,更应该相信多次运行之间的变化量。
真实流量的替代品。这个 skill 可以使用 User Simulator——GenAI evaluation service 的一项功能——生成合成场景,但它只适合用来完成冷启动。合成场景能帮助你启动流程,真正让这个循环变得敏锐的则是生产数据。
它针对同一个 GenAI evaluation service 提供了两个软件包。请选择最适合你技术栈的版本:
google-agents-cli-eval——如果你使用 agents-cli 工具链构建 ADK agents,请安装 skills.sh/google/agents-cli/google-agents-cli-eval。
agent-platform-eval-flywheel——如果你直接使用 Evaluation SDK,适用于任何框架,请安装 skills.sh/google/skills/agent-platform-eval-flywheel。
下面是一个真实 Agent 上的完整循环。阅读时请特别留意:开发者从未直接操作 eval CLI,也从未指定任何指标。他们只是安装 skill,用自然语言描述自己的担忧,批准方案,然后阅读结果。至于具体应该如何完成,则由 skill 决定。而它做出的最有意思的决定,是选择一个真正能够检测出该问题的指标。
被测试的 Agent 是 travel-concierge,它是 google/adk-samples 中一个基于 ADK 的多 Agent 旅行规划器,覆盖灵感探索 → 行程规划 → 预订 → 旅行前、旅行中和旅行后的完整流程。它把正在编辑的行程保存在 session state 中,这恰好为一种具体而隐蔽的故障创造了条件。
你对 coding agent 说:
这就是完整的交互界面。没有 flags,也没有指标名称。这个 skill 的职责是把目标转化为正确的评估方式,而这正是它体现价值的地方。它首先阅读 Agent 的代码,然后带着方案回来。它选择了两个内置的多轮对话 AutoRaters,接着又做了一件固定脚本做不到的事:在这两个指标之上添加一条自定义 rubric,专门用于把修改前后的结果精确锚定到你所关注的行为上:
coding agent · quality-flywheel skill
你批准了方案。在这段描述背后,skill 使用 User Simulator 合成这些场景,然后通过两个内置指标以及自定义的 revision_honored rubric 对 traces 进行评分。只有少量用例失败,尚未达到值得进行聚类的阈值,因此它直接阅读这些 verdicts,而没有调用 Automatic Loss Analysis。下面是它实际执行的命令:
# one User Simulator pass per revision type (×5: party_size, destination, dates, hotel, dropped_stop)
agents-cli eval dataset synthesize -n 5 --max-turns 8 --model gemini-3.5-flash \
--instruction "$(cat instr_party_size.txt)" \
--environment-context "$(cat synthesize_env_context.txt)" \
-o traces_party_size.json
# merge the five trace files, then grade all 25 in one pass
agents-cli eval grade --traces traces_merged.json --config eval_config_revisions.yaml
这些命令都不是你写的。你只描述了目标,具体的指标、模拟器和数据分区方式都由 skill 选择。
第一次运行时,三个指标全都检测到了问题。内置 AutoRaters 已经清楚表明整体质量低于理想水平——均值位于 0.6 左右的中段,在严格阈值下的通过率也很低——而自定义 rubric 则进一步单独量化了其中有多少问题是由“未遵循用户修改”导致的:
在这套 rubric 中,IGNORED 表示用户的修改被丢弃,其他 verdicts 分别为 HONORED、PARTIAL 和 NO_REVISION。21% 的比例超过了 skill 自己设定的行动阈值。verdicts 还精确定位了故障所在。问题并不是你可能猜测的那样:Agent 并没有信心满满地确认一份错误行程。在四个失败用例中的三个里,它的内部状态其实是正确的——保存了正确的值,也调用了正确的工具——但在最终发送给用户的消息中,它却仍然复述了过期的值。Agent 在内部做对了,却在对外表达时自相矛盾。下面一条 verdict 具体说明了这个问题:
这就是“看起来正在正常工作”的微型失败案例:没有任何东西崩溃,快速浏览时计划也没有明显问题,Agent 听起来似乎完成了你的要求,但用户真正收到的答案却是错误的。这些用例背后有一个共同原因:root agent 的 instruction 中,没有要求它在发送最终回复前,将回复内容与用户最近一次消息进行核对。
你可能会问,自定义 rubric 是否真的有必要,毕竟内置指标本身就是自适应的。事实证明,问题不在于能否检测,而在于能否将故障单独分离出来。以其中一个被判定为 IGNORED、但内置 task-success 仍给出 0.80 高分的用例为例:party_size_02。在这个用例中,用户把酒店要求修改为入住某家指定旅舍的多人宿舍。下面的 annotation 解释了原因:rater 确实针对这一具体要求生成了一条 criterion,并将其标记为未满足——它捕获了这个遗漏,也解释了原因——但这条失败标准与另外四条通过的标准混合在一起,因此综合分数仍然很高。内置指标无法提供的是一个能够覆盖全部 25 个用例、直接回答“它是否遵循了用户修改?”的单一数字。把这个关注点提升为独立的分类指标,才使 21%→5% 的前后变化变得可量化。
用户要求规划一趟从柏林到阿姆斯特丹、适合 5 人且价格便宜的旅行,随后又在对话中途将酒店要求修改为“入住 Hostel World Amsterdam 的多人宿舍”。
revision_honored(自定义)→ IGNORED。“Agent 确认收到了请求,但没有按照修改后的条件重新搜索,而是再次提供了之前的结果,并且从未记住这项新偏好。”
multi_turn_task_success(内置)→ 0.80。生成了五项标准,其中四项通过:✓ 适合 5 人的低价旅行 · ✓ 航班选项 · ✓ 已确认选择 easyJet · ✓ 提供了酒店选项。第五项未通过:✗ “提供 ‘Hostel World Amsterdam’ 的多人宿舍选项”:“Agent 未能提供所要求的具体信息……因为它声称工具不具备相应能力。”用户修改确实被遗漏,而且问题也被明确指出;但它只是五项标准中的一项,因此综合分数仍然很高。
multi_turn_trajectory_quality(内置)→ 0.67。这里未通过的项目是 eval 配置造成的假象,并不是 Agent 缺陷:Agent 的工具 schemas 没有提供给 rater,因此它把合法调用——flight_search_agent、_memorize_impl——标记为“tools not permitted”。这正是为什么在前后对比中,我们主要依赖自定义 rubric 和 task-success,而不是 trajectory。
修复并重新运行。你批准了一项针对性修改:在 root agent 的 instruction 中添加三个句子,要求它根据用户最新的修改核对最终回复。skill 随后重新运行同一套评估:
前面的循环从一个明确目标开始。但即使你还没有目标,甚至说不清究竟哪里出了问题,这个 skill 也同样有效。你可以直接把一个陌生 Agent 交给它,然后说:“找出一个真实故障并修复它。”它会进行宽泛评估:合成多样化的场景,使用内置多轮对话指标评分,并自行找出最主要的故障聚类。
我们在另一个 Agent 上做了完全相同的实验:software-bug-assistant。它来自 google/adk-samples,是一个连接了真实工具的 bug 分流助手,包括由 MCP toolbox 提供支持的 Postgres 工单数据库,以及 Web 和 StackExchange 搜索。在没有任何预设假设的情况下,skill 立刻发现了一个故障聚类:15 个用例中有 14 个,Agent 都正确完成了任务,却从未告诉用户自己调用了哪些工具。它自己的 instruction 明明要求这样做,但模型悄悄把这项要求视为可选项。只需增加一段修复内容,强制要求每次回复都以类似“Tools used: search-tickets, get-ticket-by-id”的 footer 结尾,就在单次循环中,让全部 15 个用例的回复合规率从 0% 提升到了 96%。
同一个 skill,只是 prompt 更宽泛。“这是我的目标”和“帮我找个问题”,两种方式都能得到结果。
在这两个循环中,诀窍都一样:为你所修改的行为选择一个稳定的衡量标准——自定义 rubric 或简单计数——同时把自适应内置指标视为整体健康度信号,因为它们的 rubrics 会在不同运行之间发生变化。
上面的循环使用 User Simulator,是因为我们当时还没有真实使用数据——这是循环中按需运行、面向开发的部分。随着 Agent 逐渐成熟并开始服务真实流量,生产 sessions 会成为最有价值的输入:每个 session 都对应一个真实请求,可能来自用户、另一个 Agent 或上游服务;每次失败也都是下一轮循环中现成的测试用例。同样的阶段现在不再由模拟数据驱动,而是由真实使用数据驱动。
同一个 skill 也能针对生产流量运行;你只需要让它使用真实 traces,而不是合成 traces。让它对上周的生产 sessions 进行评分,由于这些 traces 已经完整生成,它会完全跳过 Run Inference,直接使用同样的 raters 就地评分。Online Monitors 会持续评估实时流量,并将质量分数写入 Cloud Monitoring;当分数出现漂移时,你可以把失败 traces 交给同一个 skill,进入刚刚看到的 eval-fix 循环。仍然是同一个飞轮,只是节奏不同:在生产环境中持续运行,在开发环境中按需运行,并由同一套 AutoRaters 对两者评分。
目前,这个 skill 可以按需运行内部循环,也可以在你指定生产 traces 后对其评分。未来的发展方向,是让它自行驱动更多外部循环:监控 monitors、发现回归问题,并在流量变化时提出修复方案。
你需要准备:一个已启用 Agent Platform GenAI Evaluation Service 的 GCP project、一个需要评估的 Agent——可以使用 ADK 或任何其他框架——以及一个负责驱动该 skill 的 coding agent。如果需要对生产流量评分,你的 Agent 还应该生成 OpenTelemetry traces,ADK 默认会这样做。
安装由你的 coding agent 驱动的 skill:
# CLI-driven (ADK + agents-cli):
npx skills add https://github.com/google/agents-cli --skill google-agents-cli-eval
# SDK-driven (any framework):
npx skills add https://github.com/google/skills --skill agent-platform-eval-flywheel
然后启动一个循环:把它指向你的 Agent,并描述你希望衡量的内容。其余工作会由 coding agent 接手。
你的 Agent 不必做到完美,但它必须能够持续改进。
致谢:Quality Flywheel skills 及其底层服务由 Jason Dai、Ludwik Trammer、Iwo Naglik、Xi Liu、Aleksandra Grzegorczyk,以及更广泛的 Cloud AI Agent Platform 团队共同构建。本文所依据的演讲由 Alex Martin(Google)和 Daniel J. Lewis(Geotab)共同在 Cloud Next '26 上发表。
了解更多:Cloud Next '26 演讲 · Agent Evaluation 文档 · GitHub 上的 agents-cli · GitHub 上的 google/skills。