规格驱动开发:2026年用AI写代码最狠的工作流
深入拆解 spec-driven development 的实操方法,讲清如何用结构化规格文件让 AI 编码代理一次写对,附完整示例和踩坑清单。
为什么”直接让 AI 写代码”总是返工
大多数人用 AI 写代码的方式是:开一个对话框,打一句”帮我写个用户登录接口”,然后看着模型吐出一堆能跑但不符合你项目规范、命名风格混乱、边界条件缺失的代码。
问题不在模型,在输入。你给的是一句模糊的自然语言,模型只能用它的”平均想象”填补所有空白,而你的项目有它自己的约定、架构、命名习惯——这些它根本不知道。
2026 年真正高效的做法,叫规格驱动开发(spec-driven development):先把需求写成一份结构化规格,再让 AI 代理照着规格实现。
规格文件长什么样
一份好的规格不是”需求文档”,而是可执行的合同。它至少包含五块:
1. 目标与范围 —— 这个功能要解决什么问题,不解决什么
2. 接口契约 —— 输入输出、类型、错误码,精确到字段
3. 约束条件 —— 语言、框架、依赖限制、性能红线
4. 验收标准 —— 什么算做完了,可测的判定条件
5. 参考示例 —— 一两段符合项目风格的样板代码
关键在于第 5 项。给模型一个”长在我们项目里”的代码样本,比一百句文字描述都管用。它会把你的命名习惯、错误处理方式、目录结构全部对齐。
一个真实例子
假设要做一个”订单退款”接口。含糊的写法是:帮我写个退款接口。
规格写法:
目标:实现 POST /orders/{id}/refund,支持全额和部分退款。
输入:{ amount?: number, reason: string }
输出:成功返回 { refundId, status, amount };失败返回标准错误体。
约束:使用现有 OrderService,不得新增数据库表;幂等,重复调用返回同一 refundId。
验收:
- 已支付订单可退款,未支付返回 409
- 部分退款金额不得超过剩余可退金额
- 同一 idempotency-key 二次调用不重复扣款
参考:见 services/payment/refund.ts 现有实现风格
模型拿到这种规格,一次写对的概率会从”看运气”变成”基本可用”。剩下的只是审查边界和补充测试。
规格该怎么迭代
规格不是一次写死的。实用流程是三轮:
- 草案轮:让 AI 读你的需求,先输出一份规格草案,你改
- 澄清轮:让 AI 列出规格里的歧义点,逐个拍板
- 实现轮:规格冻结后,让 AI 代理实现,你只审代码
第二轮最容易被跳过,也最值钱。绝大多数返工,源于”我以为你知道”——澄清轮就是逼双方把隐藏假设摊到桌面上。
在代理化工具里怎么落地
2026 年的编码代理(如各类 CLI agent)支持在仓库里放一个约定文件(如 .agent/ 或项目根目录的说明文件),代理每次任务前都会读它。把规格模板、项目约定、常用命令写进去,等于给代理装上了”项目记忆”。
推荐结构:
/AGENTS.md 项目级约定(架构、命令、风格)
/specs/<feature>.md 单个功能的规格
代理接到任务时,先读 AGENTS.md 建立上下文,再读对应 spec,再动手。这样它的每一次输出都锚定在你的项目现实里。
踩坑清单
- 规格写成散文:模型对结构化字段的遵从度远高于段落文字,能用列表就用列表
- 接口契约含糊:字段类型、可空性、错误码必须写死,留白就会被乱猜
- 验收标准不可测:“体验流畅”这种词没用,要写成可断言的判定条件
- 规格与代码脱节:改了实现不改规格,下一轮代理就会按旧规格写,雪球越滚越大
- 一次要太多:一个 spec 对应一个可独立验收的功能,别塞成大杂烩
结语
规格驱动开发的核心洞察是:AI 编码的上限,取决于你喂给它的约束质量。你越能把”脑子里默认的那些约定”显式写出来,模型越能贴近你的真实需求。这不只是用 AI 的技巧,也是让整个团队协作更清晰的方法——规格写好了,人和 AI 都受益。