30 秒看懂
Arize AI 的 Xander Song 介绍了开源框架 Harbor。它通过真实任务、隔离环境、独立试验和结果验证器来评估智能体。他解释了 oracle 解法如何先验证评估流水线,以及为什么基于结果的检查能在智能体实现变化时继续发挥作用。 Song 随后展示了 Phoenix 团队如何把 Harbor 与版本化数据集和轨迹结合起来,测试团队维护的智能体接口。在一个案例中,提示词引导智能体用只读 SQL 工具处理聚合查询后,SQL 使用增多,工具调用减少,正确性奖励仍保持较高水平。他还讨论了并行执行、分布式系统的限制、技能回归测试,以及获取真实数据的难点。
- 1在隔离环境中评估真实任务Harbor 任务把自然语言指令和数据交给全新沙箱中的智能体。任务专属验证器检查结果并产生奖励,让团队能用同一任务比较不同的智能体改动。
- 2用 oracle 验证评估本身先运行已知解法脚本,就能在启动智能体之前检查环境和验证器是否正常,从而在消耗 token 之前发现数据或配置问题。
- 3用结果检查建立更持久的回归测试验证器可以像集成测试一样,把智能体当作黑盒,只检查它留下的结果。当执行路径本身是测试目标时,检查轨迹也有用,但会让测试更依赖实现细节。
- 4并行运行独立试验每次试验都有独立且初始状态相同的沙箱。Song 表示,团队使用 Daytona,约有 200 个并发工作进程,并会计算三次尝试内是否成功等指标。
- 5用 Phoenix 检查 Harbor 实验Phoenix 把 Harbor 的 job 和奖励映射为实验与评估,将 ATIF 轨迹转换成 OpenInference trace,并提供数据集版本和对比视图。Harbor 也可以独立使用。
- 6把智能体与产品接口一起评估Phoenix 团队在沙箱中放入 Phoenix 服务和真实 SQLite 数据,测试智能体与 CLI、MCP 服务、技能或服务端 harness 的组合。验证器可以查数据库或调用 API,确认预期效果。
- 7用具体工作负载衡量提示词改动团队添加只读 SQL 工具后,修改提示词,引导智能体用它处理聚合查询,再用带 oracle 解法的合成任务评估。示例中 SQL 使用增多,平均工具调用减少,正确性奖励仍保持较高水平。
要点建议
- 用真实数据定义任务,并让验证器检查真正重要的结果。
- 先运行 oracle 解法,发现环境和验证器的问题,再为智能体运行消耗 token。
- 通过独立试验和并行沙箱处理随机性,并比较智能体改动的效果。
- 条件允许时,让正确性检查独立于智能体实现;当执行路径本身就是指标时,再检查轨迹。
- 评估智能体实际使用的完整系统,包括工具、技能、API 和有代表性的应用环境。
- 为数据集保留版本,既比较汇总奖励、成本、延迟和工具使用,也检查单次运行。
按章节阅读整理后的全文
以证据为依据交付
Xander Song 介绍开源框架 Harbor:它用真实任务和数据评估智能体。他说明可靠评估如何帮助团队更有信心地迭代智能体、技能和工具。
我是 Xander Song,Arize AI 的工程师,负责 Phoenix 这一开源可观测性、实验和评估平台。今天我想介绍 Harbor:它是一个开源框架,可以在隔离环境中用真实任务和真实数据评估智能体。演讲的主题是以证据为依据交付,而不是凭感觉。
我希望解释 Harbor 的工作方式,以及团队如何用它更有信心地迭代智能体、harness、技能、提示词和工具。今天是讨论,不是动手工作坊。先说明一下:我不是 Harbor 的维护者,但已经非常熟悉它的使用。
任务、沙箱与验证器
自然语言任务让智能体在全新环境中运行,验证器随后检查它留下的结果。固定任务和验证器,便于比较不同的智能体改动。
从整体看,Harbor 任务是一条自然语言指令,描述你希望智能体完成的事情。Harbor 把指令交给全新沙箱中的智能体,沙箱里预先放入相关数据。你可以定义任务专属验证器,检查环境中留下的结果,并给出零或一、通过或失败等奖励。
如果任务和数据足够真实,验证器也准确描述了成功条件,你就可以固定任务与验证器,只改变智能体实现。运行同一条流水线,便能判断改动让这个任务的表现变好还是变差。收集覆盖智能体主要能力的多个任务,比单凭直觉更容易建立迭代信心。

试验、轨迹、job 与 oracle
Harbor 把指令、环境和测试脚本组成数据集,并运行独立试验。ATIF 轨迹记录执行细节,oracle 则能在启动智能体之前验证评估配置。
每个任务都包含指令,通常写在 Markdown 文件里;还包含环境,常用 Dockerfile 描述。环境可以装入任务所需的任何数据,例如 SQLite 数据库,或固定在某个提交的 Git 仓库。Harbor 不限定数据的类型。
任务还会在测试目录中提供验证脚本。智能体运行完后,脚本检查环境,看预期的变化是否发生。多个任务可以组成一个数据集,每个任务又可以配置多次相互独立的试验。
重复试验很重要,因为语言模型和智能体具有随机性,每次运行不会完全一样。每次试验都从带有相同种子数据的全新容器开始,把选定的智能体放进去并交给它任务。智能体可能修改源文件或数据库,验证器随后检查结果并写入奖励。

你还可以让智能体输出 ATIF 轨迹。ATIF 是 Agent Trajectory Interchange Format,即智能体轨迹交换格式,以 JSON 记录智能体采取的步骤,便于调试和检查。对整个数据集运行试验、验证器、奖励和轨迹收集,合起来称为一个 Harbor job。
Harbor 还支持 oracle,也就是能解决该任务的脚本。先运行这个已知解法,可以在为智能体消耗 token 之前,检查数据、环境和验证器是否配置正确。它帮助我们确认评估流水线本身能够工作。
以失败的数据库迁移为例
Song 展示一个修复迁移的任务,包含数据库、源文件、oracle 和预期表结构检查。验证器在智能体结束后挂载,并评估最终结果。
假设一个编程智能体的任务是修复失败的数据库迁移。指令可以很简单:告诉它迁移失败,并请它修好。环境里可以放入数据库、表结构定义和源代码,其中的 up 迁移被有意设置为失败。

验证器可以运行迁移,检查退出状态是否为零,再核对预期的表、列和索引。可选 oracle 则是应用实际修复的脚本。如果 oracle 能通过验证器,我就能在测试智能体前,对任务和检查的配置建立一定信心。
智能体修改坏掉的迁移文件后,验证器会检查文件系统和数据库中的结果。在 Harbor 默认的本地 Docker 设置中,验证器通常等智能体结束后才挂载进容器,因此智能体执行时无法查看测试或解法。
黑盒验证与可维护性
验证器通常只判断输出和副作用,不依赖智能体内部实现。Song 将它比作集成测试,并讨论与实现耦合的测试需要付出的维护成本。
标准的验证器不关心智能体内部如何实现。它把智能体视为黑盒,依据最终结果和副作用评分,而不要求智能体走某条固定路径。需要时你也可以检查轨迹,但那是另一类检查。
这类似于为 API 编写良好的集成测试:测试描述接口应有的行为,却不依赖接口背后的实现。你可以重构智能体、更换工具或调整 harness,同时保持任务不变,然后快速检查结果是否仍然正确。
一位听众问什么样的系统适合放进环境。它本质上是 Docker 容器,因此智能体可以用任何框架或语言构建,环境里也可以装入所需的可执行代码。团队在调整工具、提示词和技能时,就利用了这种灵活性。
例如,我们正在整合多个智能体体验共同使用的技能,包括基于 MCP 的智能体、基于 CLI 的智能体,以及我们自己的服务端智能体。过去的测试与某个具体工具耦合过紧,工具一改就会失败,即使用户真正需要的功能仍然完好。独立于实现的测试更容易跟随这些变化维护。
并行扩展独立试验
隔离的试验可以在不同沙箱提供商上并行运行。重复运行和三次尝试内是否成功等指标,有助于应对智能体行为的随机性。
每个任务和每次试验都独立运行在自己的容器里,因此整条流水线可以水平扩展。Harbor 可以配合 Daytona、Modal、E2B 等沙箱提供商。我们使用 Daytona,约有 200 个工作进程并发运行,因此能够很快处理大型测试集。
假设有四个任务、两种智能体配置,每种配置在每个任务上试验三次。图中的每个方格都是独立且初始状态相同的容器;智能体开始后,各次试验可能采取不同路径。把它们并行运行,才能让重复评估变得实用。

从这些试验中可以计算指标,例如 pass at three:智能体在三次尝试内是否成功。你可以对每个任务计算,再汇总到整个数据集。好的数据集能让你快速看到改动对关心的能力产生了什么影响。
将 Harbor 接入 Phoenix
Phoenix 把 Harbor 的概念映射到数据集和实验,并把 ATIF 轨迹转换成 OpenInference trace。它提供版本管理、可视化与检查工具,但不是使用 Harbor 的必要条件。
Harbor 也能接入我参与维护的 Phoenix。Phoenix 把 Harbor 的数据集、job、试验和奖励映射为自己的数据集、实验、运行和评估,并能将 ATIF 轨迹转换成 OpenInference trace,让我们检查运行中的步骤。
OpenInference 是一套建立在 OpenTelemetry 之上的语义约定;OpenTelemetry 负责处理 trace、日志、指标等遥测数据。这些约定描述 AI 应用事件的数据结构,供 Phoenix 等下游工具接收和使用。我也是 OpenInference 的维护者,其规范已经捐赠给 OpenTelemetry 工作组。

在数据库迁移示例中,ATIF 记录可以包含智能体步骤、模型调用和工具调用。转换后,Phoenix 能把它们展示为 trace,并提供适合智能体、语言模型和工具的界面。这样我们看到的不只是最终奖励,还能追查试验内部发生了什么。
Phoenix 还能为任务和数据集保留版本、记录实验,并绘制奖励和其他指标随时间变化的图表。技能、CLI 和 MCP 服务让编程智能体也能访问这些信息。Harbor 本身有本地开源界面和托管服务,使用它并不一定需要 Phoenix;上述功能是你可能考虑接入 Phoenix 的原因。
评估 Phoenix 智能体系统
Song 介绍 Phoenix 的 API 和三种智能体接口。团队把单节点服务、真实 SQLite 数据和测试客户端打包进沙箱,再检查智能体是否产生预期改动。
要理解我们如何使用 Harbor,可以先看 Phoenix 的正常架构。经过埋点的 AI 应用通过 OTLP 向 Phoenix 服务发送 trace。服务把它们存入 SQLite 或 Postgres,并通过 REST 和 GraphQL API 提供 trace、span、会话、数据集、实验和评估等服务。

我们围绕这些 API 支持多种智能体体验。编程智能体可以使用我们的 CLI 或 MCP 服务;我们的服务端智能体 Pixie 也可以使用 MCP 服务。Pixie 还有一个 bash 模拟器。这些是团队分别需要支持和测试的接口。
我们的架构在测试方面有一个优势:Phoenix 在单节点运行,很容易放进 Docker 容器。我们用包含真实数据的 SQLite 文件做种子数据,并用测试客户端代替浏览器。整个应用进入容器后,就能把它作为 Harbor 环境使用。
一个真实用户任务可能是:找出过去一周 trace 中产生幻觉的模型调用,并把它们加入数据集。我们可以把任务交给三种智能体配置中的任意一种。运行结束后,验证器可以调用 REST 端点,或直接查询 SQLite 数据库,确认预期的数据集变化是否发生。

编排流程与更复杂的环境
Harbor 作为主机侧 CLI 运行,通过脚本编排智能体、验证器和 oracle。Song 讨论了环境灵活性、数据规模,以及如何避免在测试分布式系统时过度依赖 mock。
一位听众问 Harbor 如何控制这套环境。一次试验只测试一种智能体配置,不会同时测试三种。Harbor 本身是运行在笔记本或 GitHub Actions runner 等主机上的 CLI 编排器;环境可以是本地容器,也可以是远程沙箱。
Harbor 通过脚本启动智能体和其他步骤。任务要提供启动工作、运行验证器和运行 oracle 的脚本,并放在 Harbor 预期的位置。它的契约主要是一套关于脚本及其存放位置的约定。
环境的配置非常灵活。常见的入门例子是让编程智能体操作 Git 仓库;我们的例子则包含 SQLite 数据库、Phoenix 服务与 API、CLI、智能体,以及文件系统上的技能。只要能把需要的东西打包进 Docker 镜像,Harbor 就可以运行这个环境。
有位听众提出更难的情况:如果应用是包含 S3 等服务的分布式系统,而不是单个服务和 SQLite 文件,该怎么办?我还没有亲自解决过。一个可能的做法是把智能体隔离在稳定接口后面,并在边界提供数据;但模拟外部服务可能让我们重新面对原本想避免的维护问题。
Harbor 可以运行多个 Docker 镜像,因此把多个组件一起打包可能也是值得探索的方向。我不能说已经有完整的分布式系统解决方案;我们的单节点架构让这项工作容易了不少。
另一个问题是数据集规模。我们目前使用较小的数据集合,有时会让 Claude 针对某个任务帮忙清理。多个任务可以共用同一份数据,但不必强制如此。如果一个问题只需要很小的数据子集,就不必上传全部数据。
如果目标是测试智能体在完整数据库或高负载下的表现,放入更多数据就很有意义,但我们还没有这样做。至于为什么要把 Phoenix 和 Harbor 一起用:你完全可以只用 Harbor;Phoenix 补充了数据集版本、实验视图、可视化和深入检查结果的方式。
案例:引导智能体使用 SQL
团队添加只读 SQL 工具,并测试一条建议用它处理聚合查询的提示词。合成任务和 oracle 解法显示,SQL 使用增多,工具调用减少。
我们的具体案例从聚合问题开始。用户可能问哪一天的 trace 最多,或哪个模型的成本最高。MCP 服务和 CLI 原本可以调用 REST 和 GraphQL,但现有端点不是聚合解析器,因此智能体可能需要逐页获取结果,再自己计算聚合值。
数据增多后,这种做法可能产生大量工具调用。我们给 MCP 服务添加了只读 SQL 工具,让智能体直接查询数据库。但工具增加后又出现一个选择问题:智能体同时面对 REST、GraphQL 和 SQL,却不总会在合适的场景选用 SQL。

我们修改了原先偏重 GraphQL 的提示词,新指引建议智能体在处理计数、分组等聚合问题时使用 SQL 工具。接下来要验证的是,这个改动是否真的改善了行为,而不是直接假定它有效。
我们在环境中放入一个半真实的 SQLite 文件,数据来自团队开发和亲自使用 Phoenix 的过程。随后我让 Claude 查看 trace、span、数据集和实验等产品领域,生成一些用户问题,其中既有聚合问题也有非聚合问题,再为它们编写 REST 调用或数据库查询形式的 oracle 解法。
我抽查了这些合成问题。验证器包括 SQL 查询、REST 调用,也有一些让模型担任评判者的检查。看到验证器能对 oracle 通过,让我在比较智能体行为之前,对评估配置建立了一定信心。
提示词改动让智能体按预期更频繁地使用 SQL,也降低了轨迹中的平均工具调用次数。测试数据并不特别大,因此在真实工作负载需要翻更多页时,这里观察到的下降幅度可能低估了收益。
检查和比较实验
Phoenix 展示版本化示例、奖励、成本、延迟与轨迹。并排对比可以把汇总指标的变化关联到单个任务;执行路径本身重要时,也可以检查路径。
在 Phoenix 中,数据集视图展示任务示例及其版本历史。一个例子询问按总成本计算最贵的三个模型。参考答案来自 oracle 对种子数据执行的 SQL 查询;结果是确定性的,但我仍然需要相信查询本身写得正确。

Phoenix 把 Harbor job 称为实验,并展示成本、延迟、奖励、工具调用和 SQL 使用情况等指标。这个案例中奖励原本就很高,因为改动前系统通常已经能得到正确答案。我们的目标是减少不必要的调用,而不是修复错误答案。
奖励来自你为每个任务编写的验证器。你决定什么算成功,以及如何从文件系统或数据库等环境状态识别成功。验证器可以输出零或一,也可以给奖励起其他名字;实验视图随后汇总这些结果。
一位听众注意到,有些检查会查看轨迹,判断是否使用了 SQL,而我之前说验证器通常是黑盒检查。这个问题很合理。对于纯粹的正确性回归测试,我们可以只检查最终答案或副作用,不依赖智能体采取的路径。
这次实验的目标不同:我要优化工具使用,因此确实关心执行路径。Harbor 既可以支持端到端正确性测试,也可以用来研究某个特定行为。查看轨迹有时很有用,不过测试可能因此更容易受到实现变化影响。
Phoenix 还可以帮助团队共享和整理数据、把 trace 加入数据集,并从外部文件存储或更新数据。不过,我不能声称自己有太多大团队的亲身经验,因为目前只有少数几个人在做这套评估。
对比视图让我能在汇总层面和单个任务层面并排查看两个 job。这个例子比较的是同一模型修改提示词之前和之后的表现:GraphQL 调用与总工具调用下降,SQL 调用增加,而奖励基本保持不变。

表格可以展示每个任务的预期答案、实际输出和指标。单个结果可能与整体趋势不同:其中一个例子里,工具和轮次数下降了,但 SQL 调用次数也下降了。逐任务检查可以避免平均值掩盖这些细节。
我可以筛选对比结果,找出第二次实验减少工具使用的案例。演示中,我尝试让浏览器里的本地模型把自然语言筛选条件转换成查询 DSL,但它没有按预期工作,于是我粘贴了一个已知正确的表达式,把表格缩小到需要检查的案例。
转换后的 ATIF trace 展示了某个任务的具体变化。提示词改动前,智能体使用 bash,而 bash 在底层调用 GraphQL;改动后,它直接发出了 SQL 查询。我可以直观看 trace,也可以让智能体检查这些实验并解释差异。
这构成我们反馈循环的一部分:使用智能体,记录它的 trace 和结果,再根据这些观察改进智能体本身。逐任务对比能把整体指标的变化关联到具体运行。
回归测试、技能与真实数据
Song 讨论技能触发测试、黑盒检查与依赖实现的检查之间的取舍,以及为何要评估智能体和工具组成的完整系统。他最后强调获取真实数据的难度。
我们的回归测试仍处于早期。我们先为重要技能建立正常路径测试,因为在我们的场景中,技能描述的是工作流。这些测试类似把智能体和语言模型调用放进循环的端到端测试;我们希望它们在支持的各类模型和提供商上都能通过。
一位听众问,如果新技能的 front matter 与已有技能重叠,导致原本应该触发的技能没有触发,会怎样?一种做法是只关心最终结果:如果任务成功,也许不必在意触发了哪个技能。当这个选择影响结果时,好的端到端测试就能发现失败。
另一种做法是让验证器检查轨迹,明确判断调用了哪个技能。我们写过这样的测试。它与实现细节耦合更紧,因此更改技能名称可能导致测试失败;但聚焦单轮的测试可以很简单:提出一个问题,再检查预期技能是否触发。
从完全不依赖实现的端到端测试,到依赖某个内部步骤的测试,中间有一个连续的范围。两类测试都可能有用。重要的是覆盖真正关心的行为,同时理解每种检查的维护成本。
在生产环境中,经过埋点的应用把 trace 发给 Phoenix,由它写入数据库。在 Harbor 环境里,我们省略终端用户应用和遥测接入环节,直接为数据库提供种子数据。我们假设生产应用已经生成了 SQLite 文件所代表的数据。
Harbor 经常用来评估编程智能体本身,但那不是我们这里要评估的完整单元。我们不维护 Claude Code 或 Codex。我们评估的是混合系统:编程智能体加上我们的 MCP 服务、CLI、技能或 API,或者我们的服务端智能体及其配套基础设施。
这些部分需要一起变化、一起评估,因为它们共同决定智能体能否有效使用我们的产品。我们花了一些时间才形成这个整体认识。Phoenix 能在单节点运行、容易容器化,对我们帮助很大;使用分布式系统的团队可能要承担更多配置工作。
Harbor 的约定还要求脚本放在正确的目录里,而编程智能体未必有 linter 可以检查这套契约的每个部分。Harbor 自带的技能可以帮助智能体按预期方式配置项目。
至于 SQLite 文件,我们目前的做法比较临时:保留一批数据,任务适合时就复用其中的文件。如果文件包含太多内容,我可能让 Claude 删除不需要的部分,再把结果放到云存储中。
获取数据是最难的部分。数据越真实,评估就越有机会发现智能体系统在真实场景中的问题。这仍然是构建这些任务时的主要挑战。
同频道的其他文章
19:43EN → 简体中文
20:55EN → 简体中文
18:27EN → 简体中文
17:56EN → 简体中文
35:19EN → 简体中文
20:58EN → 简体中文