| 编辑推荐: |
本文主要介绍了Spec Driven Development(规格驱动开发) 在 AI 编码代理协作中的核心价值与实践方法,希望对你的学习有帮助。
本文来自于Halo咯咯,由火龙果软件Alice编辑,推荐。 |
|
AI 编码代理之所以经常翻车,很多时候不是因为模型不够强,而是因为指令本身不够清楚,代理依赖的 harness 也不够强。
所以现在整个行业都在补两样东西: spec ,以及 agent harness 。
文章主要想讲更核心的另一半: 当你让 agent 写代码时,到底该怎么把需求说清楚。
如果只用一句话概括这篇文章,那就是:
未来高质量的人机协作开发,重点不再只是“怎么 prompt”,而是“怎么把需求规格化”。
真正的瓶颈,其实不是模型
关于 AI coding agent,有一个不太讨喜但很现实的事实:
最大的瓶颈,不是模型,不是上下文窗口,也不是工具链,而是给出指令的人。
很多人刚开始用 coding agent 时,和它的互动大概是这样的:
“加一个从后台管理商品的功能。”
代理读一遍代码库,找一个它觉得合理的模式,然后把功能写出来。刚看上去,好像也没什么问题。
结果你点第二次“添加商品”,它就把同一条商品插入了两次。
这时候,那些你原本觉得根本不用说出口的前提,全都冒出来了:
- 这个操作应该是 幂等 的;
- 只有管理员才能执行;
- 这里说的“后台”指的是 内部运营后台 ,不是商家后台;
- 商品新增成功后应该写审计日志;
- 如果 SKU 已存在,应该返回明确错误,而不是静默覆盖;
- 商品创建后要触发索引更新,但失败不能影响主流程。
问题在于,这些信息压根没写进 prompt 里。
代理只能自己猜:
- 是哪个后台?
- 用哪套 API?
- 数据写入哪一层?
- 权限怎么校验?
- 错误怎么处理?
- 触发哪些副作用?
这些都是没有明说、但又必须做出的决定。有些它会猜对,有些会猜错。系统越复杂,偏差就会越大。
这就是 歧义问题 。
这不是代理的问题,本质上是沟通的问题。
为什么大家都在往同一个方向走
现在整个生态,其实都在独立地收敛到同一种解法。
- GitHub 的 Spec Kit 在把 spec、plan、task、implement 做成结构化流程;
- OpenAI 的 Symphony 要求用 SPEC.md 作为契约;
- 像 Claude Code 、 Cursor 这样的工具,也都把 Plan mode 和任务拆解逐步变成默认能力。
这些工具架构不同,理念也不完全一样,但底层共识是一致的:
在写代码之前,先把你要什么定义清楚;然后再让 agent 按照结构化规格去实现。
这就是 Spec Driven Development ,简称 SDD 。
什么是 Spec Driven Development
Spec Driven Development 不是一个工具,而是一种方法。
最简单的版本,只有四步:
- 先定义你要做什么
- 再规划技术上怎么做
- 把工作拆成小而有序的任务
- 让代理一次只实现一个任务
每往前走一步,歧义就少一点。
等代理真正开始写代码时,它已经拿到了足够的信息:
- 功能目标是什么;
- 它怎么接入现有系统;
- 哪些边界行为必须处理;
- 测试要验证什么;
- 应该遵循什么技术约束。
这时候它不需要再靠猜。
一句更直白的话是:
spec 和 plan,不只是“补充说明”,它们其实就是你替 agent 设计上下文窗口的方式。
先看一个贯穿全文的例子
为了把这件事讲清楚,我用一个贯穿全文的例子。
假设我们要在一个已有的电商运营系统里,加一个功能:
支持运营管理员在内部后台手动创建商品。
如果你直接这样对 agent 说:
“帮我在后台加一个商品创建功能。”
它大概率会做出一个“看起来能用”的版本,但会留下很多坑。比如:
- 没做权限控制;
- 重复提交会创建两次;
- 商品类目没校验;
- 没写审计日志;
- 失败时错误信息不一致;
- 没有接入现有的库存初始化流程;
- 用了一个和仓库里现有代码风格不一致的接口模式。
它不是乱做,它只是把所有没说清楚的地方都替你猜了一遍。
而 SDD 的做法,是先把这些本来藏在脑子里的东西,变成结构化工件。
下面就用这个例子,把 spec、plan 和 tasks 一步步展开。
一、Spec:先写清楚“做什么”
spec 是功能层。它描述的是这个功能 要完成什么 ,而不是技术上 怎么实现 。
很多人一写需求,就喜欢把功能目标和技术方案混在一起写。这样对人都不够清楚,对 agent 更糟。
比如:
“做一个商品创建接口,用 Next.js App Router,调用 ProductService,写 PostgreSQL,再通过 Kafka 发商品同步事件。”
这不是 spec,这是半截技术方案。
spec 更应该回答的是:
- 这个功能是给谁用的?
- 解决什么问题?
- 成功和失败分别意味着什么?
- 哪些边界行为必须明确?
一个最小可用的 Spec 模板
下面是一套可以直接拿去用的 最小 Spec 模板 :
# Feature Spec
## 1. Background
为什么要做这个功能?它解决什么问题?
## 2. Goal
这个功能完成后,用户能做什么?
## 3. Non-goals
这次明确不做什么,避免范围蔓延。
## 4. Users / Roles
谁会使用这个功能?有哪些角色限制?
## 5. User Stories
从用户角度描述典型使用场景。
## 6. Functional Requirements
功能必须满足哪些要求?
## 7. Edge Cases
边界情况、异常情况、冲突情况是什么?
## 8. Acceptance Criteria
用 Given / When / Then 写验收标准。
## 9. Open Questions
当前还没定的地方有哪些?
|
这个案例对应的 Spec 示例
下面是“内部后台手动创建商品”的一个最小可用 spec。
# Feature Spec: 内部后台手动创建商品
## 1. Background
运营团队需要在内部后台手动创建商品,用于活动上新、补录商品和应急处理。
当前只能通过批量导入或商家侧流程创建,效率低且不适合紧急场景。
## 2. Goal
允许运营管理员在内部后台手动创建商品,并在成功后进入商品详情页继续补充信息。
## 3. Non-goals
- 本次不处理商品编辑
- 本次不处理批量创建
- 本次不处理图片上传流程改造
- 本次不改商家后台的商品创建逻辑
## 4. Users / Roles
- 仅内部运营管理员可使用
- 普通运营、商家用户不可使用
## 5. User Stories
- 作为运营管理员,我希望手动创建一个商品,以便快速完成活动上新
- 作为运营管理员,我希望在 SKU 已存在时收到明确提示,而不是重复创建
- 作为审计人员,我希望系统记录谁在什么时间创建了什么商品
## 6. Functional Requirements
- 后台提供商品创建入口
- 表单至少包含商品名称、SKU、类目、品牌、价格
- 提交前必须校验必填项
- SKU 必须唯一
- 创建成功后进入商品详情页
- 创建成功后必须写审计日志
- 仅管理员可调用该能力
## 7. Edge Cases
- 重复提交时不能重复创建商品
- SKU 已存在时返回可理解的错误提示
- 类目无效时不可创建
- 审计日志失败时,需要记录错误并告警,但不影响商品主流程
- 库存初始化失败时,商品状态应标记为待修复,而不是完全成功
## 8. Acceptance Criteria
- Given 一个管理员用户,
When 他填写完整合法信息并提交,
Then 系统创建商品成功并跳转到商品详情页
- Given 一个非管理员用户,
When 他尝试访问创建入口,
Then 系统拒绝访问
- Given 一个已存在的 SKU,
When 管理员重复提交,
Then 系统不创建新商品,并返回“SKU 已存在”
- Given 管理员连续点击两次提交按钮,
When 请求到达服务端,
Then 系统最多只创建一个商品
## 9. Open Questions
- 库存初始化失败后的修复流程由哪个系统承接?
- 商品创建后是否需要立即触发搜索索引更新?
|
这个 spec 最大的价值,不是“写得很正式”,而是它把本来散落在脑子里的隐含前提都拉到了台面上。
这一步做完之后,很多歧义已经被消掉了。
二、Plan:再写清楚“怎么做”
如果说 spec 是功能层,那么 plan 就是技术层。
spec 解决的是“我们要实现什么”,plan 解决的是“我们准备怎么实现”。
这也是开发者最该体现经验的地方。不是体现在“亲手把代码敲出来”,而是体现在 做架构决策 。
一个好的 plan,至少要回答这几类问题:
- 现有系统里应该复用什么,不该新造什么?
- 数据模型改哪里?
- 接口怎么设计?
- 权限、幂等、审计、错误处理怎么接进去?
- 测试怎么做?
- 上线时要注意什么风险?
一个最小可用的 Plan 模板
# Technical Plan
## 1. Scope Mapping
本次需求会影响哪些模块?
## 2. Existing Patterns to Reuse
仓库里有哪些已有实现模式应该复用?
## 3. Architecture Decisions
这次采用什么方案,为什么?
## 4. Data / Contract Changes
涉及哪些数据结构、接口、事件、字段变更?
## 5. Security / Authorization
权限、鉴权、审计怎么处理?
## 6. Reliability / Idempotency / Error Handling
幂等、重试、异常处理怎么做?
## 7. Testing Strategy
单测、集成测试、端到端测试分别覆盖什么?
## 8. Rollout / Migration / Monitoring
上线方式、开关、监控、回滚怎么做?
|
这个案例对应的 Plan 示例
# Technical Plan: 内部后台手动创建商品
## 1. Scope Mapping
- backoffice-web: 新增商品创建页面
- product-service: 新增内部创建商品接口
- audit-service: 接入商品创建审计日志
- inventory-service: 创建成功后初始化库存记录
## 2. Existing Patterns to Reuse
- 复用 backoffice-web 中现有表单校验组件
- 沿用 product-service 里已有的管理员鉴权中间件
- 参考已有“手动创建品牌”流程的审计日志写法
## 3. Architecture Decisions
- 商品创建能力由 product-service 暴露内部接口
- 页面只调用内部 API,不直接写数据库
- 幂等性通过 request_id + SKU 组合保证
- 商品创建与库存初始化分步执行,避免耦合成单个大事务
## 4. Data / Contract Changes
- Product 增加 created_by 字段
- 新增 internal_create_product API
- 审计日志增加 product_create 事件类型
## 5. Security / Authorization
- 仅带 admin role 的内部用户可访问页面和接口
- 所有创建行为必须记录操作者 ID 和时间
## 6. Reliability / Idempotency / Error Handling
- 前端提交时生成 request_id
- 服务端基于 request_id + SKU 做幂等控制
- SKU 冲突返回业务错误码 PRODUCT_SKU_EXISTS
- 库存初始化失败不回滚商品创建,但标记状态为 inventory_pending
## 7. Testing Strategy
- 单元测试覆盖 SKU 校验、权限校验、幂等逻辑
- 集成测试覆盖商品创建成功、SKU 冲突、非管理员访问
- E2E 测试覆盖后台表单提交流程
## 8. Rollout / Migration / Monitoring
- 先对内部灰度角色开放
- 监控商品创建失败率、SKU 冲突率、库存初始化失败率
- 保留功能开关,异常时可快速下线入口
|
如果 spec 是把功能讲明白,那么 plan 的价值就是: 把实现空间收窄。
到这一步,agent 不需要再在仓库里到处摸索“作者大概想怎么做”,因为关键决策已经写明了。
三、Tasks:把大问题拆成 agent 真能做的小任务
接下来,plan 要被拆成任务。
这一步特别重要,因为很多团队即便写了 spec 和 plan,最后还是会翻车,问题就出在 task 拆得不好。
坏任务通常长这样:
“把商品创建功能做完。”
这不是任务,这是愿望。
一个对 agent 友好的任务,应该具备三个特点:
一个最小可用的 Tasks 模板
# Task
## 1. Task Goal
这一个任务要完成什么?
## 2. Inputs / Context
实现这个任务需要知道哪些上下文?
## 3. Changes to Make
明确列出要改哪些地方。
## 4. Out of Scope
这次不要顺手做什么。
## 5. Verification
做完后用什么方式验证?
## 6. Done Definition
满足什么条件才算完成?
|
这个案例对应的 Tasks 示例
Task 1:完成后台商品创建页面
# Task 1: 新增后台商品创建页面
## 1. Task Goal
在 backoffice-web 中新增商品创建页面和表单。
## 2. Inputs / Context
- 仅管理员可访问
- 复用现有表单校验组件
- 字段包括名称、SKU、类目、品牌、价格
## 3. Changes to Make
- 新增页面路由
- 新增表单组件
- 接入管理员权限校验
- 提交到 internal_create_product API
## 4. Out of Scope
- 不处理商品编辑
- 不改图片上传逻辑
## 5. Verification
- 管理员可访问页面
- 非管理员无法访问
- 必填项校验正确
- 提交成功后跳转商品详情页
## 6. Done Definition
页面可访问、提交流程可跑通、对应测试通过
|
Task 2:实现商品创建内部接口
# Task 2: 实现内部商品创建接口
## 1. Task Goal
在 product-service 中新增 internal_create_product 接口。
## 2. Inputs / Context
- 仅管理员可调用
- SKU 必须唯一
- 支持 request_id + SKU 幂等
## 3. Changes to Make
- 新增接口 handler
- 增加输入校验
- 写入 Product 数据
- 处理 SKU 冲突错误码
- 写入 created_by 字段
## 4. Out of Scope
- 不处理商品编辑
- 不接搜索索引更新
## 5. Verification
- 合法请求返回创建成功
- 重复 SKU 返回业务错误
- 重复请求不重复创建
- 非管理员请求被拒绝
## 6. Done Definition
接口可用,单测和集成测试通过
|
Task 3:接入审计日志和库存初始化
# Task 3: 接入审计日志和库存初始化
## 1. Task Goal
在商品创建成功后写审计日志,并触发库存初始化。
## 2. Inputs / Context
- 审计日志失败不影响主流程
- 库存初始化失败时商品标记为 inventory_pending
## 3. Changes to Make
- 调用 audit-service 记录 product_create
- 调用 inventory-service 初始化库存
- 增加失败状态标记和日志
## 4. Out of Scope
- 不做库存修复后台
- 不改库存服务内部逻辑
## 5. Verification
- 商品创建成功后能看到审计记录
- 库存初始化成功时状态正常
- 库存初始化失败时状态正确标记
## 6. Done Definition
主流程稳定,异常分支可验证
|
这种拆法的价值在于:任务本身已经带着足够的上下文,agent 不用再从头推理一遍“这件事可能还隐含了什么”。
这一步一旦做得好,会直接带来两个结果:
第一, 你可以并行执行 。 第二, 你可以更换 agent 。
Task 1 给 Claude Code,Task 2 给 Cursor,Task 3 再交给别的 agent,都没问题。因为上下文跟着任务走,而不是跟着某个 agent 绑定。
四、什么时候该用,什么时候别用
这里必须讲清楚一件事:
SDD 不是万能钥匙。
它有效,但不是所有任务都值得上完整 spec → plan → tasks 这套流程。
如果不讲边界,文章就会变成口号。真正成熟的用法,是知道它什么时候值得,什么时候不值得。
一个简单的判断框架
你可以用下面这套判断方式:
适合直接 prompt 或只用 Plan mode 的场景
- 改一个文案
- 修一个小 bug
- 调一个配置
- 改一个单文件里的局部逻辑
- 做一次很小的重构,影响范围很明确
- 你对需求、代码位置和实现方式都非常确定
这类场景的问题不在歧义,而在执行速度。 上完整 SDD,成本大于收益。
适合用 SDD 的场景
- 跨多个文件或多个模块
- 涉及权限、状态流转、幂等、审计等业务约束
- 会碰到隐含规则,稍微猜错就会出问题
- 老仓库、复杂仓库、多人维护仓库
- 一个功能看上去不大,但牵涉多个系统
- 你发现自己在给 agent 解释需求时,越解释越长
这类场景最怕的不是编码,而是理解偏差。 而 SDD 的价值,正是在编码前把偏差尽可能消掉。
一个更实用的判断问题
如果你不想记那么多条,可以只问自己三个问题:
1. 这件事是不是有很多“默认前提”?
比如权限、幂等、错误处理、审计、副作用。
2. 这件事是不是一旦做偏,返工成本就很高?
比如要改多个模块、影响线上行为、会引入数据问题。
3. 我是不是已经开始写很长的 prompt 来补充背景?
如果是,那你其实已经在“半手工做 spec”了,只是还没把它结构化。
只要这三个问题里有两个答案是“是”,通常就值得上 SDD。
五、为什么 spec 和技术实现要分开写
这里还有一个很关键、但常被忽略的点:
spec 和 plan 最好分开写。
很多人会把功能目标和技术实现混在一份文档里,这样做对人都不够清楚,对 agent 更是如此。
比如:
“用户可以用 Google 和 GitHub 登录,使用 NextAuth.js 的 JWT strategy,并把 session 存到 Redis。”
这句话里混了两层信息:
如果把它们拆开,事情会清楚很多。
spec 只负责说:
- 用户能做什么
- 成功是什么
- 失败是什么
- 边界行为是什么
plan 再负责说:
- 用什么框架
- 走哪条现有模式
- 数据怎么落
- 测试怎么写
这样分层的好处是,agent 在不同阶段只需要处理一种问题,不会在功能理解和技术选型之间来回跳。
六、开发者真正增加价值的地方,已经变了
过去,开发者的主要价值常常体现在“把代码写出来”。
但在 agent 参与开发之后,开发者越来越多的价值,体现在另外几件事上:
- 把需求讲清楚;
- 把边界画清楚;
- 做正确的架构决策;
- 判断哪里该复用,哪里该新增;
- 审查 task 是否过度设计;
- 识别 agent 会在哪些地方瞎猜。
也就是说,开发者的角色没有变轻,反而变得更偏“设计”和“约束”。
写代码这件事还在,但它不再是唯一核心。
你真正交给 agent 的,不只是任务,而是上下文、约束和判断框架。
七、这套方法的代价也很明确
Spec Driven Development 不是免费的。
它要多花时间,也会多消耗 token。一次完整的 spec → plan → tasks 流程,成本通常明显高于“直接丢一个 prompt 开干”。
所以它真正的 tradeoff 很简单:
你在前面多投入,换后面少返工。
这笔账值不值,要看任务本身。
对于一个很小的改动,当然不值。 但对于一个一旦做偏就要来回修三轮、补五个边界、再返工两次测试的功能,这笔账往往非常值。
很多团队不是不愿意花 token,他们是不愿意把 token 花在“反复修错的实现”上。
从这个角度看,SDD 不是增加成本,而是把成本前移。
八、怎么开始,不用一步到位
如果你第一次尝试这套方法,不需要一上来就做完整流程。
最简单的起点其实是:
先用 Plan mode。
也就是先别急着让 agent 直接写代码,而是先让它:
- 帮你整理需求里的歧义;
- 先产出技术方案;
- 先拆任务;
- 等你看过一遍,再进入实现。
这是成本最低、回报也很明显的一步。
再往前一点,你可以开始固定自己的最小流程:
- 先写一个短 spec
- 再写一个短 plan
- 再拆成 2 到 5 个 task
- 最后逐个交给 agent 做
你不需要一上来就把文档写得很大、很全、很正式。
刚开始最重要的,不是完美,而是建立一个习惯:
在实现之前,先把含糊的地方写清楚。
一个足够实用的最小流程
如果你想马上试,下面这套就够了:
第一步:写 10 分钟 spec
只写背景、目标、非目标、功能要求、边界情况、验收标准。
第二步:写 10 分钟 plan
只写影响模块、复用点、关键技术决策、测试策略。
第三步:拆 3 个以内的 task
每个 task 必须能单独完成、单独验证。
第四步:逐个交给 agent
不要一次把整套任务全扔进去,让它自己组织。
这样已经足够比“直接一句 prompt 开始写”稳定很多。
九、方法论之外,agent 还需要你的内部上下文
最后还要补一句: SDD 不是全部。
它解决的是“要做什么”“怎么拆清楚”,但 agent 还需要另一类信息:你的内部上下文。
比如:
- 你们团队有哪些编码规范;
- 哪些模式是约定俗成必须复用的;
- 哪些内部 SDK、脚手架、服务能力应该优先用;
- 哪些系统需要通过 MCP 或其他方式接入;
- 哪些错误处理和审计方式是组织级约束。
方法论负责定义“要做什么”; harness 负责提供“在你的环境里,什么叫正确地去做”。
十、结语:Vibe coding 做得出 demo,规格化开发才更像生产方式
这篇文章如果只想留下一句话,那就是:
Vibe coding 很适合做 demo 和 MVP,Spec Driven Development 更适合做真正要上线、要维护、要协作的系统。
AI coding agent 最大的问题,从来不只是“代码写得好不好”,而是“它到底有没有理解对”。
而理解对这件事,不能只靠模型自己变聪明,还要靠你把需求表达得更清楚,把约束写得更清楚,把上下文组织得更清楚。
这也是为什么我越来越觉得:
规格,才是新的代码。
因为在 agent 参与开发的时代,真正决定结果质量的,往往不是最后那几百行代码,而是代码生成之前那份是否足够清晰的规格。
附录:三份可以直接拿来用的最小模板
A. 最小 Spec 模板
# Feature Spec
## Background
## Goal
## Non-goals
## Users / Roles
## User Stories
## Functional Requirements
## Edge Cases
## Acceptance Criteria
## Open Questions
|
B. 最小 Plan 模板
# Technical Plan
## Scope Mapping
## Existing Patterns to Reuse
## Architecture Decisions
## Data / Contract Changes
## Security / Authorization
## Reliability / Idempotency / Error Handling
## Testing Strategy
## Rollout / Monitoring
|
C. 最小 Task 模板
# Task
## Task Goal
## Inputs / Context
## Changes to Make
## Out of Scope
## Verification
## Done Definition
|
D. 什么时候该用 SDD
适合:
- 多模块改动
- 复杂业务规则
- 有权限、审计、幂等、状态流转
- 老仓库 / 大仓库
- 返工成本高
- prompt 已经开始变长
不太适合:
- 小 bug
- 文案修改
- 配置调整
- 单文件局部改动
- 需求和实现路径都很清楚的小任务
|