Skip to content

Spec Engineering —— 规格工程 / Spec Engineering

本章观点

Prompt Engineering 教你怎么跟模型说话,Spec Engineering 教你怎么把需求固化成可验证的规格

两者关系是:

Prompt 是临时指令,Spec 是长期契约。Prompt 让模型听懂这一次,Spec 让 Agent 每次都做对。

在 Agent 时代,Spec Engineering 变得比 Prompt Engineering 更重要。原因有三个:

  1. Agent 会跨会话执行:一次 prompt 不够,必须有持久 spec 让 Agent 反复对齐。
  2. Agent 会自己拆任务:拆得对不对,要看 spec 是否把目标和约束写清楚。
  3. Agent 输出要验收:验收标准必须可量化、可测试,这正是 spec 的核心。

这一章讲 Spec Engineering 的方法论:spec 怎么写、怎么分层、怎么和 Agent 配合。


4.1 Spec 是什么

Spec(Specification,规格说明) 是对"要做什么、做到什么程度、不做什么"的精确描述。

一个完整的 Spec 至少包含四块:

回答的问题例子
目标 (Goal)解决什么问题让用户上传视频反推提示词
需求 (Requirements)必须实现什么视频上传、AI 反推、历史记录
约束 (Constraints)边界在哪Next.js 15、单次成本 ≤ $0.5
验收标准 (Acceptance)怎么算做完了100MB 视频 30s 内开始处理

少了任何一块,Agent 就会"自由发挥"——通常是发挥到你想不到的方向。


4.2 Spec vs Prompt:本质区别

很多人把 Spec 和 Prompt 混为一谈。它们确实相关,但层次不同:

维度PromptSpec
寿命一次性,发完就丢长期,跨会话存在
载体字符串、API 参数文件(SPEC.md)
谁写终端用户工程师 / 产品
粒度单次任务整个项目或模块
可验证难(看输出像不像)易(对验收标准逐条 check)
版本化git
适合Chatbot / 单轮任务Agent / 多步任务

一个直观对比:

Prompt 写法

帮我做一个视频上传功能,要支持大文件,还要能反推提示词,用智谱或者 Gemini 都行,做得快一点,UI 要好看。

这是 prompt——表达需求,但模糊。Agent 接到这个 prompt 会做出五花八门的东西。

Spec 写法

markdown
## 目标
视频提示词反推工具,用户上传视频,AI 输出提示词。

## 需求
- F1: 视频上传(mp4/mov,≤500MB,分片上传)
- F2: AI 反推(智谱 GLM-4V / Gemini 2.0,可切换)
- F3: 历史记录(分页,按时间倒序)

## 约束
- 前端 Next.js 15 App Router
- 单次反推成本 ≤ $0.5
- P95 延迟 ≤ 30s

## 验收标准
- AC1: 500MB mp4 上传成功,分片进度可见
- AC2: 反推结果 60s 内返回,含 ≥5 个关键词
- AC3: 历史记录 200ms 内响应

这是 spec——精确、可测、可版本化。Agent 按这个做,偏差会很小。

Spec 和提示词样本分类的关系 07-09

吴恩达 Agentic AI 课程(Bilibili BV1DfrdByE2H,Module 4)把提示词按"给几个示例"分成三类:

  • Zero-shot:0 个示例,只靠指令描述
  • One-shot:1 个示例,展示格式或模式
  • Few-shot:2-5+ 个示例,展示复杂模式

Spec 本质上是给 Agent 的 zero-shot 上下文。它不依赖示例,而是通过精确描述(目标 + 需求 + 约束 + 验收)让 Agent 理解要做什么。

这对 Spec Engineering 的启示:

  1. Spec 要写到 zero-shot 就能让 Agent 做对--不能依赖"给几个例子让 Agent 自己悟"
  2. 如果 Spec 写不清楚,加示例(one/few-shot)是补丁,不是根治--更好的做法是把示例里的模式提炼成 Spec 规则
  3. Spec 和示例可以共存:Spec 写规则,TASK_SPEC.md 里可以附 1-2 个参考实现(本章 4.6 节技巧 3"给参考实现")

什么时候该用 few-shot 而不是纯 Spec

  • 任务模式难以用规则描述(如"写诗的风格")-> few-shot 更有效
  • 任务边界清晰(如"实现 API 接口")-> 纯 Spec 更有效
  • Agent 项目里 90% 的任务是后者,所以 Spec 优先,示例辅助

这条原则也解释了为什么 Spec Engineering 比 Prompt Engineering 更适合 Agent 时代:Prompt Engineering 经常依赖 few-shot 技巧(塞一堆示例),而 Spec Engineering 追求"zero-shot 就能做对"--后者更可维护、更可验证。


4.3 Spec-Driven Development

Spec-Driven Development(规格驱动开发) 是一种工作流:

text
写 Spec → Agent 拆任务 → Agent 实现 → 跑 EVALS 验收 → 不通过则改 Spec 或改实现

和传统 TDD(测试驱动开发)的区别:

TDDSpec-Driven
起点写测试用例写 spec(含验收标准)
测试谁写人写 EVALS,Agent 跑
实现谁写Agent
反馈测试通过/失败EVALS 通过/失败

Spec-Driven 把"想清楚要什么"和"怎么实现"分开:人负责前者(写 spec),Agent 负责后者(写代码)。这正好利用了各自的强项——人擅长判断需求对不对,Agent 擅长把需求落成代码。

Spec-Driven 的三个原则

  1. 先 spec 后 code:没有 spec 不让 Agent 动手。Agent 没有 spec 就拆任务,等于在不知道终点的情况下规划路线。
  2. spec 可验证:每条需求都必须有对应的验收标准。写不出验收标准的需求,说明 spec 还没想清楚。
  3. spec 是活文档:实现过程中发现 spec 错了,改 spec 再改 code,而不是"绕过 spec"。

4.4 Spec 的三个层次

Spec 不是只有一份,应该按层次组织:

项目级 Spec(PROJECT_SPEC.md)

定义整个项目的目标、范围、约束。一个项目只有一份。

markdown
# PromptLens 项目 Spec

## 使命
让视频创作者用最低门槛获得专业级提示词。

## 范围
- In: 视频上传、AI 反推、历史记录、用户系统
- Out: 视频剪辑、模板市场、移动端

## 技术约束
- 全栈 TypeScript
- 部署在 Vercel
- 数据库 Supabase

模块级 Spec(MODULE_SPEC.md)

每个核心模块一份,定义该模块的接口、行为、边界。

markdown
# Analyzer 模块 Spec

## 职责
接收视频文件,调用 LLM,返回提示词列表。

## 接口
interface Analyzer {
  analyze(video: VideoFile): Promise<PromptResult>
}

## 实现
-智谱Analyzer: 用 GLM-4V,价格便宜
- GeminiAnalyzer: 用 Gemini 2.0,质量好

## 边界
- 不处理视频下载(由上层 Upload 模块负责)
- 不存历史(由 History 模块负责)

任务级 Spec(TASK_SPEC.md)

单个任务的最小 spec,通常在 PLAN.md 里。

markdown
# 任务:加 GeminiAnalyzer

## 背景
用户反馈智谱对动漫视频效果差,需要 Gemini 备选。

## 范围
- 新增 `lib/analyzers/gemini.ts`
- 注册到 `lib/analyzers/index.ts`
- 前端加模型切换 UI
- 加测试

## 验收
- gemini.test.ts 全过
- EVALS E1-E3 用 Gemini 跑,准确率 ≥ 智谱
- UI 切换无刷新

三层的分工:

  • 项目级 = 为什么做(Why)
  • 模块级 = 做成什么样(What)
  • 任务级 = 这次做什么(Which)

4.5 验收标准的写法

验收标准是 Spec 的灵魂。一条好的验收标准要满足 SMART 原则:

  • Specific(具体):不模糊
  • Measurable(可测):有数字或明确判断
  • Achievable(可达):技术上能做
  • Relevant(相关):和需求对应
  • Time-bound(有时限):有完成期限或性能指标

反例 vs 正例

反例(模糊)

  • ✗ "上传要快"
  • ✗ "UI 要好看"
  • ✗ "支持大文件"
  • ✗ "测试要充分"

正例(SMART)

  • ✓ "500MB mp4 上传 P95 ≤ 30s"
  • ✓ "首屏 LCP ≤ 2.5s,按钮可点击区域 ≥ 44px"
  • ✓ "支持 mp4/mov/avi,单文件 ≤ 500MB"
  • ✓ "单元测试覆盖率 ≥ 80%,E2E 测试覆盖核心路径"

验收标准的两种形式

量化标准:有数字,能跑测试。

markdown
- AC1: 500MB mp4 上传 P95 ≤ 30s
- AC2: 反推结果 60s 内返回
- AC3: API 错误率 ≤ 1%

行为标准:描述具体行为,能写 e2e 测试。

markdown
- AC4: 用户上传 mp4 → 进度条可见 → 完成后跳转结果页
- AC5: 用户切换模型 → 不重新上传 → 直接重新分析
- AC6: 用户未登录 → 上传时弹登录框

两种都要有。量化标准管性能,行为标准管功能。


4.6 给 Agent 写 Spec 的特殊技巧

Agent 读 spec 和人读 spec 不一样。给 Agent 写 spec,有几个额外技巧:

技巧 1:明确"做什么"和"不做什么"

Agent 容易"多做"。spec 里要写负面边界

markdown
## 范围
- In: 视频上传、AI 反推
- Out: 视频剪辑、模板市场

## 禁止
- 不要加用户头像上传功能
- 不要改 db/schema.ts(这次只加 analyzer)
- 不要 commit `.env.local`

技巧 2:给约束写理由

Agent 知道"为什么"才能在边界 case 做对判断。

markdown
## 约束
- 单次反推成本 ≤ $0.5
  理由:免费用户每月 10 次,订阅 $9.99/月,毛利要 ≥ 60%
- 不用 FFmpeg 服务端转码
  理由:Vercel 函数 50MB 内存限制,转码会 OOM

技巧 3:给参考实现

Agent 看代码比看文字准。spec 里贴参考代码片段。

markdown
## 接口示例
Analyzer 接口必须长这样(参考 lib/analyzers/zhipu.ts):

​```typescript
export interface Analyzer {
  name: string
  analyze(video: VideoFile): Promise<PromptResult>
}
​```

GeminiAnalyzer 必须实现这个接口,不能改签名。

技巧 4:标注优先级

Agent 容易把所有需求当同等重要。标注 P0/P1/P2 让它知道哪些必须做、哪些可选。

markdown
## 需求
- P0 F1: 视频上传(必须)
- P0 F2: AI 反推(必须)
- P1 F3: 历史记录(这次要做)
- P2 F4: 模板市场(这次不做,留接口)

技巧 5:写"完成定义"(Definition of Done)

不要让 Agent 自己判断"做完了"。明确定义。

markdown
## 完成定义
本任务算完成,当且仅当:
1. 代码通过 `pnpm lint``pnpm typecheck`
2. 单元测试全过,覆盖率 ≥ 80%
3. E2E 测试 `gemini-analyzer.spec.ts` 全过
4. EVALS E1-E3 用 Gemini 跑,准确率 ≥ 智谱基线
5. CHANGELOG.md 已更新
6. SPEC.md F2 已更新支持 Gemini

4.7 Spec 的反模式

反模式 1:Spec 写成产品文档

markdown
✗ 我们的使命是让每个人都能用 AI 创作视频,让创意不再被技术门槛阻挡,
  让每个人都能成为自己生活的导演...

这是营销文案,不是 spec。Spec 要写"做什么",不是"为什么伟大"。

反模式 2:Spec 过度详细

markdown
✗ 函数 `analyzeVideo` 第 3 行必须调用 `client.messages.create`
  第 4 行必须解构 response.content[0].text,
  第 5 行必须 try/catch...

这是伪代码,不是 spec。Spec 写"做什么"和"做到什么",不写"怎么做"——怎么做让 Agent 决定。

反模式 3:Spec 写完不动

Spec 是活文档。实现过程中发现 spec 错了,要回头改 spec。常见情况:

  • 验收标准测不了("UI 要好看"→改成"按钮 ≥ 44px")
  • 约束不现实("P95 ≤ 1s"→改成"P95 ≤ 3s")
  • 范围变了(用户临时加需求)

每次改 spec 都要在 CHANGELOG 记一笔。

反模式 4:Spec 和 Code 不同步

代码改了 spec 没改,下次 Agent 读 spec 还以为代码是旧样子,就会写错。改代码前先看 spec,改完代码同步改 spec

反模式 5:验收标准写在事后

markdown
✗ (写完代码后)"嗯,验收标准就写'功能正常'吧"

验收标准要先写,作为实现的靶子。事后写的验收标准永远会"通过",因为它在迁就实现。


4.8 前人智慧 / Prior Art

Anthropic 的 Spec 实践

Anthropic 在 Claude Code 文档 里反复强调 spec 的重要性。他们的工作流推荐:

  1. 让 Claude 先读 spec(CLAUDE.md / SPEC.md)
  2. 让 Claude 写 plan(PLAN.md),人 review
  3. 人批准后 Claude 才动手改代码
  4. 改完跑 evals 验收

这个流程本质就是 Spec-Driven Development。Anthropic 自己做 Claude Code 时也是这么干的。

OpenAI 的 Evals 哲学

OpenAI 在 Evals 文档 里有一句关键话:

"If you can't measure it, you can't improve it."

翻译:测不了就改不了。这直接对应 Spec 的验收标准——写不出验收标准的需求,等于没想清楚

OpenAI 自己做 GPT 评测时,每个能力都先写 eval spec,再写测试用例,最后跑模型。这个思路迁移到 Agent 项目就是 EVALS.md。

Cognition(Devin)的 Spec 观察

Cognition 在 Devin 技术报告 里提到一个现象:

"Devin 在有清晰 spec 的任务上表现远好于模糊任务。给 Devin 一个具体 issue('修复 X 测试'),它几乎能自主完成。给一个模糊目标('让代码更好'),它经常跑偏。"

这印证了 Spec Engineering 的核心命题:Agent 的能力上限由模型决定,但实际表现由 spec 决定。同一个 Agent,spec 写得好 vs 不好,效果差几个数量级。

传统软件工程的 Spec 传统

Spec-Driven Development 不是 Agent 时代才有的。传统软件工程里:

Agent 时代的 Spec Engineering 继承了这些传统的核心(可验证、可量化、分层),但有两个新特点:

  1. Spec 直接被 Agent 读,不只是给人读。所以要写得让 Agent 能解析(结构化、无歧义、有参考代码)。
  2. Spec 是动态的,Agent 实现过程中会反馈 spec 的问题,需要快速迭代。

Aider 的"spec first" 工作流

Aider(终端 Coding Agent)推荐一个工作流:

  1. CONVENTIONS.md 写项目规则
  2. TODO.md 写任务清单
  3. 跟 Aider 说"按 CONVENTIONS 实现 TODO 第一项"

这就是 Spec-Driven 的轻量版。Aider 文档里建议:CONVENTIONS.md 越具体,Aimer 表现越好——和 Cognition 的观察一致。

Spec-Driven vs Behavior-Driven

BDD (传统)Spec-Driven (Agent)
载体Gherkin (.feature 文件)Markdown (SPEC.md)
谁读测试框架 + 人Agent + 人
谁写
谁实现Agent
验收跑 Cucumber跑 EVALS

BDD 的核心思想"用业务语言描述行为"被 Spec-Driven 继承。差别在实现者从人变成 Agent,所以 Spec-Driven 的 spec 要更结构化、更明确边界。


4.9 课后练习

  1. 找一个你最近做的功能,写一份任务级 spec,包含目标、范围、约束、5 条 SMART 验收标准。
  2. 把下面这段模糊 prompt 改写成 spec:"帮我做一个用户登录功能,要安全,体验好"。至少 5 条验收标准。
  3. 解释为什么"spec 写成产品文档"是反模式。产品文档和 spec 各自该写什么?
  4. 设计一个机制:让 Agent 在实现过程中发现 spec 错了,能主动提示人改 spec,而不是绕过 spec。
  5. 对比 Spec-Driven 和 TDD:在 Agent 时代,两者应该结合还是互斥?写出你的理由。

4.10 小结

  • Spec Engineering 是把需求固化成可验证规格的工程方法,比 Prompt Engineering 更适合 Agent 时代。
  • Spec 四要素:目标、需求、约束、验收标准。
  • Spec 三层:项目级(Why)、模块级(What)、任务级(Which)。
  • 验收标准 SMART:具体、可测、可达、相关、有时限。
  • 给 Agent 写 Spec 五技巧:明确做/不做、给约束写理由、给参考实现、标优先级、写完成定义。
  • Spec-Driven Development:写 spec → Agent 拆任务 → Agent 实现 → 跑 EVALS → 不通过则改 spec 或改实现。
  • 核心命题:Agent 的能力上限由模型决定,实际表现由 spec 决定

下一章讲 Context Engineering——Agent 的工作记忆怎么管,为什么塞满 context 反而更差,怎么用 Context Rot / Compression / Subagent 让 Agent 保持清晰。

基于 CC BY-SA 4.0 发布