从零构建 Coding Agent
English

15. 评测、调试与最终项目

Agent 开发最大的错觉是“刚才那次看起来能跑,所以它是对的”。模型输出不稳定,真实仓库复杂,工具和上下文状态很多。如果没有评测和调试体系,你会在每次改 prompt 或工具描述后重新手工试一遍,而且无法判断退化来自哪里。

三层测试

教学项目至少需要三层测试:

  • 单元测试:工具参数校验、路径解析、输出截断、写队列。
  • Loop 测试:faux provider 驱动 tool use、错误回传、steering、压缩。
  • 回放测试:读取一段会话日志,重建上下文,验证投影结果。

真实模型端到端测试只做 smoke。它可以告诉你系统能连通,但不适合作为主要回归测试。主要回归必须确定、便宜、可重复。

会话回放

会话日志天然是调试材料。一次失败任务可以导出为 JSONL,测试 harness 读取后重建 active branch,断言:

  • 上下文里是否包含该有的系统规则。
  • 压缩摘要是否保留关键事实。
  • 最后一个 tool result 是否正确进入下一轮。
  • 模型切换是否影响后续请求。
  • 分支 leaf 是否指向预期 entry。

这比截屏或人工描述 bug 更可靠。

成本与性能

Agent 应该统计每次模型请求的 usage、耗时、工具耗时和重试次数。没有这些数据,你无法回答“为什么这个任务花了这么久”或“哪个模型最贵”。成本信息可以作为事件和 session entry 记录,不必每次都进入模型上下文。

常见指标:

  • input tokens。
  • output tokens。
  • cache read/write tokens。
  • provider latency。
  • tool latency。
  • retry count。
  • compaction count。
  • estimated cost。

最终项目:tiny-agent

最终项目不是复刻某个现成产品,而是证明你理解 Agent 工程边界。选择一个小型 TypeScript 仓库,让 tiny-agent 完成一次真实修改:

  1. 读取用户目标。
  2. 搜索相关文件。
  3. 读取目标文件。
  4. 精确编辑实现。
  5. 运行指定检查命令。
  6. 根据失败继续修正。
  7. 生成最终摘要。
  8. 写入完整会话日志。
  9. 退出后恢复会话,说明刚才做了什么。

验收时不要只看最终代码是否正确,还要看过程是否可审计。

Capstone 验收清单

你的 tiny-agent 需要满足:

  • Provider 可替换,至少有真实 provider 和 faux provider。
  • Tool call 由 stop reason 驱动,不靠硬编码步骤。
  • 工具参数校验失败会回喂模型。
  • read/edit/write/bash 都有路径边界和截断策略。
  • 写操作有 diff details 和模型摘要分离。
  • 会话日志是追加式 JSONL。
  • 恢复后不重新执行历史工具。
  • 压缩不删除历史,只改变上下文投影。
  • steering 和 follow-up 有独立队列。
  • JSON 模式 stdout 只输出机器可读事件。
  • 权限门在所有运行壳中一致生效。
  • faux provider 测试覆盖至少一个工具错误自我修正场景。

调试手册

当 Agent 行为异常时,按这个顺序查:

  1. 看 session log,确认事实是否写入。
  2. 看 context projection,确认发给模型的内容是否正确。
  3. 看 provider adapter,确认 stop reason 和 tool call 是否转换正确。
  4. 看 tool result,确认错误是否可修正。
  5. 看系统提示词,确认规则顺序和冲突。
  6. 最后再怀疑模型本身。

这条顺序很重要。很多“模型不听话”的问题,其实是上下文投影漏了约束,或者工具错误写得不可行动。

结束语

构建 Coding Agent 的核心不是找到一段神奇 prompt,而是把一个不确定的模型放进确定的工程边界里:协议清晰,工具受控,状态可恢复,事件可观察,权限可审计,扩展有边界。做到这些之后,模型能力提升会自然变成系统能力提升;否则模型越强,系统越难控制。