开源工具 AgentEval Forge 解决 agent 评估的根本难题——超越单一答案,评估完整执行路径。包含 20 个关键用户旅程、17 个确定性检查和 11 个 LLM 裁判指标。
两周前,我发表了《为什么 Agent 评估比模型评估更难》。核心观点是:评估 Agent 时,你判断的不只是一个答案,而是一次完整的运行过程。执行路径很重要,调用的工具很重要,安全边界也很重要。文章最后,我说等代码仓库准备好后就会分享出来。
现在,它已经准备好了。AgentEval Forge 已经开源并发布到 PyPI。这次发布其实也是一份报告,记录了我在尝试构建一套可信的 Agent 验证方法时学到的东西。
我原以为自己主要是在构建一个评分系统。但真实 Agent 化作了一场我毫无准备的海啸,这个项目也比我预想中更快地变成了一次对集成现实的全面检验。
我不想只给现有的评估框架套一层薄薄的封装,就把它称为一次产品发布。所以,我做得很深入。
PRD 定义了 20 条关键用户旅程(Critical User Journeys,CUJ),覆盖发布场景、回归工作流、对抗性用例生成和 CI 门禁。技术规格详细描述了一套由五个核心组件构成的架构:场景包引擎、Runner、包含 17 项确定性检查和 11 项 LLM-as-judge 指标的评分层、回归引擎,以及对抗性生成器。WBS 则拆分为横跨 12 个里程碑的 118 项任务,从 M0 项目脚手架一直到 M12 正式发布。
我为五种 Agent 接入方式构建了适配器:subprocess、Python import、HTTP、LangGraph 和 PydanticAI。每个适配器都实现了一套精简契约:Agent 接收的是受限调用 payload,包括场景输入、允许使用的工具、禁止使用的工具以及预算。它永远看不到预期答案或评分阈值,不会发生 ground-truth 泄漏。
我构建了一套安全模型,包括 sandbox 模式、信任策略、审计追踪和 API key 脱敏。我还构建了 CI 集成,包括 GitHub Actions、GitLab CI 和 Docker sandbox。文档方面,我编写了用户指南、评分指南、场景编写指南,以及包含原始数据的完整实地测试报告。
完整的能力清单可以在代码仓库的 README 中找到。如果你想深入了解产品和设计文档,可以查看 PRD、技术规格、评分指南和场景指南。概括来说,它包含:分属 10 个类别的 20 个发布场景、8 个安全场景、17 个确定性评分器、11 项 LLM-as-judge 指标、5 种框架适配器,以及一套将安全失败置于其他一切因素之上的产品评估层级。
我不想发布一套只对自己编写的示例有效的测试工具。但实地测试并不在最初的计划中。它是在构建后期临时加入的,因为我开始担心单元测试和 mock Agent 掩盖了真实的集成问题。事实证明,它们确实掩盖了问题。
从 GitHub 寻找真实 Agent,听上去很简单。搜索“langgraph agent”和“pydantic-ai agent”,挑几个出来,然后运行。可实际情况一点也不简单。
我搜索了 150 多个代码仓库,其中大多数都不可用。大型框架和平台过于沉重;依赖数据库的 Agent 需要额外的基础设施,而我无法为每个 Agent 单独部署;没有明确入口、没有 run() 方法、也没有消息接口的 Agent,只能静静地躺在那里,根本无法调用;藏在 API gateway 后面的 Agent,则需要我没有的 key。最终,我找到了 19 个看起来可以测试的 Agent:11 个 LangGraph Agent 和 8 个 PydanticAI Agent。即使是这些 Agent,也需要额外处理。
为了让测试结果具有实际意义,我还必须为实地测试划分不同的分组。高 Star Agent 属于可靠性组:这些被广泛使用的代码仓库,主要应该用来检验我的工具,而不是让我去检验它们。如果 EvalForge 连这些 Agent 都无法集成,那么首先应该归咎于我。中等 Star Agent 属于双向摩擦组:它们足够成熟,是真实可用的软件,同时也足够混乱,让测试能够同时暴露双方的问题。有时,我会发现它们在打包或启动流程上的缺陷;有时,我会发现自己的测试工具做出了错误假设。低 Star Agent 属于极限挑战组:这些实验性代码仓库往往更加混乱,但 EvalForge 也可以在这里展现明显价值,让一个粗糙的 Agent 更容易被评估、比较和改进。
每个 Agent 都有自己的配置文件、自己的场景包和自己的虚拟环境。我在三个档位上进行了测试:local、cheap 和 better。因为我从一开始就担心 token 成本,所以我认真投入了本地档位,而没有把它当成一个虚假的演示模式。在我的机器上,这意味着使用 MLX 部署 Qwen3.5-9B-MLX-4bit。它可以轻松运行在我的 Apple Silicon 配置上,只要 endpoint 状态正常,其能力也足以让本地批量测试变得值得。云端档位则分别使用 gpt-4o-mini 作为 cheap 档、gpt-4o 作为 better 档。
就在那一刻,原本干净利落的故事被打破了。我以为自己主要是在构建一个评分系统,而真实 Agent 却迫使这个项目变成了一次对集成现实的全面检验。
PRD 并不是后来才补上的东西。正是它迫使我始终诚实面对这个项目。
Product DNA 章节迫使我在写下第一行代码之前,回答一些令人不太舒服的问题。这个产品按优先顺序是为谁服务的?首先是独立 OSS 开发者,其次是小型团队,最后是平台团队。能够体现采用价值的最小成果是什么?在合并代码前发现一次回归。评估层级是什么?安全性 > 正确性 > 效率。
最后这一点构成了一种强制约束。它意味着,我不能设计出这样一套评分系统:最终给出一个漂亮答案,就能洗掉执行过程中发生的策略违规。安全失败始终会导致整次运行失败。正确性回归默认触发警告,但除非你主动配置,否则不会阻断流程。效率回归只提供信息。这套层级如今已经内置于系统生成的每一份 scorecard 中。
20 条 CUJ 是另一项强制约束。CUJ 不是一项功能,而是一个具体时刻:产品要么在这一刻证明自己的价值,要么证明不了。“一名独立开发者希望对照 baseline 评估候选 Agent 版本。”“一名团队负责人希望为特定领域的工具添加新的场景包。”“CI pipeline 需要在安全分数低于阈值时阻止 PR。”每个里程碑都必须能够通过至少一条 CUJ 证明自身的合理性。
这套纪律在一些方面拖慢了我的速度,而现在我对此十分感激。它阻止我构建一个什么都能做得还行、却没有任何一件事做得出色的通用评估库。
这也是项目最早带给我的真正教训之一:如果产品无法帮助某个人在合并代码前发现一次有意义的回归,那么其余架构大多只是装饰。
下面是我原本预期会发生的事、没有预料到的事,以及最令我意外的事。
我原以为,一些 Agent 会在特定的场景类别上遇到困难。我原以为 better 档的 judge 会比 cheap 档更有辨别力。我还原以为,大多数 Agent 都能通过大多数场景,真正有价值的信号会是哪些场景失败了,以及为什么失败。
这些预期没有一个符合事实。
通过率只有 9%。在全部 19 个 Agent 和 95 个场景中,仅有 9 次通过。这并不意味着名单中全是能力弱的 Agent,而是意味着当前的实地测试更多是在衡量适配器的真实性,而不是 Agent 的质量。当某个 wrapper 能让测试工具继续运行,却只返回空白 completion 时,judge 会给出零分。这是兼容性失败,不是质量失败。但它仍然主导了最醒目的总体数字。
最昂贵的模型没有带来任何额外价值。我使用两个云端档位测试了全部 19 个 Agent。cheap 和 better 的结果完全相同:两者都是 9/95 通过。better 档没有发现任何一项 cheap 档遗漏的回归或改进。瓶颈不在 judge 模型,而在于测试工具能够多么忠实地执行真实的 Agent 逻辑。当适配器质量不高时,judge 看到的就是糟糕的输出,并会给出低分——无论背后使用哪个模型担任 judge,结果都一样。
真正的阻碍是配置混乱。一个 Agent 在模块作用域中硬编码了 ChatOpenAI(),而它指定的模型并未部署在我的本地 MLX endpoint 上。要修补它,必须在模块导入之前,对 __init__ 执行 monkeypatch。另一个 Agent 会在导入时写入 /root。还有三个 Agent 携带了 ormsgpack,但它的 C extension ABI 与我的 Python runtime 不匹配,因此只能被隔离。某个代码仓库把 pyproject.toml 放在子目录中,导致在根目录执行 uv sync 时静默地什么也不做。最后,我编写了 8 个兼容性 wrapper 模块,为 3 个打包方式存在问题的代码仓库创建了 pyproject.toml,还彻底移除了 1 个 Agent,因为它停留在过时的 PydanticAI API 版本上。
当你在一台并非由你配置的机器上,运行并非由你编写的软件时,这些事情就是会发生。这也解释了为什么大多数 Agent 评估都局限在作者自己的环境里,使用作者自己的示例和作者自己的模型。那样确实很舒服,却也是检验 Agent 是否真正可用的最糟糕方式。
lg-mcp-agents 是一个 LangGraph 多 Agent 代码仓库。它之前无法脱离原有的 Streamlit 应用运行,但经过针对性的适配器改造后,在两个云端档位上都实现了 5/5 全部通过。
这个结果很重要,因为它表明适配器确实执行了真实的 Agent 行为。当一个两天前甚至无法导入的 Agent 得到 5/5 的结果时,这种集成是真实有效的。
实地测试工具原本并不在 WBS 中。我之所以加入它,是因为单元测试和 mock Agent 都通过得过于顺利,而这让我感觉不对劲。mock Agent 表现得太规矩了,它们会严格按照适配器契约的要求行事。真实 Agent 不会。
真实 Agent 会传递性地导入 ffmpeg。它们会使用与你不同的 Python 版本创建 venv。它们会写入绝对路径。它们会在模块作用域中硬编码 API key。它们会把项目文件嵌套在子目录中。mock 覆盖率无法发现这些问题,因为 mock 覆盖率并不运行真实代码。
教训并不只是“加入实地测试”。真正的教训是:对于一套评估工具来说,单元测试和 mock 覆盖是必要的,但并不充分。从一开始就应该规划一个真实 Agent 实地测试层。它将是唯一能够捕捉集成现实的测试层。
这可能是本次发布带给我的最大收获:人们讨论 Agent 评估时,往往把它当作一个评分问题;但在实践中,它会以远超大多数团队预期的速度,变成环境、适配器和真实性问题。
这是 v0.1.0,我想明确说明这一点。
实地测试证明,AgentEval Forge 可以规模化地导入、配置、调用来自 GitHub 的真实第三方 Agent,并对其进行评分。但它还没有证明,评分器能够在规模庞大且高度异构的 Agent 名单中,对 Agent 做出有意义的排序。一些 PydanticAI wrapper 在所有场景中都出现了空白 completion——测试工具成功运行了,但 Agent 并没有生成真实输出。这是兼容性上的成果,而不是评估上的成果。我选择如实说明,因为我认为这类问题经常在产品发布公告中被轻描淡写地带过,随后才由用户痛苦地发现。
一些 PydanticAI wrapper 中出现的空白 completion 行为仍需调查。ormsgpack 的 C extension 不匹配问题导致 3 个原本可用的 Agent 被隔离,需要通过容器化方案解决。实地测试名单也需要继续扩充:更多 Agent、更高多样性、更多边界情况。适配器质量需要持续提升,直到实地层面的兼容性真正转化为评估层面的实用性。SWE-bench 和 WebArena connector 已经构建完成,并通过了端到端验证,但尚未集成到默认 CI 路径中。
这个系列文章也只完成了 1/5。我已经写过为什么 Agent 评估比模型评估更难。现在,这次发布为接下来的文章提供了更好的素材:场景包究竟应该是什么样子、如何思考 trajectory 评分、对抗性测试从哪里开始真正发挥作用,以及为什么相比集成真实性,成本与质量之间的权衡往往没有那么重要。
代码仓库位于 github.com/deghosal-2026/agent-eval-forge。可以使用 pip install agent-eval-forge 安装。README 中包含完整的能力清单,代码仓库的文档中还包括用户指南、实地测试报告,以及这些来之不易的经验教训。
如果你正在构建 Agent,我有一个问题想问你:你目前使用怎样的评估工作流?你是否仍然只是凭感觉查看几个 demo,然后就认为工作完成了?你是否已经尝试为 trajectory 评分,还是仍然只检查最终答案?
如果你已经尝试过规模化评估 Agent——尤其是由第三方编写、并非出自你手的 Agent——最先出问题的是什么?
如需采取进一步行动,你可以考虑屏蔽此人和/或举报滥用行为。