规格驱动开发:2026年用AI写代码最狠的工作流

📅 2026/9/27 ✍️ 小文 📖 约 1 分钟

深入拆解 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 现有实现风格

模型拿到这种规格,一次写对的概率会从”看运气”变成”基本可用”。剩下的只是审查边界和补充测试。

规格该怎么迭代

规格不是一次写死的。实用流程是三轮:

  1. 草案轮:让 AI 读你的需求,先输出一份规格草案,你改
  2. 澄清轮:让 AI 列出规格里的歧义点,逐个拍板
  3. 实现轮:规格冻结后,让 AI 代理实现,你只审代码

第二轮最容易被跳过,也最值钱。绝大多数返工,源于”我以为你知道”——澄清轮就是逼双方把隐藏假设摊到桌面上。

在代理化工具里怎么落地

2026 年的编码代理(如各类 CLI agent)支持在仓库里放一个约定文件(如 .agent/ 或项目根目录的说明文件),代理每次任务前都会读它。把规格模板、项目约定、常用命令写进去,等于给代理装上了”项目记忆”。

推荐结构:

/AGENTS.md           项目级约定(架构、命令、风格)
/specs/<feature>.md  单个功能的规格

代理接到任务时,先读 AGENTS.md 建立上下文,再读对应 spec,再动手。这样它的每一次输出都锚定在你的项目现实里。

踩坑清单

  • 规格写成散文:模型对结构化字段的遵从度远高于段落文字,能用列表就用列表
  • 接口契约含糊:字段类型、可空性、错误码必须写死,留白就会被乱猜
  • 验收标准不可测:“体验流畅”这种词没用,要写成可断言的判定条件
  • 规格与代码脱节:改了实现不改规格,下一轮代理就会按旧规格写,雪球越滚越大
  • 一次要太多:一个 spec 对应一个可独立验收的功能,别塞成大杂烩

结语

规格驱动开发的核心洞察是:AI 编码的上限,取决于你喂给它的约束质量。你越能把”脑子里默认的那些约定”显式写出来,模型越能贴近你的真实需求。这不只是用 AI 的技巧,也是让整个团队协作更清晰的方法——规格写好了,人和 AI 都受益。

📤 分享到