GitHub PR #1192

工具化评测环境 judge

这个 PR 把评测从“看最终答案是否匹配”推进到“在受控业务环境里验证结果”。worker 只通过公开工具完成任务,judge 则作为独立 agent session 调用审计工具,从最终状态、动作日志、状态差异和最终回复多个角度判断任务是否真的完成。

Base: main Head: feat/eval-judge-tool-agent 2026-07-08 更新 大规模新增:38 个文件 建议拆为外部评测 harness
PR
代码规模
+10,080 / -2
提交数
5
核心入口
blade eval-env

一句话结论

PR #1192 新增了一套可编译、可托管、可审计的工具化评测环境,让复杂业务任务的评测可以检查“状态是否正确改变、是否有错误副作用、worker 是否按受控工具办事”,而不再主要依赖静态字段或最终文本匹配。

评测价值: 它更适合验证财务、法务、客服、订单处理这类有状态、有规则、有副作用的业务任务。judge 可以拿到环境证据后做解释性裁决,减少“答案看起来对,但系统状态其实错了”的误判。

影响范围

  • 新增 Go CLI 命令:blade eval-envblade eval-package
  • 新增 Python EnvSpec compiler 和 runtime 模板。
  • 新增 server route:注册 runtime、注销 runtime、代理 tool-call。
  • 新增 rehearsal runner、prompt、archive、RunSpec 支持。
  • 新增 easy / medium / hard 三个示例评测环境 IR。
  • 更新 Docker / Makefile,把 CLI tools 一并打包到产物。

工作流

1. 编写 EnvSpec builder 只提交 env_spec.yaml,描述业务实体、工具、case、目标状态和禁止副作用。
2. 编译环境 blade eval-env compile 生成 env_runtime、worker package 和 judge 材料。
3. worker 执行 worker 只能通过 call_tool.sh 调业务工具,不能直接接触 SQL、hidden goal 或 verifier。
4. runtime 托管 runner 在 server 注册 case runtime,工具调用经 /api/eval-env/tool-call 代理到隔离环境。
5. judge 审计 judge 读取 audit 输出,结合 DB 状态、action log、state diff 和 final response 给出裁决。

主要新增能力

受控环境编译

cli/tools/evalenv/compiler.pyenv_spec.yaml 编译成可执行环境,包含 SQLite 初始状态、工具 controller、worker 可见包和 judge 审计材料。

工具化调用协议

worker 面向的是业务工具,而不是数据库或验证器。工具前置条件失败会以业务错误返回,协议错误会被统一包装,便于 judge 区分“业务失败”和“调用方式错误”。

独立 judge runner

rehearsal runner 支持 worker 完成后启动独立 judge session。judge 不复用 worker 上下文,而是基于环境证据进行复核。

安全与隔离设计

  • server 只允许注册受控的本地 runtime root,并通过 token 校验 tool-call。
  • runtime 注册记录按 user 和 run_id 隔离,并有 TTL 清理。
  • 后续修复加入 runtime map 锁,避免并发注册、清理、调用时的数据竞争。
  • case_id 增加路径穿越校验,避免通过 ../ 访问其他 case 或 runtime 文件。
  • .gitignore 排除 env_runtime/work/judge/ 等生成产物。

是否可以改成非侵入 BA 的方案?

结论: 大部分可以,而且建议这么做。这个 PR 里 compiler、EnvSpec、示例 IR、runner 编排、archive、judge prompt、审计规则都不必进入 BA 主体,可以作为独立评测 harness 或独立 Python/CLI 包存在,通过 BA 已有 SDK 创建 session、上传 worker 包、发送任务、订阅事件、下载结果,再启动 judge session 进行复核。

可以外置的部分

当前 PR 内容 外置方式 是否需要改 BA
EnvSpec compiler 与 runtime 模板 放到独立 blade-eval-env 包或 eval 仓库,生成 work.zip、judge briefing、审计材料。 不需要
rehearsal runner / RunSpec blade-agent-kit Python SDK 调 BA:创建 worker session、上传输入、发送任务、订阅结束事件、下载输出。 不需要
judge agent session runner 再创建一个 judge session,把 audit JSON、state diff、action log 摘要和 worker 输出作为上下文输入。 不需要
示例 IR 与评测包构建 skill 放在评测仓库或 SDK 示例目录,作为外部评测资产维护。 不需要
TypeScript REST 类型更新 如果不新增 BA eval-env route,就不需要污染前端 SDK OpenAPI 类型。 不需要

真正卡住外置化的点

当前 PR 最侵入 BA 的部分是 /api/eval-env/tool-call:它让 worker 在 BA 沙盒里调用一个由 runner 托管、worker 看不到实现细节的受控 runtime。这个能力的价值是“worker 只能通过业务工具行动,不能读 hidden goal、verifier、SQLite 或 reference trajectory”。如果完全不改 BA,也不提供等价回调通道,就只能二选一:

更推荐的拆分方案

层次 建议 原因
外部 eval harness 保留 EnvSpec、compiler、runner、judge orchestration、样例 IR 和审计逻辑。 这些是评测产品能力,不是 BA 的通用运行时能力。
BA SDK 复用现有 Python SDK 的 session、upload、chat、download、headless 能力;缺少的只在 SDK 补薄封装。 runner 作为第三方调用方可以完整 dogfood BA,而不是把评测逻辑塞进 server。
BA 主体 如果必须支持隐藏 runtime 的实时工具调用,只新增通用能力:session-scoped external tool bridge 或 MCP/tool-provider 注册,而不是 eval-env 专用 route。 通用扩展点可服务评测、业务插件、外部系统工具,不会把评测概念固化进 BA server。
短期 MVP 先做纯 SDK runner:worker 包含公开工具 wrapper,runner 在外部完成审计;需要强隔离的 case 暂走外部服务回调。 能快速验证工具化 judge 的价值,同时把 BA 改动压到最小。
对这个 PR 的处理建议: 不建议按当前形态直接合入 BA 主干。更稳妥的路线是把 PR 拆成两个方向:第一部分迁到外部 eval harness,通过 blade-agent-kit 调 BA;第二部分如果确有必要,再单独设计一个通用 external tool bridge。这样可以保留工具化 judge 的核心价值,同时避免在 BA server、CLI、OpenAPI 类型和镜像构建里引入大量评测专用代码。

参考 agent-octagon 后的细化判断

[本地路径已隐藏] 已经验证了一个更低侵入的形态:评测平台独立运行,BA 只是被 SDK 调用的 agent runtime。环境状态、工具鉴权、trace、scorer、对比视图都在 Octagon 自己的进程和数据目录中,BA 不需要新增 eval 专用 API。

Octagon 的关键设计

设计点 Octagon 做法 对 PR #1192 的启发
环境是外部黑盒 Env Attempt Server 暴露 /attempts/{id}/tools/{tool},鉴权后调用 env 的 core.py eval-env server route 不应放进 BA;应放在评测 harness 进程中。
BA 工具只是传送门 blade_skill/tools.py 不 import env core、不写 DB,只读取 .octagon/attempt.json 后 HTTP 回调 Octagon。 PR 的 call_tool.sh / tool proxy 可以变成外部生成的 skill 薄壳,不污染 BA CLI/server。
多 agent 入口统一 Blade 走 skill HTTP 回调;Claude/Codex 走 MCP stdio;最后都汇聚到同一个 env attempt server。 评测环境入口应面向多 agent 设计,不应绑定 BA 的专用 route。
trace 在环境层落盘 @env_tool wrapper 自动记录 trace.jsonl,adapter 不负责写环境轨迹。 PR 的 action log / state diff 应由 eval harness 统一生成,BA 只提供 agent 事件和 workspace 产物。
runner 通过 SDK 调 BA BladeAgentClient 创建 session、上传 attempt 配置、stream chat、读 history、删除 session。 PR runner 应优先使用 blade-agent-kit,而不是把 runner 逻辑推进 BA 内部。
scorer 独立于 agent scorer 读取 env DB、trace、final_state,不读 agent thinking。 工具化 judge 可以作为 scorer 后的解释层,而不是替代确定性审计。

推荐的目标架构

1. Eval Harness 独立进程加载 EnvSpec / env core,管理 attempt、token、DB、trace、scorer。
2. BA SDK Adapter blade-agent-kit 创建 headless session,上传 attempt 配置和任务物料。
3. Skill 薄壳 BA sandbox 内工具只读 attempt 配置,并把业务工具调用转发到 harness。
4. Deterministic Audit harness 基于 DB、trace、state diff、final response 产出可复现 audit JSON。
5. Judge Session 再用 SDK 启动 judge agent,读取 audit 证据,输出解释性裁决。

PR #1192 可拆分清单

当前变更 建议归属 处理方式
server/routes/eval_env.py 移出 BA 改为外部 harness 的 Env Attempt Server。BA 不需要注册 runtime,也不需要保存 _RUNTIMES
cli/internal/cmd/eval_env.go 移出 BA 或降级 作为外部 blade-eval CLI;BA CLI 只保留通用能力,不打包评测 compiler。
cli/tools/evalenv/compiler.py 外部 eval 包 保留价值很高,但应由 eval harness 发布和版本化。
scripts/eval_rehearsal_runner.py 外部 eval runner 重写为 SDK adapter 模式:create_sessionupload_filechatget_historydownload_file
evals/thinking_envs/* 外部评测资产 保留为 eval repo 的 fixtures;BA 仓库只可放轻量示例或链接。
web/packages/agent-kit/src/client/types/rest.ts 不应变化 删除 eval-env 专用 OpenAPI 类型。若 SDK 缺方法,只补通用 session/file/history 方法。
core/builtin_skills/.../eval-package-builder 谨慎外置 如果这是评测作者工具,应作为外部 skill 或模板包,不进入 BA builtin skills。

BA 侧真正值得补的通用能力

和当前 PR 方案的核心差异

维度 PR #1192 当前方案 Octagon 式方案
BA 侵入度 新增 server route、CLI、OpenAPI 类型、Docker 打包、builtin skill。 BA 基本不变,只使用 SDK 和已有 skill/session 能力。
环境生命周期 BA server 临时注册 runtime root,并代理 tool-call。 外部 harness 自己管理 attempt、token、DB、trace、terminal status。
工具协议 worker 调 blade eval-env call 或 server proxy。 worker 调 BA skill;skill 薄壳 HTTP 回调外部 env server。
多 agent 扩展 主要围绕 BA worker/judge 设计。 Blade、Claude、Codex 可通过不同 adapter 接同一个环境核心。
审计权威性 audit、state diff、judge runner 混在 PR 新增代码里。 trace 和 scorer 在环境层统一生成,judge 只解释证据。
更新后的建议: 以 agent-octagon 为参考,PR #1192 最好先退回为外部评测平台实现。BA 主仓只接受少量通用 SDK/会话能力增强;等外部 harness 跑通并证明需求稳定后,再讨论是否把“session 级外部工具 bridge”作为 BA 通用扩展点合入。

文件分布

区域 代表文件 作用
CLI cli/internal/cmd/eval_env.go
cli/internal/cmd/eval_package.go
新增评测环境编译、审计、托管调用,以及评测包脚手架和规则检查入口。
Env compiler cli/tools/evalenv/compiler.py
runtime_templates.py
把 EnvSpec IR 编译为 runtime、worker 包、judge 材料和审计器。
Server server/src/blade_agent/server/routes/eval_env.py 提供 runtime 注册、注销和工具调用代理 API。
Runner scripts/eval_rehearsal_runner.py
scripts/eval_rehearsal_runspec.py
支持 IR 自动编译、worker/judge 编排、归档和 RunSpec 执行。
示例场景 evals/thinking_envs/*/env/env_spec.yaml 提供 easy、medium、hard 三档业务评测环境样例,只提交 IR,不提交生成产物。
测试 tests/test_eval_env_tool_proxy.py
cli/internal/cmd/*_test.go
覆盖工具代理、路径校验、编译审计、CLI 行为和 eval package 构建规则。

验证情况

  • 运行 EnvSpec IR 自动编译检查:ensure_existing_package_compiled(...)
  • 对新增 Python 文件执行 py_compile
  • 对 CLI compiler、runner、server route 和测试执行 ruff check
  • 运行 Python 测试:tests/test_eval_env_tool_proxy.pytests/test_builtin_eval_package_builder_skill.py
  • 运行 Go 测试:go test ./internal/cmd -run 'TestEvalEnv|TestEvalPackage'

需要关注

这是一个横跨 CLI、server、runner、文档、示例 IR 和生成器的大型新增能力,代码体量超过一万行。后续合入前最值得关注的是端到端 rehearsal 是否在真实 runner 环境稳定,以及 server runtime 托管的权限边界是否符合部署预期。

复审重点

  • 确保生成产物不会被误提交,尤其是 env_runtime/work/judge/
  • 确认 Docker / release 镜像内确实包含 cli/tools,否则 CLI wrapper 无法找到 Python compiler。
  • 关注 eval-env route 的本地路径白名单与 token 传递方式,避免扩大可访问面。

提交脉络

提交 含义
54fb0c4 主功能提交:新增工具化评测环境 judge。
c6e0fc7 同步 main。
b442526 / f4b168e 围绕生成产物清理进行调整与回滚。
9171774 处理 review 问题:并发锁、路径穿越防护、structured initial values 序列化、worker 解压提示修正等。