Skip to content

用嘴编程会腐烂:把 AI 编码变成有护栏的工程

第二部 · Agent 实践 · 第23章

撰写日期:2026-07-07

结论

“随便和 AI 说几句就能跑出一个程序”只在玩具项目里成立。项目一复杂,AI 犯错概率就随代码量上升——这里改好、那里就坏,最后花掉大量 token,程序勉强能跑,代码却已经没人能读懂,连“还能不能继续加功能”都说不准。

根因不在模型不够聪明,而在两点:一是需求本来就没想清楚,二是所有代码都堆在同一段越来越长的上下文里。前者靠先对齐再动手解决,后者靠把知识沉到文件、让每次会话只做一件小事解决。

这篇把一次“从零让 AI 写一个 FC 模拟器”的公开实践,抽象成一套可复用的结构化 AI 编码方法。它对 AI 产品经理有两重价值:既是自己驾驭 AI 编码的工作流,也是设计“AI 写代码类产品”时可以照搬的产品结构。

为什么长上下文会让质量崩塌

这是理解整套方法的前提。AI 写出的代码都活在上下文里,项目一大,上下文窗口越拉越长——不仅又慢又贵,更危险的是窗口逼近上限时模型会自动总结压缩历史,而压缩很可能把正在编写模块的关键细节丢掉,于是越写越容易出 bug。

失效环节表现对策
需求模糊AI 写出的东西总差一口气,反复改成一堆烂代码先用文档把需求钉死,再动手
上下文膨胀越写越慢越贵,模型开始忘细节每个会话只做一件事,做完就清
自动压缩丢信息总结历史时丢掉正在写的模块细节关键信息落到文件,不依赖聊天历史
弱类型语言太灵活AI 自由发挥引入隐性错误用类型检查 + 单测做强约束

核心机制:文档即上下文

整套方法只有一个中心思想——把每一步的成果浓缩进文件,让下一步在干净的新会话里、基于文件而不是聊天历史继续工作

这样做同时解决三件事:省 token、防止模型幻觉、让任何一步都可以随时换个新会话重来。它和 Agent Workflow 与评估 里“可恢复”的要求是同一件事的两种说法:状态不在对话里,在文件里。

阶段落地文件这一步只回答
需求proposal.md到底要做什么
概要设计需求文档内的“功能需求”章节分成哪些模块、模块间什么关系
详细设计每模块一份设计文档每个模块具体怎么实现
任务拆分每模块一份任务清单 + 总 progress.md做到哪了、还差什么
实现每模块一个代码文件 + 一个测试文件按设计和任务把代码写出来

四步流程

text
需求 (proposal.md,让 AI 主动提问)
  -> 概要设计 (划分独立模块)
  -> 详细设计 (每模块一份,新会话)
  -> 任务拆分 (每模块 checklist + progress.md,新会话)
  -> 实现 (监工 Agent 派发子 Agent,每模块独立上下文)

每一步之间都开新会话:因为上一步的讨论成果已经沉到文件里了。这条纪律贯穿始终,是控制上下文长度的根本手段。

四步共用一个提问结构(目标 / 输入 / 输出 / 步骤),并在不确定的步骤让 AI 主动向人提问——这部分作为可复用模板单独整理,见 结构化编码的四段式 Prompt

监工 Agent + 子 Agent 架构

实现阶段是上下文压力最大的地方。最直觉的做法——把整份任务清单塞给一个 Agent 顺序实现——恰恰最糟:整个程序都挤在同一个上下文里,必然触发多次压缩,质量难保、花费还高。

更好的结构是分层:

角色职责上下文特征
监工 Agentprogress.md,为每个模块派发子 Agent,跟踪整体进度只装进度,不装实现细节,始终短
子 Agent × N各自负责一个模块的实现、单测与验证只装自己模块的设计和任务,互不干扰

关键约束:整个实现过程全自动、无人参与,人唯一能下命令的时刻,是监工 Agent 最开始收到的那个 prompt。所以这个 prompt 必须同时写清监工做什么、每个子 Agent 做什么,会相当复杂——复杂到它本身也值得让 AI 来生成(用一个“生成 prompt 的 prompt”,见上面链接的模板文档)。

这和 Agent 产品操作系统 的分层思路一致:把长任务切成互不污染的短上下文,是多 Agent 协作最实在的收益,而不是“Agent 数量多”本身。

质量护栏:每行代码都要有测试和类型检查

弱类型语言(Python/JS)灵活,AI 又爱自由发挥,两个不确定性叠加,光靠“看起来对”兜不住。所以在写第一行业务代码之前,护栏就要立好:

护栏作用何时立
类型检查(如 mypy)运行前抓出类型层面的逻辑错误建工程时就装好
语法/风格检查(如 ruff)统一风格,挡低级错误建工程时就装好
单元测试(如 pytest)每个模块一个测试文件,覆盖每行代码写代码时同步生成

要求写进监工 prompt:每一行代码都要有对应单测,并且必须通过类型检查和语法检查,子 Agent 才算完成一个模块。上面那次实践最终产出了每模块一个代码文件 + 一个测试文件、近两百个测试全通过的结果。

测试和类型检查真正的价值不在“证明现在是对的”,而在未来加新功能时不破坏旧功能。没有这层回归防线,AI 每加一个特性都可能悄悄弄坏另一个——这正是“用嘴编程”最后代码腐烂的机制。

顺带一个语言选择的产品判断

“用什么语言”对 AI 编码不是中立选择,而是一个可以列清楚的权衡:

取向收益代价
选 AI 最擅长的语言(Python/JS)模型训练语料多、第三方库全,少造轮子、少幻觉语言本身弱类型,需外挂类型检查补安全
选强约束语言(如 Rust)语法严格带来的安全性AI 生成的熟练度低,连编译通过都更费劲

我的判断是:既然代码由 AI 写,就优先选它最熟的语言把“写得出、写得对”的概率拉满,再用类型检查和单测把弱类型丢掉的安全补回来——把安全从“语言默认给”转成“工程流程给”,比让 AI 硬啃不擅长的语言更划算。

我的判断

这套方法看起来是编码技巧,本质是 Context 管理:它把“别让上下文太长”这条抽象原则,落成了一套具体动作——分步、落文件、开新会话、分层派 Agent、立测试护栏。

对 AI 产品经理,有两点可直接迁移:

  1. 面向自己:任何交给 AI 的复杂任务,都值得先问“状态存在对话里还是文件里”。存在文件里,任务才可拆、可恢复、可换会话重来。
  2. 面向产品:设计 AI 生成类产品(写代码、写文档、做设计)时,真正的壁垒不是调一次模型有多强,而是有没有这套“需求文档 → 设计 → 任务 → 分层执行 → 自动验证”的结构在背后兜底。模型会一直变强,但可拆解、可验证、可持续迭代的工程结构,才是产出质量长期变好的基础。

相关

MIT License