找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2431

积分

0

好友

325

主题
发表于 3 小时前 | 查看: 2| 回复: 0

AI 编码代理翻车,很多时候不是模型能力问题,而是指令本身就不够清晰,它所依赖的执行框架(harness)也不够强健。

整个行业都在补齐两个核心短板:spec(规格说明),以及 agent harness(代理执行框架)。

在上一篇关于 The Coding Agent Harness 的文章里,我把 Spec Driven Development 称为“终极 harness”。那篇主要讨论了上下文、规则、工具和约束,而本文想探讨另一半核心问题:当你让 AI 代理编写代码时,究竟该如何把需求说清楚

用一句话概括,那就是:未来高质量的人机协作开发,重点将逐渐从“如何编写提示词(prompt)”转向“如何将需求规格化(specification)”。

真正的瓶颈,其实不是模型

关于 AI 编码代理,有一个不太讨喜但很现实的真相:最大的瓶颈,往往不是模型能力、上下文窗口大小或工具链,而是发出指令的人。

许多人初次尝试时,与代理的互动可能是这样的:

“加一个从后台管理商品的功能。”

代理浏览一遍代码库,寻找一个它认为合理的模式,然后把功能实现出来。乍一看,似乎没问题。

但当你第二次点击“添加商品”时,它可能会将同一条商品插入两次。

此时,那些你原本认为不言自明的前提,全都暴露出来了:

  • 这个操作必须是幂等的;
  • 只有管理员才能执行;
  • 这里说的“后台”是指内部运营后台,而非商家后台;
  • 商品新增成功后需要写入审计日志;
  • 如果 SKU 已存在,应返回明确错误,而非静默覆盖;
  • 商品创建后需触发搜索索引更新,但失败不应影响主流程。

问题在于,这些关键信息根本没有写在 prompt 里。代理只能自行猜测:

  • 是哪个后台?
  • 使用哪套 API?
  • 数据写入哪一层?
  • 权限如何校验?
  • 错误如何处理?
  • 会触发哪些副作用?

这些都是未被明说、但又必须做出的技术决策。有些它猜对了,有些则会猜错。系统越复杂,这种偏差就越大。

这就是歧义问题。这不是代理自身的问题,本质上是人与机器沟通方式的问题。

为什么生态正在向同一方向演进

当前整个开发生态,其实都在独立地收敛到同一种解决方案。

  • GitHub 的 Spec Kit 正在将 spec(规格)、plan(计划)、task(任务)、implement(实现)构建成结构化流程;
  • OpenAI 的 Symphony 要求使用 SPEC.md 作为开发契约;
  • Claude CodeCursor 这类工具,也逐步将 Plan mode 和任务拆解能力作为默认配置。

这些工具的架构和理念虽不尽相同,但底层共识是一致的:在编写代码之前,先清晰定义你要什么;然后让代理依据结构化的规格说明去实现。

这就是 Spec Driven Development,简称 SDD

什么是 Spec Driven Development

Spec Driven Development 不是某个具体工具,而是一种方法论。

其最简版本,只有四个步骤:

  1. 先定义你要做什么
  2. 再规划技术上如何实现
  3. 将工作拆分为小而有序的任务
  4. 让代理一次只完成一个任务

每向前推进一步,歧义就减少一分。当代理真正开始编码时,它已经获得了充分的信息:

  • 功能目标是什么;
  • 如何接入现有系统;
  • 必须处理哪些边界情况;
  • 测试需要验证什么;
  • 应遵循哪些技术约束。

此时,它不再需要依赖猜测。一句更直白的总结是:spec 和 plan 不仅仅是“补充说明”,它们实质上是你为 agent 精心设计的上下文窗口。

贯穿全文的示例

为了清晰地阐述这一过程,我将使用一个贯穿全文的示例。

假设我们需要在一个已有的电商运营系统中,增加一项功能:

支持运营管理员在内部后台手动创建商品。

如果你直接这样告诉代理:

“帮我在后台加一个商品创建功能。”

它很可能会做出一个“看起来能用”的版本,但留下诸多隐患。例如:

  • 未做权限控制;
  • 重复提交会创建两条记录;
  • 商品类目未校验;
  • 未写审计日志;
  • 失败时错误信息不统一;
  • 未接入现有的库存初始化流程;
  • 使用了与仓库现有代码风格不一致的接口模式。

它并非胡乱实现,只是替你猜测了所有未说清楚的地方。而 SDD 的做法,是将这些原本隐藏在脑海中的概念,转化为结构化的交付物。

下面就用这个例子,一步步展开 spec、plan 和 tasks。


一、Spec:先写清楚“做什么”

Spec 是功能描述层。它阐述的是这个功能要完成什么,而不是技术上如何实现

许多人撰写需求时,喜欢将功能目标与技术方案混在一起。这对人类协作已不够清晰,对 AI 代理而言则更为糟糕。例如:

“做一个商品创建接口,用 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 的核心价值就是:收窄实现的可能性空间。走到这一步,代理无需再在代码仓库中四处摸索“作者大概想怎么做”,因为关键的技术决策已经清晰列明。


三、Tasks:把大问题拆成 agent 真能做的小任务

接下来,plan 需要被拆解为具体的任务。这一步尤为重要,因为许多团队即便写了 spec 和 plan,最终仍会失败,问题往往就出在任务拆解得不够好。

糟糕的任务通常长这样:

“把商品创建功能做完。”

这不是任务,这是愿望。一个对 AI 代理友好的任务,应具备三个特点:边界清楚上下文完整完成后可以验证

一个最小可用的 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
主流程稳定,异常分支可验证

这种任务拆解方式的价值在于:任务本身已携带充足的上下文,代理无需从头推理“这件事可能还隐含了什么”。做好这一步,会直接带来两个好处:

第一,你可以并行执行任务。第二,你可以灵活更换不同的 AI 代理。Task 1 给 Claude Code,Task 2 给 Cursor,Task 3 再交给其他代理,都没有问题。因为上下文是跟随任务走的,而非与某个特定代理绑定。


四、什么时候该用,什么时候别用

这里必须澄清一点:SDD 不是万能钥匙。 它很有效,但并非所有任务都值得走完 spec → plan → tasks 这套完整流程。如果不界定其适用范围,任何方法都会沦为空洞的口号。真正成熟的用法,是明确知道它何时值得投入,何时无需大动干戈。

一个简单的判断框架

你可以参考下面的判断方式:

适合直接 prompt 或仅用 Plan mode 的场景

  • 修改文案
  • 修复小 bug
  • 调整配置
  • 修改单文件内的局部逻辑
  • 进行影响范围明确的小规模重构
  • 你对需求、代码位置和实现方式都非常确定

这类场景的核心矛盾不在于歧义,而在于执行速度。上完整的 SDD,成本大于收益。

适合使用 SDD 的场景

  • 改动涉及多个文件或多个模块
  • 涉及权限、状态流转、幂等、审计等业务约束
  • 存在隐含规则,稍猜错就会导致问题
  • 老旧、复杂或由多人维护的代码仓库
  • 一个功能看似不大,但牵涉多个子系统
  • 你发现自己向代理解释需求时,提示词越写越长

这类场景最怕的不是“写代码”,而是“理解偏差”。SDD 的价值,正是在编码开始前,尽可能消除这些偏差。

一个更实用的判断问题

如果你不想记太多条条框框,可以只问自己三个问题:

  1. 这件事是不是有很多“默认前提”?
    例如权限、幂等、错误处理、审计、副作用等。
  2. 这件事是不是一旦做偏,返工成本就很高?
    例如需要改动多个模块、影响线上行为、可能引入数据问题。
  3. 我是不是已经开始写很长的 prompt 来补充背景了?

如果是,那你其实已经在“半手工地制作 spec”了,只是尚未将其结构化。只要这三个问题中有两个答案是“是”,通常就值得采用 SDD。


五、为什么 spec 和技术实现要分开写

这里有一个非常关键却常被忽略的点:spec 和 plan 最好分开撰写。

很多人习惯将功能目标和技术实现混在一份文档里,这种做法对人类协作已不够清晰,对 AI 代理则更糟。例如:

“用户可以用 Google 和 GitHub 登录,使用 NextAuth.js 的 JWT strategy,并把 session 存到 Redis。”

这句话混合了两层信息:1)用户需要什么能力;2)技术上如何实现。

如果将它们拆分开,事情会清晰得多:

  • Spec 只负责说明
    • 用户能做什么
    • 成功是什么样
    • 失败是什么样
    • 边界行为是什么
  • Plan 再负责说明
    • 用什么框架或工具
    • 遵循哪种现有模式
    • 数据如何持久化
    • 测试如何编写

这种分层的好处是,AI 代理在不同阶段只需处理单一类型的问题,不会在功能理解和技术选型之间来回跳跃,从而减少混淆。


六、开发者真正增加价值的地方,已经变了

过去,开发者的核心价值常常体现在“把代码写出来”这一执行层面。但在 AI 代理参与开发之后,开发者越来越多的价值,体现在以下几件事上:

  • 把需求讲清楚;
  • 把边界画清楚;
  • 做出正确的架构决策;
  • 判断哪里该复用已有代码,哪里该新增;
  • 审查任务是否过度设计;
  • 识别代理可能在哪些地方进行无依据的猜测。

也就是说,开发者的角色并未减轻,反而变得更偏向 “设计”与“约束” 。写代码本身依然重要,但它不再是唯一的核心活动。你真正交给 AI 代理的,不只是任务清单,还包括上下文、约束条件和判断框架。


七、这套方法的代价也很明确

Spec Driven Development 并非没有成本。它需要额外投入时间,也会消耗更多 Token。一次完整的 spec → plan → tasks 流程,其成本通常明显高于“直接丢一个 prompt 开干”。

因此,它真正的权衡很简单:你在前期多投入,换取后期少返工。 这笔账是否划算,取决于任务本身。

对于一个很小的改动,当然不划算。但对于一个一旦做偏就需要来回修补三轮、补充五个边界情况、再返工两次测试的功能,这笔前期投资往往非常值得。

许多团队不是不愿意花费 Token,他们是不愿意把 Token 浪费在“反复修正错误的实现”上。从这个角度看,SDD 并非增加总成本,而是将成本进行了前移和优化。


八、如何开始,无需一步到位

如果你是第一次尝试这套方法,完全不需要从一开始就执行完整流程。

最简单的起点其实是:先尝试使用工具的 Plan mode。 也就是说,先别急着让代理直接写代码,而是让它:

  • 帮你整理需求中的歧义点;
  • 先产出技术方案草案;
  • 先进行任务拆解;
  • 等你审查过一遍后,再进入具体实现阶段。

这是成本最低、回报却很明显的第一步。

再进一步,你可以开始固化自己的最小流程:

  1. 先写一个简短的 spec
  2. 再写一个简短的 plan
  3. 拆分成 2 到 5 个 task
  4. 最后逐个交给 AI 代理执行

你不需要一开始就把文档写得大而全、非常正式。初期最重要的,不是追求完美,而是建立一种习惯:在动手实现之前,先把含糊不清的地方书面化、清晰化。

一个足够实用的最小流程

如果你想立刻尝试,下面这套流程就足够了:

第一步:写 10 分钟 spec
只写背景、目标、非目标、功能要求、边界情况、验收标准。

第二步:写 10 分钟 plan
只写影响模块、可复用点、关键技术决策、测试策略。

第三步:拆 3 个以内的 task
确保每个 task 都能独立完成、单独验证。

第四步:逐个交给 agent
不要一次性把所有任务丢进去让它自行组织。

这样做,已经比“直接一句 prompt 开始写”要稳定和可靠得多。


九、方法论之外,agent 还需要你的内部上下文

最后必须补充一点:SDD 不是全部。 它解决了“要做什么”和“如何拆解清楚”的问题,但 AI 代理还需要另一类关键信息:你的内部上下文。

例如:

  • 你们团队有哪些编码规范?
  • 哪些模式是约定俗成必须复用的?
  • 哪些内部 SDK、脚手架、服务能力应该优先使用?
  • 哪些外部或内部系统需要通过 MCP 等方式接入?
  • 哪些错误处理和审计方式是组织级别的强制约束?

方法论(SDD)负责定义 “要做什么” ;而执行框架(harness)则负责提供 “在你的特定环境里,怎样才算正确地去做”。在云栈社区的技术论坛中,经常能看到开发者们分享如何为自己的团队构建这类内部上下文和约束的最佳实践。


十、结语:Vibe coding 做得出 demo,规格化开发才更像生产方式

如果这篇文章只能留下一句话,那就是:Vibe coding(氛围编码)很适合制作 demo 和 MVP,而 Spec Driven Development 更适合构建真正需要上线、维护和团队协作的生产级系统。

AI 编码代理最大的挑战,从来不只是“代码写得好不好”,更是“它到底有没有理解对”。而确保正确理解这件事,不能只依赖模型自身变得更聪明,还需要你把需求表达得更清楚、把约束写得更明确、把上下文组织得更完善

这也是为什么我越来越认同一个观点:规格,正在成为新时代的“代码”。因为在 AI 代理参与开发的时代,最终决定产出质量的,往往不是最后那几百行生成代码,而是代码生成之前那份是否足够清晰、无歧义的规格说明书。


附录:三份可以直接拿来用的最小模板

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

适合:

  • 多模块改动
  • 复杂业务规则
  • 涉及权限、审计、幂等、状态流转
  • 老旧 / 大型代码仓库
  • 返工成本高
  • 已经开始编写长篇幅的提示词

不太适合:

  • 小 bug 修复
  • 文案修改
  • 配置调整
  • 单文件内的局部改动
  • 需求和实现路径都非常清晰明确的小任务



上一篇:ADMT4000多圈位置传感器:从密码锁到机械臂的工业控制应用实践
下一篇:中断与异常机制详解:CPU如何处理内部错误与外部事件?
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-3-18 09:02 , Processed in 0.866500 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表