编码 Agent 报告完成后,还要评估什么
文章以支付服务开发为例,说明 Agent 自报完成或测试通过并不足以证明任务正确。评估还应覆盖服务定位、架构遵循、权限验证、修改范围、测试执行和工具使用。
AI 深度解读
编码 Agent 回复「实现完成,测试全过」,只能证明它给出了完成声明。它可能找错服务、漏掉权限校验,甚至根本没执行测试。原文讨论的 Evals,就是把这些疑问变成可重复执行的检查。
作者的主张很明确:判断 Agent 是否可靠,要同时看结果、执行过程,以及更换模型或提示词后能否保持稳定。文章给出了一套 TypeScript 入门思路,但没有真实团队的对照实验。值得带走的是评估方法,而不是把示例分数当成效果证明。
「测试通过」为什么还不够
传统单元测试通常有明确的输入和预期输出。原文用 calculateCreditCardLimit(10000, 5000) 举例,预期结果是 5000。但让 Agent「找到信用卡额度更新实现」,合法路径可能有很多:从接口入口找,从 controller 找,或者先搜索 service,都可能正确。
所以,评估不该要求它逐步复刻标准答案,而应检查两件事:有没有达到目标,采取的行动是否合理。
这也解释了 Evals 与单元测试、集成测试、端到端测试的关系。后者检查程序行为,前者还要检查 Agent 能否稳定地产出值得验证的代码,以及有没有遵守任务边界。
原文设计了四个案例:CC-001 查找实现,CC-002 增加授权校验,CC-003 修复非法额度被接受的问题,CC-004 解释 BFF、API 与 service 的调用关系。查找和解释任务要求 mustNotModifyFiles: true;实现和修复任务要求 testsRequired: true。
任务不同,合格标准就不同。解释代码时顺手改文件,即使改得没错,也越过了任务边界。
作者还建议加入需求不完整、API 文档缺失、MCP 超时、仓库存在多份实现、已有测试失败、两个 Agent 修改同一文件,以及用户权限不足等情况。这些都是建议覆盖的场景,文章没有展示实际运行结果。
最有复用价值的做法,是把每次真实失败沉淀成固定评估案例。
能用代码确认的事,先别交给另一个模型
作者把评估分成两类:能明确判断的事情用代码检查,难以固定答案的事情再考虑模型评分。
下面这段代码检查文件改动和测试调用记录,用来拆穿一句笼统的「完成了」:
type AgentResult = {
modifiedFiles: string[];
toolCalls: string[];
testsPassed: boolean;
};
function evaluateCreditCardFeature(result: AgentResult) {
return {
correctServiceModified: result.modifiedFiles.some(
file => file.includes("payment-service")
),
testsAdded: result.modifiedFiles.some(
file => file.endsWith(".spec.ts")
),
testsExecuted: result.toolCalls.includes("run_tests"),
testsPassed: result.testsPassed
};
}
要重点看 testsExecuted 和 testsPassed:调用过测试工具、测试确实通过,是两个不同条件。不过,这段示例还远远不能证明功能正确。路径包含 payment-service 不代表修改位置正确;改过 .spec.ts 不代表新增了有效断言;代码也没有检查持卡人身份校验是否真的生效。
原文进一步强调,评估器应独立执行验证命令:
yarn nx test payment-service
yarn nx run payment-service:lint
yarn nx run payment-service:build
这里关键的是由评估器执行这三行,并采集执行结果。仅从 Agent 自述中读取 testsPassed,仍然没有跳出「相信它说了什么」的循环。
工具使用也能做规则检查。原文列出的工具包括 search_jira、search_repository、read_file、get_api_documentation、run_tests 和 create_merge_request。对于查找并解释实现的任务,可以要求必要的读取工具,同时禁止 create_merge_request。
原文的 evaluateToolUsage 只检查必需工具是否缺失、禁用工具是否出现,不强制调用顺序。这比锁死整条执行路线更合理。不过,如果上下文已经包含目标文件,硬性要求再搜索一次,也可能误判,需要按任务设置规则。
答案正确,还要看它怎么得到答案
原文用执行轨迹(trajectory)描述 Agent 完成任务的行动序列。同样一句「完成」,背后可能是定位服务、阅读文档、修改代码、运行测试并修复失败;也可能是读取 35 个无关文件、重复搜索、调用 MCP 工具 6 次,最后跳过测试。
作者给出的轨迹预算是:工具调用不超过 20 次、读取文件不超过 25 个、重试不超过 3 次、测试执行次数大于 0、耗时不超过 120_000 毫秒、token 不超过 30_000。这些数字明确只是示例,不能直接当团队标准。查找代码和跨文件实现功能,消耗本来就不同。
对于架构解释这类开放答案,作者建议用 LLM-as-a-Judge:把任务、参考事实和回答一起交给裁判模型,按技术正确性、完整性、相关性、无依据假设四项打 0-5 分。示例结果分别是 4、3、5、1,理由是遗漏了所有权校验。但「无依据假设」究竟高分更好还是更差,提示词没有说清,实际使用前必须明确。
RAG 则需要拆开检查检索和生成。原文以返回五篇文档为例:预期三篇,只找回一篇,Recall@5 = 1/3;返回的五篇中两篇相关,Precision@5 = 2/5。MRR 关注首篇相关文档的位置,但原文只举了排在第二位的情形,没有完整展开计算。答案碰巧正确,不能证明检索可靠。
多 Agent 工作流还要检查协作:Frontend Agent 是否等到了 API 契约,Review Agent 是否审查最新代码,两个 Agent 有没有同时修改一个文件。单个角色得分高,无法保证整个流程正确。
这些检查最终要进入回归流程。模型、prompt、工具、上下文策略或编排逻辑变化后,重新跑相关任务,才能发现「后端表现改善,前端却开始多改文件」这样的退步。
我的判断
我认同作者把结果检查、过程检查和回归评估放在一起。相比只看演示,或者只看最终代码能否通过测试,这套方法更容易发现工具误用和任务越界。
但文章主要是方法示例,没有给出通过率提升、成本下降或不同模型之间的对照数据。提到用同一套任务比较本地 Qwen 与其他编码模型,也只是提议,不能理解为已经验证过的结论。
评估结果能否可信,首先取决于证据从哪里来。
工具日志、文件差异、命令退出状态,应来自执行环境的实际记录。若这些字段仍由 Agent 自己填写,结构化 JSON 只是把自述换了一种包装。
原文的小型 runner 也有这个边界:evaluateCase 检查必需工具、禁用工具和文件修改限制;runEvaluation 汇总 successRate、averageTokens 等数据。虽然 AgentExecution 定义了 testsPassed,评估函数并没有断言它。因此,示例里的 passed 只表示已有规则通过,不能等同于功能验收通过。
作者也承认,生产环境还需要隔离工作区、测试结果断言、执行超时、结构化轨迹、重复运行和错误分类。对于可以直接运行验证的条件,确定性检查更合适;对于解释质量,模型裁判可以补位,但关键权限逻辑仍需明确断言和人工审查。
文章列出的 promptfoo、openai/evals、inspect_ai 可以作为后续调研入口。原文没有版本和实测记录,选型时仍需确认它们是否覆盖自己的执行环境。
能拿来做什么
- 从日常 AI 编程任务中挑选查找代码、修复缺陷、增加功能、解释调用链几类案例,分别写清允许改什么、必须验证什么,再把真实失败持续补进去。
- 给前端或 Node 仓库的 Agent 接上独立验证步骤,采集实际文件差异、测试结果、lint 和 build 结果,让完成声明对应到可检查的证据。
- 对只读任务设置文件修改限制和工具禁用规则;对实现任务记录测试执行情况,再按任务复杂度观察耗时、token 和无关文件读取。
- 每次调整模型或系统提示词,都在同一批任务上比较结果,并重复运行观察波动;如果使用模型裁判,先写清评分方向和参考事实。