Agentpath
原理26 / 31 节 · 预计 35 分钟

编码 agent:改代码要闭环

会写代码不难,难的是改完自己验证。测试就是编码 agent 的眼睛。

学完这节你能做到

  • 设计一条「改动 → 验证 → 修正」的闭环,并让 agent 自己跑完
  • 在整文件重写与精确补丁之间做出选择
  • 为大仓库设计定位代码的检索策略

写代码不难 —— 模型一直都会。难的是改完自己知道对不对。 一个没有验证闭环的编码 agent,本质上是在猜。

闭环的三段

定位 ──→ 编辑 ──→ 验证
  ↑                 │
  └──── 失败回灌 ────┘

三段都做好才有闭环。缺了验证,你得到的是「看起来合理的 diff」; 缺了失败回灌,它第一次没改对就卡住了。

定位:在大仓库里找到该改的地方

工具就那几个:grepfindreadls。差别在策略:

场景顺序
有报错信息从堆栈的文件行号直接 read → 往上找调用方
有功能描述grep 关键词(UI 文案、路由、常量名)→ 顺依赖找
要改一类模式grep 出全部命中 → 先数量后明细 → 分批改
完全陌生ls 顶层 + read README + package.json → 建立骨架认知

最容易出事的是第三类:grep 出 200 处,全量塞进上下文,一次改完 —— 窗口撑爆、改错了也回不去。正确做法是先要数量和分布,再分批。

大仓库定位派子 agent 最划算

「这个功能在哪实现」这种问题,翻十几个文件才能得出一句结论 —— 中间过程主 agent 完全不需要。这是 L2 讲的 sub-agent 的最佳场景。

编辑:整文件重写 vs 精确补丁

整文件重写(write精确补丁(edit
token 成本高:要输出整个文件低:只输出改动片段
出错方式容易漏掉没读到的部分定位串了会改错地方
大文件很容易超输出上限无压力
适合新建文件、小文件、结构性重写绝大多数改动

Pi 的 edit 工具在 details.patch 里给出统一格式的 patch(给 SDK 消费方), details.diff 给 TUI 渲染 —— 又是 content / details 分离的例子。

×精确补丁的经典失败

「把这个字符串替换成那个」在文件里有多处匹配时,改错位置。 所以补丁工具应该:匹配不唯一时报错并列出全部候选,而不是默默改第一处。 这条规则能挡住编码 agent 最常见的一类静默错误。

并行修改还有个坑:同一个文件被两个工具调用同时改。Pi 的答案是 withFileMutationQueue(absolutePath, ...),把读-改-写整个窗口串行化。 自己写编辑类工具时照抄。

验证:agent 的眼睛

按「反馈速度 ÷ 可信度」排,agent 应该优先用快的:

手段速度覆盖
语法/类型检查(tsc --noEmit秒级类型与拼写
lint秒级风格与低级错误
单测(相关文件)十秒级逻辑
全量测试分钟级回归
构建分钟级集成

在 AGENTS.md 里把这个梯子写清楚,收益极高:

## 验证梯子(按顺序)
1. `bun run typecheck` —— 每次改完必跑,10 秒
2. `bun test <改动涉及的文件>` —— 逻辑改动时跑
3. `bun run build` —— 只在改了构建配置或依赖时跑(3 分钟,别乱跑)
!测试本来就是红的

真实仓库里经常有一批长期失败的测试。agent 不知道这件事, 会花很多轮去「修」一个和它无关的失败。 在 AGENTS.md 里写明「这些测试本来就挂,别管」,或者让验证命令只跑相关子集。

失败回灌:把报错原样喂回去

这是编码 agent 最有效的一环,也是最容易做砸的:

✅  tsc 的完整报错(文件:行:列 + 消息)—— 原样给
✅  测试失败的断言消息 + 期望/实际 —— 原样给
⚠️  完整的 200 行堆栈 —— 截断,保留最上面的应用栈帧
❌  「构建失败」四个字 —— 等于没说

一个实用技巧:报错超过 N 行时,保留头尾。 头部有具体错误,尾部常有汇总(「3 个测试失败」)。中间的重复堆栈可以省掉。

大改动:分步且随时可停

「把这 40 处调用都改成新 API」不该一轮做完。分步的三个理由: 上下文撑得住、错了容易回滚、人能中途叫停。

推荐节奏:

1. 先改 1 处 → 验证 → 确认方案对
2. 按目录/模块分批,每批改完就验证
3. 每批之后报告进度(改了几处、还剩几处)
4. 遇到不确定的(比如某处语义确实不同)停下来问,而不是自作主张

第 4 条要写进提示词。默认行为是模型倾向于「硬着头皮做完」, 而在重构里,一处自作主张的语义变更可能几个月后才暴露。

交出去之前

编码 agent 的产出必须能被人审。三条硬要求:

  1. 改动可 diff —— 别在版本控制之外改文件。
  2. 改动范围可预期 —— 「改这一处」就别顺手格式化整个文件 (在 AGENTS.md 里明确禁止无关格式化)。
  3. 说清做了什么、没做什么 —— 包括「有 3 处我没改,因为它们的语义确实不同」。
检查点单选

编码 agent 改完代码就报告完成,但用户经常发现根本没编译通过。最该先补哪一环?

这一节的结论

  1. 定位 → 编辑 → 验证 → 失败回灌,缺一段就不是闭环。
  2. 大范围搜索先要数量和分布,再取明细;定位类任务适合派子 agent。
  3. 补丁优于重写;匹配不唯一时必须报错,不能默改第一处。
  4. 验证梯子按秒级 → 十秒级 → 分钟级排,写进 AGENTS.md。
  5. 报错原样回灌(长的保留头尾);大改动分步、随时可停、不确定就问。

延伸资料