Spec 该怎么写,才能让 AI 可靠执行?GEARS 格式详解
亚马逊的编程智能体 Kiro 在其规约驱动开发(SDD)流程中采用了 EARS——Easy Approach to Requirements Syntax,简明需求语法。越来越多的 AI 软件开发实践,把模糊的提示词或上下文表达为格式清晰的规约(spec),让人和智能体都能更好理解。
EARS 由 Alistair Mavin 和罗尔斯-罗伊斯(Rolls-Royce PLC)的同事们提出,经过多年广泛应用,已成为编写清晰可测的需求条目的常用格式。其原始论文获得了 2019 年 IEEE 国际需求工程大会“十年最具影响力产业论文奖”。
然而,这套格式最初是面向需求方设计的,并未覆盖 AI 原生软件开发所需的完整规约体系。在实际规约驱动开发的实践中,直接使用 EARS 会暴露出一些局限。
因此,我们提出 GEARS——Generalized EARS,或 Generalized Expression for AI-Ready Specs(AI 就绪的规约通用表达式),在保留 EARS 成功要素的同时,扩展其语法以适配 AI 时代更广泛的规约实践。
什么是规约
规约是对系统需求和行为的自然语言描述。规约应当被版本管理,并与代码保持“最终一致”,从而成为 AI 理解系统的主要事实来源。从广义来看,规约也可以描述对系统做出的决策、计划与变更,但 GEARS 语法不覆盖这些辅助信息,因其在智能体的提示词或上下文中较少被引用。
规约是人类开发者新的“源代码”。我们认为,规约对 AI 原生软件开发至关重要,原因有二:
- 没有清晰的规约,人与大语言模型(LLM)之间、人与人之间的误解就会持续存在。规约是人类开发者和 AI 之间沟通的自然语言载体。
- 即便有 AI 的能力加持,软件开发中仍然存在分工。清晰的规约有助于人和智能体理解并复用系统的各个组件。
规约是迭代式的。SDD 并不是回归瀑布模型。规约通常与代码一起,从零起步、逐次迭代、不断累积。
规约可以由 AI 生成。SDD 也不意味着每一行规约都要由人来写。通常,人类开发者从高层的、有时甚至模糊的意图出发,与 AI 讨论;随后 AI 可以协助澄清要求、提出注意事项、补全细节,最后以合适的格式落笔成文。
为什么使用 GEARS
AI 需要一致性。结构可预期时,LLM 表现更好。规约格式充当了人类意图与智能体执行之间的协议。缺少这一协议,误解就会在多轮迭代中扩散,带来不稳定和风险。
人类同样需要 GEARS;AI 编码的瓶颈很少在智能体的能力本身,而在于我们能否清晰表达自己想要什么。受限的语法反而带来清晰:不要用自由“散文体”描述需求,让结构帮助我们表达更准确。
AI 降低了应用最佳实践的成本。GEARS 刻意保持轻量、直观,无需繁琐的工具或培训。规范化格式、完整测试用例、可追溯需求等都很有价值,但实现成本较高。而当我们可以让 AI 起草、人类只负责评审时,成本-收益的比率就会发生显著变化。
另外,测试用例最好使用同一套语言。原始的 EARS 面向需求;测试框架则可能使用 BDD(行为驱动开发)风格的 Given-When-Then。维持两套认知模型会增加 LLM 的负担。GEARS 在同一语法下统一了两者。
GEARS 语法
[给定 `<静态前置条件>`]
[如果 `<状态前置条件>`]
[当 `<触发条件>`]
`<主体>` 应 `<行为>`
| 关键字 | 含义 | 对应 GWT |
|---|---|---|
| 给定/Where | 静态前置条件——配置、特性开关、环境 | Given/给定(设置) |
| 如果/While | 状态前置条件——执行期间必须成立的条件 | Given/给定(状态) |
| 当/When | 触发条件——引发行为的事件 | When/当 |
| 应/shall | 所要求的行为——主体必须做的事 | Then/那么 |
方括号表示可选子句。原 EARS 之所以使用“系统应……”,是因为它针对系统级需求。GEARS 把它替换为 <主体>——任意名词:系统、组件、服务、智能体、函数、产物。这样就允许在各种系统层级和粒度上表达规约。
原 EARS 根据出现的关键字定义了五种模式:
| 模式 | EARS 语法(被 GEARS 合并) |
|---|---|
| 普适(Ubiquitous) | The <system> shall <response> |
| 状态驱动(State-driven) | While <precondition>, the <system> shall <response> |
| 事件驱动(Event-driven) | When <trigger>, the <system> shall <response> |
| 可选特性(Optional feature) | Where <feature>, the <system> shall <response> |
| 非预期行为(Unwanted behavior) | If <trigger>, then the <system> shall <response> |
GEARS 把这些都合并为一个统一模式,其差异由出现哪些可选子句来体现。这种抽象同时降低了 LLM 的认知负担和 token 成本。
“非预期行为”的模式需要注意。EARS 用 If...then 的不同格式在视觉上突出其为边界情况;GEARS 取消了这一区分,直接使用“不应……”。从结构上看,错误处理也只是一组触发-响应。“非预期”属于语义层面,而不属于语法层面。GEARS 优先考虑 AI 处理,而不是人眼扫读。
原 EARS 用 “where” 表示可选特性,用 “while” 表示状态。GEARS 保留这两个关键字,但把语义规定得更清楚:
- 给定/where 表示静态前置条件(配置、部署环境、特性开关);
- 如果/while 表示状态前置条件(运行期可能变化的条件)。
区分示例:
给定部署环境为生产环境,当请求失败时,服务应使用指数退避进行重试。
如果熔断器处于打开状态,当请求到达时,服务应返回缓存响应。
第一句是配置——执行期间不会改变;第二句是状态——可能在任意时刻发生转移。
GEARS 示例
-
普适:
<主体>应<行为>。手机的质量应小于 150 克。
-
状态驱动:如果
<状态前置条件>,<主体>应<行为>。如果未插入银行卡,ATM 应显示“请插入银行卡”。
-
事件驱动:当
<触发条件>,<主体>应<行为>。当用户选择静音时,音频控制器应抑制所有输出。
当缓存超过 80% 容量时,淘汰策略应移除最近最少使用的条目,直到容量降至 60% 以下。
-
可选特性:给定
<静态前置条件>,<主体>应<行为>。给定车辆安装了天窗,车辆应在驾驶员侧车门上包含天窗控制装置。
-
复合(状态 + 事件)
给定用户已授予文件系统访问权限,当用户请求生成代码时,编程智能体应把输出写入指定目录。
-
错误处理
当输入无效信用卡号时,支付表单应显示“请重新输入信用卡信息”。
-
否定式表达
当未经身份验证的请求到达时,API 不应在响应中包含堆栈跟踪。
-
测试用例
给定用户已通过身份验证
且会话处于活动状态
当用户请求自己的个人资料
那么 API 返回用户的个人资料数据转写为 GEARS:
如果用户已通过身份验证且会话处于活动状态,当用户请求自己的个人资料时,API 应返回用户的个人资料数据。
应用
要让 LLM 理解 GEARS 并据此写规约,只需把下面这段文字放进你的提示词,或 CLAUDE.md / AGENTS.md 文件即可。
每条规约应遵从[GEARS](https://sublang.ai/zh/ref/gears-ai-ready-spec-syntax/)格式:
[给定 `<静态前置条件>`] [如果 `<状态前置条件>`] [当 `<触发条件>`] `<主体>` 应 `<行为>`。
| 子句 | 用途 | 示例 |
| ------ | ------- | ------- |
| 给定/Where | 静态前置条件(特性、配置) | 给定调试模式已启用 |
| 如果/While | 状态前置条件(运行时状态) | 如果连接处于活动状态 |
| 当/When | 触发事件(最多一个) | 当用户点击提交 |
| 应/shall | 所要求的行为 | 表单应校验输入 |
注意:子句关键字和标点遵循自然语言惯例。
测试规约应使用同一模式,并映射 Given-When-Then:
| GWT | 子句 |
| --- | ------ |
| Given/给定 | 给定/Where + 如果/While |
| When/当 | 当/When |
| Then/那么 | 应/shall |
要把 GEARS 应用到你的项目中,我们准备了一个脚手架工具:
npm install -g @sublang/spex
spex scaffold --lang zh
运行上述命令后,你会得到如下结构的 specs 目录:
specs/
├── decisions/ # 决策记录(DRs)
├── iterations/ # 迭代记录(IRs)
├── user/ # 用户可见行为规约
├── dev/ # 系统内部行为规约
└── test/ # 测试验证规约
规约文件可以按目录层级组织。记录类文件(DR 和 IR)并不严格遵循 GEARS。
⭐ 如果你觉得这个工具有帮助,欢迎给 https://github.com/sublang-ai/spex 点个 Star,持续关注更新 💜
总结
GEARS 在四个方面扩展了 EARS:
- 通用化主体:用任意名词——系统、组件、智能体、产物——替代“系统”,适配规约更广泛的应用范围。
- 统一模式:一套语法覆盖所有情况;不再为特性、状态、事件、错误设置不同模式,减少 LLM 认知负担和 token 成本。
- 明确的前置条件:给定/Where 表示静态配置,如果/While 表示状态条件,有助消除语义模糊。
- 测试用例的等价表达:语法可以直接映射到 Given-When-Then,无需为规约和测试维护两套语言。
由此得到的规约语法,为 AI 原生软件开发而生:足够一致让 LLM 能可靠解析,足够有表达力让人或智能体能自然书写,足够统一让规约与测试描述合而为一。
参考文献
- Mavin, A., Wilkinson, P., Harwood, A., & Novak, M. (2009). Easy Approach to Requirements Syntax (EARS). 17th IEEE International Requirements Engineering Conference, pp. 317–322. https://doi.org/10.1109/RE.2009.9
- Mavin, A. (2009). Easy Approach to Requirements Syntax (EARS). https://alistairmavin.com/ears
- North, D. (2006). Introducing BDD. https://dannorth.net/introducing-bdd/
AI 使用声明:本文原稿由人撰写,Claude Opus 4.5 与 GPT-5.2 仅用于语言润色。