第 32 章 · Agentic Coding
一个“帮我改代码”的下午
那个卖家的技术合伙人这次来了。他管着团队自研的一套跨境 ERP,里面有个老功能:把亚马逊后台导出的订单 CSV 解析进库。最近换了新的报表格式,解析器时不时报错,他没空细看,扔给 Agent 一句:“订单导入偶尔崩,你去查查,顺手修了。”
普通的代码补全工具帮不上这个忙——它能替你补下一行,却读不懂整个仓库、跑不了测试、看不到报错。而一个真正的编码 Agent 会这样做:先 grep 出解析相关的文件,读懂现有逻辑,写一个能复现崩溃的测试,跑,看报错,改代码,再跑,直到测试变绿,最后告诉你:“根因是新格式多了一列表头,旧的按列序取值就错位了。”
这就是 Agentic Coding(智能体编程)——让 Agent 在真实代码库里独立完成“读—改—验证—修复”的完整闭环。而 pi 恰恰本身就是一个 Agentic Coding 工具,所以这一章我们讲的不是“用 pi 搭个编码 Agent”,而是“pi 自己是怎么做到的”。
编码为什么特别适合 Agent:真实反馈
Agentic Coding 效果好,是因为编程有一个别的领域羡慕不来的东西:廉价、客观、即时的反馈(feedback)。
回顾第 14 章的反思(Reflection)——最有效的反思来自真实反馈,而不是让模型自己“觉得”对不对。编码恰好把这种反馈免费送到手上:
- 编译器 / 类型检查(type check):代码写错了,
tsc、cargo build当场报错,精确到行。 - 测试(test):逻辑对不对,跑一遍单测立见分晓,红变绿就是硬指标。
- Linter:风格、隐患,工具替你挑出来。
- 运行时输出:跑一下,行为不符预期,报错栈直接指路。
把这些接进 ReAct 循环(第 3 章),就得到一条带真实反馈的 ReAct——这正是 Agentic Coding 的模式内核:
Thought → 我需要给 CSV 解析加一个表头校验
Action → 编辑 parseOrders.ts
Action → 运行测试 npm test parseOrders
Observation → 2 个测试失败:TypeError: cannot read 'city' of undefined
Thought → 哦,新格式列错位了,我按列名取值而不是列序
Action → 改成按 header 映射,再跑测试
Observation → 全部通过 ✅
这里的关键在于:Observation 不是模型脑补的,而是编译器、测试真刀真枪跑出来的。模型没法自欺,错了就是红的。这就是 Agentic Coding 比很多其他 Agent 应用更可靠的根本原因——它把“对不对”这件事外包给了客观世界。
编码 Agent 的一天:闭环怎么转
把上面的模式展开成一个真实任务的完整轨迹,感受一下这个闭环:
Thought → 先定位订单导入的代码在哪
Action → grep -r "parseOrders" src/
Observation → src/import/parseOrders.ts,被 import/index.ts 调用
Thought → 读懂现有解析逻辑
Action → read_file: parseOrders.ts
Observation → 用 row[3] 硬取 city,依赖固定列序
Thought → 写个能复现崩溃的测试,锁住 bug
Action → 新建 parseOrders.test.ts,喂新格式 CSV
Action → 运行测试
Observation → 果然崩在 row[3],复现成功
Thought → 改成按表头名映射列,不再依赖列序
Action → 编辑 parseOrders.ts + 跑测试
Observation → 全绿 ✅
Answer → 根因:新报表多了一列,旧代码按列序取值错位。
已改为按 header 名映射,并补了回归测试
注意“先写一个复现测试再改”这一步——它把模糊的“偶尔崩”变成了一个客观、可重复的红灯。这是编码 Agent 的老练之处:先让反馈信号变清晰,再动手,改完还留下一道回归测试防止复发。
用 pi 实现:pi 本身就是答案
pi 的 @earendil-works/pi-coding-agent 就是一个交互式编码 Agent CLI。它不是“用某个框架搭出来的示范”,而是把全书的模式集于一身的活样本:
| 全书模式 | 在 pi 编码 Agent 里的体现 |
|---|---|
| ReAct 循环(第 3 章) | 读代码 → 改 → 跑测试 → 看结果 → 再改 |
| 工具(第 4 章) | 文件读写、shell 执行、grep、运行测试 |
| 技能(第 7 章) | dev-browser 等按需加载的工作流 |
| 扩展 / Hooks(第 8 章) | 危险命令确认、git 检查点、路径保护 |
| 上下文压缩(第 9 章) | 长编码会话自动 compaction |
| 记忆(第 10 章) | memory 扩展记住项目约定 |
| 会话树(第 12 章) | 改错方向可回溯、可分叉重试 |
| 规划(第 13 章) | 复杂改动先列待办清单 |
| 反思(第 14 章) | 靠测试/报错自我纠错 |
真正让编码闭环转起来的,是 pi 把“运行命令、看输出”做成了第一等能力。概念上,一个“跑测试并把结果作为 Observation 回填”的工具大致长这样:
// 概念示意:把测试结果变成可被模型消费的反馈信号
pi.registerTool({
name: "run_tests",
description: "运行项目测试,返回通过/失败数与失败详情,供 Agent 自我纠错",
parameters: {
type: "object",
properties: {
filter: { type: "string", description: "只跑匹配的测试,如 parseOrders" },
},
},
async execute({ filter }) {
const { stdout, stderr, code } = await sh(`npm test ${filter ?? ""}`);
return {
passed: code === 0, // 客观信号:绿还是红
output: truncate(stderr || stdout, 4000), // 截断,别撑爆上下文
};
},
});
模型拿到 passed: false 和报错文本,就会在下一轮 Thought 里定位、修复、重跑——闭环由此自动运转,不需要人来判断对错。这也是为什么全书用 pi 做参考:你学的每个模式,都能在它身上看到能读源码的落地。
动手看看
打开 pi-coding-agent 的源码,找到它内置的 shell / 文件工具,看看它们的 description 是怎么写的——尤其是“跑命令看输出”这一类工具,如何把外部世界的反馈规整成模型能消费的 Observation。
再做个小实验:在一个有测试的小项目里,故意改坏一个函数让测试挂掉,然后让 pi “修一下测试”。全程盯着它的轨迹,数一数它跑了几次测试、每次报错后 Thought 怎么变——你会直观看到“带真实反馈的 ReAct”到底长什么样。
实战中的几个坑
坑一:不给它跑测试的能力,它只能靠猜。
- 现象:Agent 改完代码信誓旦旦说“应该好了”,实际没验证过,一跑还是错。
- 原因:没给它执行测试/编译的工具,反馈闭环断了,退化成“只推理不观察”。
- 对策:务必提供跑测试、编译、类型检查的工具,让客观信号回到循环里。
坑二:一次改一大堆,错了不知错在哪。
- 现象:Agent 同时改五个文件,测试全红,越修越乱。
- 原因:步子太大,反馈信号无法定位到具体改动。
- 对策:小步快跑——改一小块、跑一次测试,绿了再往前,把每次反馈锁定到一处。
坑三:报错输出太长,撑爆上下文。
- 现象:一次编译失败刷出上千行报错,全塞回对话,几轮就把上下文顶满。
- 原因:工具没截断就把 stderr 原样回填。
- 对策:在工具里截断/摘要(如只留前 N 行 + 失败计数),配合上下文压缩(第 9 章)。
坑四:危险操作没设门,自动化程度一高就出事。
- 现象:Agent 为“清理干净”跑了
git reset --hard或rm -rf,误删未提交的改动。 - 原因:高风险命令没有确认或拦截,隔离也没做。
- 对策:用扩展在
beforeToolCall拦危险命令(第 8 章)、用 git 做检查点、自动化程度高时在容器里跑(第 28 章)。
对比:其他框架
Agentic Coding 是一种形态:让 Agent 在真实代码库里读写文件、跑测试、看编译反馈自我纠错。它更多由专用编码 harness(Claude Code、Cursor、Aider、OpenHands)承担;通用 Agent 框架并非为编码而生,但都能把编码工具接进各自的编排里。
| 框架 | Agentic Coding 怎么做 | 特点 |
|---|---|---|
| LangGraph | 不内建编码能力,但能把“改代码→跑测试→读反馈→再改”画成带循环的状态图,反馈作条件边 | 控制显式,需自己接工具 |
| CrewAI | 组“程序员+审查者”团队按角色推进,真实文件读写/测试执行需接外部工具 | 角色分工直观,无原生 harness |
| PydanticAI | 强在让模型返回类型化补丁/操作再由你落盘,不提供编码 harness 本身 | 结构化输出稳,闭环靠自己织 |
| Agno | 挂文件/shell/测试类工具可搭简单编码 Agent,紧密纠错循环仍需自织 | 工具生态全,非编码专用 |
| pi | pi-coding-agent 本身就是开源、可读源码的编码 harness,工具/技能/扩展协作可见 | 一等公民,最佳学习样本 |
共性:编码可靠的根本在“真实反馈”(编译、测试、类型检查),不在框架;差别在于是否为编码这一形态预置了紧密的读写—验证循环。
小结
- Agentic Coding 是“带真实反馈的 ReAct”:编译器、测试、类型检查(type check)提供客观、即时的反馈信号,让 Agent 自我纠错——这是它比多数 Agent 应用更可靠的根本原因。
- 编码 Agent 的老练做法是先让反馈信号变清晰再动手:写复现测试锁住 bug,改完留回归测试防复发。
- pi 的
pi-coding-agent本身就是全书模式的集大成实现,可读源码,是最好的学习样本。 - 关键实践:让它跑测试、小步快跑、报错截断、危险操作设门、隔离环境运行。
- 反馈闭环一旦断了(没给它跑测试的能力),编码 Agent 就退化成“只推理不观察”——闭环是它的命根子。
Agentic Coding 通常是“你盯着它干”。下一章看当 Agent 不需要你盯着、在后台自主运行时会发生什么——Background Agents。