第 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):代码写错了,tsccargo 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 --hardrm -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,紧密纠错循环仍需自织工具生态全,非编码专用
pipi-coding-agent 本身就是开源、可读源码的编码 harness,工具/技能/扩展协作可见一等公民,最佳学习样本

共性:编码可靠的根本在“真实反馈”(编译、测试、类型检查),不在框架;差别在于是否为编码这一形态预置了紧密的读写—验证循环。

小结

  1. Agentic Coding 是“带真实反馈的 ReAct”:编译器、测试、类型检查(type check)提供客观、即时的反馈信号,让 Agent 自我纠错——这是它比多数 Agent 应用更可靠的根本原因。
  2. 编码 Agent 的老练做法是先让反馈信号变清晰再动手:写复现测试锁住 bug,改完留回归测试防复发。
  3. pi 的 pi-coding-agent 本身就是全书模式的集大成实现,可读源码,是最好的学习样本。
  4. 关键实践:让它跑测试、小步快跑、报错截断、危险操作设门、隔离环境运行
  5. 反馈闭环一旦断了(没给它跑测试的能力),编码 Agent 就退化成“只推理不观察”——闭环是它的命根子

Agentic Coding 通常是“你盯着它干”。下一章看当 Agent 不需要你盯着、在后台自主运行时会发生什么——Background Agents。