宋桧铭
← 文章

高效高质的 Coding Agent 工程开发流

高效高质的 Coding Agent 工程开发流

 刚接触 Coding Agent 时,我只会往对话框里扔模糊的自然语言需求。当时不会管理 context,没有项目结构的概念,甚至不会用 git。代码被生成得很快,但 context 一乱,模型就开始忘约定,改东坏西。
 
 几个月高强度使用 Coding Agent 后,我把日常开发收敛成了一套固定流程。这套流程的核心只有一条,管理好 context。context 是 Agent 的眼睛和记忆。
 

用追问代替手写需求

 人手写初始需求,容易漏掉异常分支和边界条件。你不写清楚,Agent 实现时就会瞎猜。
 
 立项第一步不要自己硬写文档,建议直接使用 grill-me Skill,给出一两句核心目标,剩下的边界全部交给 Agent 对你进行追问。
 
 grill-me 的执行规则很硬朗。Agent 会沿着决策树逐一排查存在依赖关系的设计分支,向用户询问问题,并给出它的推荐方案。能通过检索本地环境或查文档确认的客观事实,Agent 会自己查清;涉及架构取舍的决策,会交由人拍板。
 
 grill-me:https://github.com/mattpocock/skills
 

按施工阶段拆分 Spec

 有了需求文档后,调用手里推理能力最强的模型编写 Spec 文档。
 
 不要试图让模型一口气写出一份大而全的终极 Spec。单份文档过长,模型自身会出现前后契约冲突,后续施工加载可能会撑爆 context window。
 
 我建议的做法是按施工里程碑拆分,大概有几个施工阶段就写几份独立的 Spec。每份 Spec 只定义当前阶段的模块边界、数据结构与验收标准,单次加载体量可控,职责清晰。
 

动工前对 Spec 做对抗性审查

 模型写出的 Spec 表面结构工整,但往往只覆盖了理想路径,可能藏着大量模糊地带和架构隐患。如果各阶段 Spec 存在严格依赖,建议每写完一份就拉起一轮对抗性 Review,改到终版再推进。(不要害怕改的轮数多,我最多改到过 19 版)
 
 对 Spec 做对抗性审查,核心是盯着以下四个要害。
 
 第一是跨阶段与跨模块的闭合。既然把 Spec 拆成了多个施工阶段,那么最致命的隐患就是上下游脱节。审查时要逐一核对当前阶段产出的数据结构、状态机流转、接口签名与落盘格式,确认下一阶段能否直接消费。 Spec 里如果出现由上游保证数据合法、后续阶段再补充处理等模糊表述,需要打回修改。
 
 第二是异常分支与失败退路。模型写 Spec 会天然倾向于写正常跑通的路径。对抗性审查要逼问非正常状态,外部进程崩溃或超时怎么退出,写文件或改状态中途断电如何保证原子性,再次启动时如何从断点恢复等等。
 
 第三是模块边界与过度设计裁剪。模型容易在设计里塞入多余的抽象层,或者模糊调用边界,比如让界面层直接操作底层核心逻辑。审查时要强制收紧职责,砍掉当前阶段不需要的伪需求与过度封装,明确哪些模块只读、哪个模块是核心操作的唯一入口。
 
 第四是可机械执行的验收判据。Spec 里的交付标准不应该出现结构清晰、性能良好、覆盖所有异常这类空话。审查应该把每一条验收标准逼成确定性的机器判据,写明跑哪条命令、喂什么边界输入、断言什么返回结果。无法写成确定性测试断言的 Spec 条款,会让施工漏洞百出。
 

建立文档体系

 如果把所有文档一股脑塞进上下文,可能会污染 context window,导致模型注意力稀释、规范失去权威。文档体系的核心设计原则只有一条,用路由表实现上下文的按需加载。
 
 一套普适的 Agent 项目文档体系,建议拆成三层结构(仅供参考,按项目实际体量裁剪)。
 
 第一层是根目录的 README.md 与 AGENTS.md,分别作为人类与 Agent 的入口。README.md 面向人类,写明项目全貌、核心架构概览与快速上手步骤,方便人类随时掌握全局;AGENTS.md 面向 Agent,每次会话自动载入,尽量克制,放每时每刻都生效的全局铁律,包括项目定位、绝对不能碰的安全红线、常用测试与构建命令,以及一张文档地图。文档地图明确规定什么文件记什么内容、在什么时机去读,充当整个项目的路由表。
 
 第二层是运行态与开发态隔离。通过 docs/INDEX.md 做总入口分流。如果当前 Session 只是执行常规任务或日常维护,就只需要读取百行以内的精简操作总纲 WORKFLOW.md,或者按需加载 runbook/ 下的单步操作手册;只有在进行架构调整或新模块研发时,才允许进入 docs/dev/ 目录。把日常操作与底层研发物理隔离,能避免无关的架构背景干扰模型的执行判断。
 
 第三层是开发态文档按职能拆目录,谁施工谁按需读取。

  • plans/ 存放前一步通过对抗性审查的各阶段施工 Spec,动工时只加载当前阶段的文档。
  • adr/ 存放难以回头的架构决策记录,写明为什么做这个取舍、当时的实测依据是什么、推翻它的条件是什么。这能防止新开的 Session 不懂历史背景,把刻意设计的机制当成缺陷改回去。
  • issues/ 与 postmortems/ 分别记录当前未解决的系统卡点和历史事故复盘,改具体机制前先查历史踩坑记录,不在同一个地方犯两次错。

单阶段双 Session 施工

 正式写代码时,每个施工阶段固定开两个独立的 Session。一个 Session 按 Spec 写实现代码;另新开一个干净上下文的 Session,加载 code-review Skill 做对抗性审查。
 
 不要在写代码的同一个 Session 里让模型自审。写代码的 Session 里是它刚才生成代码时的隐含假设,用同一个上下文自己审自己不叫审查,算是套了个命令外壳的自认确认。新开的审查 Session 最大的预设前提只有一个,前一个 AI 写出的代码和测试在某个角落自圆其说地撒了谎、在代码库里拉了屎。
 
 参考:https://www.aihero.dev/skills-code-review
 
 对抗性代码审查不抓缩进、格式化这类 Linter 能干的事,核心沿着三个维度。
 
 第一维是对照 Spec 查有没有做对的事(Is it the right thing)。审查 Session 拿着当前阶段的 Spec 与代码 diff 逐条比对,主要看三个方面:Spec 要求的功能有没有漏实现或只做了半截、状态流转与逻辑是否偏离了 Spec 原意、以及模型有没有擅自写出超出 Spec 范围的冗余代码(Scope Creep)。每一条问题都要指认到 Spec 的具体条款。
 
 第二维是对照仓库规范查事情有没有做对(Is it built right)。即便代码功能跑通了,如果破坏了项目的模块分层和工程约定,照样不能合入。审查 Session 直接读取项目的 AGENTS.md 与架构设计文档,核查代码是否跨层调用、是否在界面层硬塞了核心业务逻辑、是否复制粘贴造了重复轮子,或者在改动一处逻辑时引发了霰弹式修改。这两个维度必须分开独立报告,绝不能因为代码写得规整就放过需求漏实现,也不能因为功能跑通就容忍架构腐化。
 
 第三维是猎杀运行时的隐蔽缺陷。针对 AI 写代码最高频的两类谎言下死手:一是端到端追踪新增的配置项与函数调用链,揪出声明了却从未在主流程中被读取的未接线死代码;二是清查所有异常捕获与分支兜底,把只打一行日志就静默返回默认值、掩盖运行时故障的吞错逻辑全部打回。
 
 这里还要注意一条实操铁律:不要让审查与修改陷入无限死循环。每次修改代码都会暴露出新的表面问题,主观的代码坏味道永远审不完。把审查报告当成线索清单,只修那些明确违反了 Spec 条款、破坏了仓库硬性架构规则或会导致运行时 Bug 的真问题,修完即止。
 
 还有一种情况要提前提防。如果当前阶段要动的改动特别冒险,比如大规模重构、换底层方案,别直接在 main 上开干,开一个 git worktree 隔离施工。

测试变异检验与真机验证

 不要轻信 Agent 跑完测试后给出的全绿结果。AI 写测试最爱干两件作弊的事,要立下两条规矩。
 
 第一,禁止看着代码输出抄答案。测试里的期望值,要根据 Spec 规则独立算出来,不能照抄代码的实际运行输出。
 
 第二,故意改坏业务代码,看测试会不会报错。如果业务代码已经改坏了,测试还是全绿通过,说明这批测试纯属摆设。
 
 任何检查都必须测真实产物,不能只测 Mock。没有实物,很多问题发现不了。

收口文档与代码的分叉

 功能合入后,最后一步是抹平文档与当前代码之间的分叉。
 
 许多项目的文档在立项后就不再更新,代码改了数轮,文档还停留在初版,下次新开 Session 时 Agent 读到过期文档,可能会按旧逻辑把代码改坏。设计有变时必须先改文档再改代码,阶段收工前再做一次全量核对。

用真实使用做最终验收

 测试全部通过,只证明代码在预设判据下没有出错。这个项目人能不能用得顺手,是另一回事。很多小毛病只有在人类真实使用时才会冒出来,按钮位置顺不顺手,操作步骤绕不绕,文案有没有说人话,某个边界场景下交互太复杂。这些东西 Spec 难以全部覆盖,测试也无法断言。
 
 所以每个施工阶段结束后,人类应该把项目当普通用户真实使用一遍。用的时候发现问题随手记进 issues/ 文档,一条记清现象、触发路径和期望表现就够了,不用当场分析根因。
 
 攒下来的 issue 有两种处理方式。特别扎手的小问题可以随时改,改完立即回到真实操作里验证,循环很快;不着急的问题攒一批,集中开 Session 批量修改,改完统一回归。
 
 如果攒下的问题已经不是修修补补的级别,说明项目进入了新的需求周期。这时别在 issue 循环里硬扛,回到流程第一步,重新走一遍 grill me、写 Spec、对抗性审查。这套流程不是只跑一遍就结束,每一轮迭代都要完整过一遍。

阶段节点必须由人类摸清架构

 人类没有精力、也没有必要去逐行审阅 Agent 生成的几万行代码。具体的函数实现和边界防守,我们交给双 Session 对抗审查和变异测试。
 
 在每个大阶段(例如 MVP)收工后、下一阶段启动前,我建议人类应该亲自搞清当前项目的整体架构。无论你是让 Agent 生成模块依赖图、顺着数据流讲解调用链,还是自己直接看目录树与接口定义,都要摸清数据从哪里进,状态存在哪里,核心路径的唯一入口是谁,以及模块间的调用边界在哪里。
 
 如果不做这一步,可能会给后续的迭代和升级带来隐性的困难和问题。因为当人类无法理解项目时,你就丧失了维护的能力,只能期待新的模型能力飞跃,这不是我们乐见的。


评论

1 评论

马
马嘉祺

贴主讲的太好了,已经用之~~

发表评论