如何为 AI 代理编写优秀的规范
摘要
学习如何为 AI 编码代理编写有效的规范,以提高 AI 驱动开发工作流程中的清晰度、专注度和生产力。
TL;DR: 目标是编写一个清晰的规范,涵盖足够的细节(这可能包括结构、风格、测试、边界)来指导 AI,而不会让它不堪重负。将大型任务分解为较小的任务,而不是将所有内容保留在一个大型提示中。首先在只读模式下进行规划,然后执行并持续迭代。
"我听说过很多关于为 AI 代理编写优秀规范的内容,但还没有找到一个可靠的框架。我可以编写一个媲美 RFC 的规范,但在某个时候上下文太大,模型就会崩溃。"
许多开发者都有这种挫败感。简单地向 AI 代理抛出一个庞大的规范是行不通的——上下文窗口限制和模型的"注意力预算"会妨碍它。关键是编写智能规范:清晰地指导代理、保持在实际上下文大小范围内并随项目演变的文档。本指南将我使用包括 Claude Code 和 Gemini CLI 在内的编码代理的最佳实践提炼成一个规范编写框架,让你的 AI 代理保持专注和高效。
我们将介绍优秀 AI 代理规范的五个原则,每个原则都以粗体要点开头。
1. 从高层次愿景开始,让 AI 起草细节
用简洁的高层次规范启动你的项目,然后让 AI 将其扩展为详细计划。
与其过度设计前期工作,不如从一个清晰的目标陈述和几个核心需求开始。将其视为"产品简报",让代理从中生成更详细的规范。这利用了 AI 在细化方面的优势,同时你保持对方向的控制。除非你已经觉得从一开始就必须满足非常具体的技术要求,否则这种方法效果很好。
为什么这有效: 基于 LLM 的代理在给定坚实的高层次指令时擅长充实细节,但它们需要清晰的使命以避免偏离轨道。通过提供简短的大纲或目标描述并要求 AI 生成完整的规范(例如 spec.md),你可以为代理创建一个持久的参考。提前规划对代理来说更加重要——你可以先迭代计划,然后将其交给代理编写代码。规范成为你和 AI 共同构建的第一个工件。
实用方法: 通过提示开始新的编码会话:"你是一名 AI 软件工程师。为 [项目 X] 起草一份详细的规范,涵盖目标、功能、约束和分步计划。" 保持你的初始提示高层次——例如"构建一个 Web 应用程序,用户可以在其中跟踪任务(待办事项列表),包含用户账户、数据库和简单的 UI"。代理可能会响应一个结构化的规范草案:概述、功能列表、技术栈建议、数据模型等。然后,这个规范成为你和代理都可以参考的"真相来源"。GitHub 的 AI 团队推广规范驱动开发,其中"规范成为共享的真相来源……随项目演变的活的、可执行的工件"。在编写任何代码之前,审查并完善 AI 的规范。确保它与你的愿景一致,并纠正任何幻觉或偏离目标的细节。
使用计划模式强制执行规划优先: 像 Claude Code 这样的工具提供计划模式,将代理限制为只读操作——它可以分析你的代码库并创建详细计划,但在你准备好之前不会编写任何代码。这对于规划阶段来说是理想的:在计划模式下开始(Claude Code 中按 Shift+Tab),描述你想要构建的内容,让代理在探索你现有代码的同时起草规范。要求它通过询问你关于计划的问题来澄清歧义。让它审查计划的架构、最佳实践、安全风险和测试策略。目标是完善计划,直到没有误解的余地。只有这样,你才退出计划模式并让代理执行。这个工作流程防止了在规范稳固之前直接跳入代码生成的常见陷阱。
将规范用作上下文: 一旦获得批准,保存此规范(例如作为 SPEC.md)并根据需要将相关部分提供给代理。许多使用强大模型的开发者正是这样做的——规范文件在会话之间持久存在,每当项目工作恢复时都会锚定 AI。这减轻了当对话历史变得太长或当你必须重新启动代理时可能发生的健忘。这类似于在团队中使用产品需求文档(PRD)的方式:每个人(人类或 AI)都可以参考以保持在正轨上的参考。有经验的人经常"首先编写良好的文档,模型可能能够仅从该输入构建匹配的实现",正如一位工程师所观察到的。规范就是那个文档。
保持目标导向: AI 代理的高层次规范应该更多地关注什么和为什么,而不是细节如何(至少最初是这样)。把它想象成用户故事和验收标准:用户是谁?他们需要什么?成功是什么样子?(例如"用户可以添加、编辑、完成任务;数据持久保存;应用程序响应迅速且安全")。这使 AI 的详细规范植根于用户需求和结果,而不仅仅是技术待办事项。正如 GitHub Spec Kit 文档所说,提供你正在构建什么以及为什么的高层次描述,让编码代理生成专注于用户体验和成功标准的详细规范。从这个大局愿景开始可以防止代理在后来进入编码时只见树木不见森林。
2. 像专业 PRD(或 SRS)一样构建规范
将你的 AI 规范视为具有清晰部分的结构化文档(PRD),而不是松散的笔记堆。
许多开发者将代理的规范视为传统的产品需求文档(PRD)或系统设计文档——全面、组织良好且易于"字面意义"的 AI 解析。这种正式方法为代理提供了要遵循的蓝图并减少了歧义。
六个核心领域: GitHub 对超过 2,500 个代理配置文件的分析揭示了一个清晰的模式:最有效的规范涵盖六个领域。将此用作完整性检查清单:
1. 命令: 尽早放置可执行命令——不仅仅是工具名称,而是带有标志的完整命令:npm test、pytest -v、npm run build。代理将不断引用这些。
2. 测试: 如何运行测试、使用什么框架、测试文件在哪里以及存在什么覆盖率期望。
3. 项目结构: 源代码在哪里、测试放在哪里、文档属于哪里。明确说明:"src/ 用于应用程序代码,tests/ 用于单元测试,docs/ 用于文档。"
4. 代码风格: 一个展示你风格的真实代码片段胜过三段描述它的文字。包括命名约定、格式规则和良好输出的示例。
5. Git 工作流: 分支命名、提交消息格式、PR 要求。如果你明确说明,代理可以遵循这些。
6. 边界: 代理永远不应该触碰的内容——秘密、供应商目录、生产配置、特定文件夹。"永远不要提交秘密"是 GitHub 研究中最常见的有用约束。
对你的技术栈要具体: 说"React 18 with TypeScript, Vite, and Tailwind CSS"而不是"React 项目"。包括版本和关键依赖项。模糊的规范产生模糊的代码。
使用一致的格式: 清晰度是王道。许多开发者在规范中使用 Markdown 标题甚至类似 XML 的标签来划分部分,因为 AI 模型处理结构良好的文本比自由形式的散文更好。例如,你可以将规范结构化为:
# 项目规范:我的团队任务应用
## 目标
- 为小团队构建一个管理任务的 Web 应用...
## 技术栈
- React 18+, TypeScript, Vite, Tailwind CSS
- Node.js/Express 后端, PostgreSQL, Prisma ORM
## 命令
- 构建: `npm run build` (编译 TypeScript,输出到 dist/)
- 测试: `npm test` (运行 Jest,提交前必须通过)
- Lint: `npm run lint --fix` (自动修复 ESLint 错误)
## 项目结构
- `src/` – 应用程序源代码
- `tests/` – 单元和集成测试
- `docs/` – 文档
## 边界
- ✅ 始终: 提交前运行测试,遵循命名约定
- ⚠️ 先询问: 数据库架构更改,添加依赖项
- 🚫 永不: 提交秘密,编辑 node_modules/,修改 CI 配置这种组织级别不仅帮助你清晰思考,还帮助 AI 查找信息。Anthropic 工程师建议将提示组织成不同的部分(如 <background>、<instructions>、<tools>、<output_format> 等),正是出于这个原因——它为模型提供了关于哪些信息是什么的强烈提示。记住,"最小并不一定意味着简短"——如果重要,不要回避规范中的细节,但要保持专注。
将规范集成到你的工具链中: 将规范视为与版本控制和 CI/CD 相关联的"可执行工件"。GitHub Spec Kit 使用四阶段门控工作流程,使你的规范成为工程流程的中心。规范不是编写后就放在一边,而是驱动实现、检查清单和任务分解。你的主要角色是引导;编码代理完成大部分编写工作。每个阶段都有特定的工作,在当前任务完全验证之前,你不会进入下一个阶段:

1. 指定: 你提供你正在构建什么以及为什么的高层次描述,编码代理生成详细的规范。这不是关于技术栈或应用设计——而是关于用户旅程、体验以及成功是什么样子。谁将使用它?它解决什么问题?他们将如何与之交互?把它想象成映射你想要创建的用户体验,让编码代理充实细节。这成为一个随着你了解更多而演变的活工件。
2. 规划: 现在你变得技术化。你提供所需的技术栈、架构和约束,编码代理生成全面的技术计划。如果你的公司标准化某些技术,这就是你说出来的地方。如果你正在与遗留系统集成或有合规要求,所有这些都在这里。你可以要求多个计划变体来比较方法。如果你提供内部文档,代理可以直接将你的架构模式集成到计划中。
3. 任务: 编码代理获取规范和计划,并将它们分解为实际工作——小的、可审查的块,每个块解决难题的特定部分。每个任务都应该是你可以独立实现和测试的东西,几乎就像为你的 AI 代理进行测试驱动开发。你不会得到"构建身份验证",而是得到具体的任务,如"创建一个验证电子邮件格式的用户注册端点"。
4. 实现: 你的编码代理逐个(或并行)处理任务。你不是审查数千行代码转储,而是审查解决特定问题的集中更改。代理知道要构建什么(规范)、如何构建(计划)以及要做什么(任务)。至关重要的是,你的角色是在每个阶段进行验证:规范是否捕获了你想要的?计划是否考虑了约束?AI 是否遗漏了边缘情况?该流程在每个阶段都内置了检查点,供你批评、发现差距并在前进之前纠正方向。
这种门控工作流程防止了 Willison 所说的"纸牌屋代码"——在审查下崩溃的脆弱 AI 输出。Anthropic 的技能系统提供了类似的模式,让你定义代理调用的可重用的基于 Markdown 的行为。通过将你的规范嵌入这些工作流程中,你可以确保在规范验证之前代理无法继续,并且更改会自动传播到任务分解和测试。
考虑 agents.md 用于专门角色: 对于像 GitHub Copilot 这样的工具,你可以创建 agents.md 文件来定义专门的代理角色——用于技术写作的 @docs-agent、用于 QA 的 @test-agent、用于代码审查的 @security-agent。每个文件都充当该角色行为、命令和边界的集中规范。当你想要针对不同任务使用不同的代理而不是一个通用助手时,这特别有用。
为代理体验(AX)设计: 正如我们为开发者体验(DX)设计 API 一样,考虑为"代理体验"设计规范。这意味着干净、可解析的格式:代理将使用的任何 API 的 OpenAPI 模式、为 LLM 使用总结文档的 llms.txt 文件以及显式类型定义。代理 AI 基金会(AAIF)正在标准化像 MCP(模型上下文协议)这样的工具集成协议——遵循这些模式的规范更容易被代理可靠地使用和操作。
PRD vs SRS 思维方式: 借鉴既定的文档实践会有所帮助。对于 AI 代理规范,你通常会将这些混合到一个文档中(如上所示),但涵盖两个角度对你很有帮助。像 PRD 一样编写它可以确保你包含以用户为中心的上下文("每个功能背后的原因"),这样 AI 就不会为错误的事情优化。像 SRS 一样扩展它可以确保你确定 AI 实际生成正确代码所需的具体内容(如使用什么数据库或 API)。开发者发现,这种额外的前期努力通过大幅减少与代理的误解而得到回报。
使规范成为"活文档": 不要写完就忘记它。随着你和代理做出决策或发现新信息,更新规范。如果 AI 必须更改数据模型或你决定削减功能,请在规范中反映这一点,以便它保持基本事实。把它想象成版本控制的文档。在规范驱动工作流程中,规范驱动实现、测试和任务分解,在规范验证之前你不会进入编码。这种习惯使项目保持连贯,特别是如果你或代理离开后再回来。记住,规范不仅仅是为 AI 准备的——它帮助你作为开发者保持监督并确保 AI 的工作满足真正的需求。
3. 将任务分解为模块化提示和上下文,而不是一个大提示
分而治之:一次给 AI 一个集中的任务,而不是一次性包含所有内容的单体提示。
有经验的 AI 工程师已经了解到,试图将整个项目(所有需求、所有代码、所有指令)塞进单个提示或代理消息中是混乱的配方。你不仅有触及令牌限制的风险,还有由于"指令诅咒"而导致模型失去焦点的风险——太多指令导致它无法很好地遵循任何一个。解决方案是以模块化方式设计你的规范和工作流程,一次处理一个部分,只引入该部分所需的上下文。

过多上下文/指令的诅咒: 研究证实了许多开发者轶事所见:当你在提示中堆积更多指令或数据时,模型遵守每个指令的性能显著下降。一项研究将此称为"指令诅咒",表明即使是 GPT-4 和 Claude 在被要求同时满足许多要求时也会挣扎。实际上,如果你提出 10 个详细规则的要点,AI 可能会遵守前几个并开始忽略其他的。更好的策略是迭代聚焦。行业指南建议将复杂需求分解为顺序的、简单的指令作为最佳实践。一次让 AI 专注于一个子问题,完成后再继续。这保持了高质量并使错误可管理。
将规范划分为阶段或组件: 如果你的规范文档非常长或涵盖很多内容,考虑将其分成几部分(物理上分开的文件或明确分开的部分)。例如,你可能有一个"后端 API 规范"部分和另一个"前端 UI 规范"部分。当它在后端工作时,你不需要总是向 AI 提供前端规范,反之亦然。许多使用多代理设置的开发者甚至为每个部分创建单独的代理或子流程——例如一个代理处理数据库/模式,另一个处理 API 逻辑,另一个处理前端——每个都有规范的相关切片。即使你使用单个代理,你也可以通过仅将相关规范部分复制到该任务的提示中来模拟这一点。避免上下文过载:不要在一次操作中混合身份验证任务和数据库架构更改,正如 DigitalOcean AI 指南所警告的。保持每个提示紧密围绕当前目标。
大型规范的扩展目录/摘要: 一个聪明的技巧是让代理为规范构建带有摘要的扩展目录。这本质上是一个"规范摘要",将每个部分浓缩为几个关键点或关键词,并引用可以找到详细信息的位置。例如,如果你的完整规范有一个跨越 500 字的"安全要求"部分,你可能让代理将其总结为:"安全:使用 HTTPS,保护 API 密钥,实施输入验证(见完整规范 §4.2)"。通过在规划阶段创建分层摘要,你可以获得可以保留在提示中的鸟瞰图,而细节则保持卸载,除非需要。这个扩展的目录充当索引:代理可以查阅它并说"啊哈,有一个我应该看的安全部分",然后你可以按需提供该部分。这类似于人类开发者浏览大纲,然后在处理特定部分时翻到规范文档的相关页面。
要实现这一点,你可以在编写规范后提示代理:"将上述规范总结为一个非常简洁的大纲,包含每个部分的关键点和参考标签。" 结果可能是一个部分列表,每个部分有一两句摘要。该摘要可以保留在系统或助手消息中,以指导代理的焦点,而不会占用太多令牌。这种分层总结方法已知通过关注高层次结构来帮助 LLM 维护长期上下文。代理携带规范的"心智地图"。
利用子代理或"技能"处理不同的规范部分: 另一种高级方法是使用多个专门的代理(Anthropic 称之为子代理或你可能称之为"技能")。每个子代理都配置为特定的专业领域,并获得与该领域相关的规范部分。例如,你可能有一个数据库设计师子代理,它只知道规范的数据模型部分,以及一个 API 编码器子代理,它知道 API 端点规范。主代理(或编排器)可以自动将任务路由到适当的子代理。好处是每个代理都有一个更小的上下文窗口要处理和一个更集中的角色,这可以提高准确性并允许对独立任务进行并行工作。Anthropic 的 Claude Code 通过让你定义具有自己的系统提示和工具的子代理来支持这一点。"每个子代理都有特定的目的和专业领域,使用与主对话分离的自己的上下文窗口,并有指导其行为的自定义系统提示,"正如他们的文档所描述的。当出现与子代理领域匹配的任务时,Claude 可以将该任务委托给它,子代理独立返回结果。
用于吞吐量的并行代理: 同时运行多个代理正在成为开发者生产力的"下一个大事件"。你可以为非重叠工作启动并行代理,而不是等待一个代理完成后再开始另一个任务。Willison 将此描述为"拥抱并行编码代理",并指出它"令人惊讶地有效,如果精神上令人疲惫"。关键是确定任务范围,使代理不会相互干扰——一个代理编写功能代码,而另一个编写测试,或者同时构建单独的组件。像 LangGraph 或 OpenAI Swarm 这样的编排框架可以帮助协调这些代理,通过向量数据库(如 Chroma)的共享内存让它们访问公共上下文,而无需冗余提示。
单代理 vs. 多代理:何时使用每种
| 方面 | 单代理 | 并行/多代理 |
|---|---|---|
| 优势 | 设置更简单;开销更低;更容易调试和跟踪 | 更高的吞吐量;处理复杂的相互依赖关系;每个领域的专家 |
| 挑战 | 大型项目上的上下文过载;迭代较慢;单点故障 | 协调开销;潜在冲突;需要共享内存(例如向量数据库) |
| 最适合 | 隔离模块;中小型项目;早期原型设计 | 大型代码库;一个编码 + 一个测试 + 一个审查;独立功能 |
| 提示 | 使用规范摘要;每个任务刷新上下文;经常开始新会话 | 最初限制为 2-3 个代理;使用 MCP 进行工具共享;定义明确的边界 |
在实践中,使用子代理或特定技能的提示可能看起来像:你维护多个规范文件(或提示模板)——例如 SPEC_backend.md、SPEC_frontend.md——你告诉 AI,"对于后端任务,参考 SPEC_backend;对于前端任务参考 SPEC_frontend。" 或者在像 Cursor/Claude 这样的工具中,你实际上为每个启动一个子代理。这肯定比单代理循环设置更复杂,但它模仿了人类开发者所做的——我们在心理上将大型规范划分为相关块(你不会一次将整个 50 页规范保留在脑海中;你回忆手头任务所需的部分,并对整体架构有一般的了解)。如前所述,挑战是管理相互依赖关系:子代理仍然必须协调(前端需要知道后端规范的 API 合同等)。中央概述(或"架构师"代理)可以通过引用子规范并确保一致性来提供帮助。
将每个提示集中在一个任务/部分上: 即使没有花哨的多代理设置,你也可以手动强制执行模块化。例如,在编写规范后,你的下一步可能是:"步骤 1:实现数据库架构。" 你只向代理提供规范的数据库部分,加上规范中的任何全局约束(如技术栈)。代理处理这个。然后对于步骤 2,"现在实现身份验证功能",你提供规范的身份验证部分,如果需要,可能还有架构的相关部分。通过为每个主要任务刷新上下文,你可以确保模型不会携带大量可能分散注意力的陈旧或不相关的信息。正如一份指南所建议的:"重新开始:开始新会话以在主要功能之间切换时清除上下文"。你总是可以每次提醒代理关键的全局规则(来自规范的约束部分),但如果不是全部需要,不要塞入整个规范。
使用内联指令和代码 TODO: 另一个模块化技巧是使用你的代码或规范作为对话的活跃部分。例如,用描述需要做什么的 // TODO 注释搭建你的代码,让代理逐个填充它们。每个 TODO 本质上充当小任务的迷你规范。这使 AI 保持激光聚焦("根据此规范片段实现此特定功能"),你可以在紧密循环中迭代。这类似于给 AI 一个检查清单项目来完成,而不是一次性给出整个检查清单。
底线:小的、集中的上下文胜过一个巨大的提示。这提高了质量并防止 AI 一次被太多东西"压倒"。正如一套最佳实践所总结的,向模型提供"一个任务焦点"和"仅相关信息",避免到处倾倒所有内容。通过将工作结构化为模块——并使用规范摘要或子规范代理等策略——你将绕过上下文大小限制和 AI 的短期记忆上限。记住,一个喂养良好的 AI 就像一个喂养良好的函数:只给它手头工作所需的输入。
4. 内置自检、约束和人类专业知识
使你的规范不仅仅是代理的待办事项列表,还是质量控制指南——不要害怕注入你自己的专业知识。
一个好的 AI 代理规范会预测 AI 可能出错的地方并设置护栏。它还利用你所知道的(领域知识、边缘情况、"陷阱"),这样 AI 就不会在真空中运作。把规范想象成 AI 的教练和裁判:它应该鼓励正确的方法并指出犯规。
使用三层边界: GitHub 对 2,500+ 代理文件的分析发现,最有效的规范使用三层边界系统,而不是简单的禁止列表。这为代理提供了更清晰的指导,说明何时继续、何时暂停以及何时停止:

✅ 始终做: 代理应该在不询问的情况下采取的行动。"始终在提交前运行测试。" "始终遵循风格指南中的命名约定。" "始终将错误记录到监控服务。"
⚠️ 先询问: 需要人工批准的行动。"修改数据库架构前先询问。" "添加新依赖项前先询问。" "更改 CI/CD 配置前先询问。" 这一层捕获可能没问题但需要人工检查的高影响更改。
🚫 永不: 硬停止。"永远不要提交秘密或 API 密钥。" "永远不要编辑 node_modules/ 或 vendor/。" "未经明确批准,永远不要删除失败的测试。" "永远不要提交秘密"是研究中最常见的有用约束。
这种三层方法比扁平的规则列表更细致。它承认某些行动总是安全的,某些需要监督,某些是绝对禁止的。代理可以自信地继续"始终"项目,标记"先询问"项目以供审查,并在"永不"项目上硬停止。
鼓励自我验证: 一个强大的模式是让代理自动根据规范验证其工作。如果你的工具允许,你可以集成 AI 在生成代码后可以运行的单元测试或 linting 等检查。但即使在规范/提示级别,你也可以指示 AI 进行双重检查:例如"实现后,将结果与规范进行比较并确认满足所有要求。列出任何未解决的规范项目。" 这推动 LLM 反思其相对于规范的输出,捕获遗漏。这是内置于流程中的一种自我审计形式。
例如,你可以在提示后附加:"(编写函数后,审查上述需求列表并确保满足每个需求,标记任何缺失的需求)。" 然后模型将(理想情况下)输出代码,然后是一个简短的检查清单,指示它是否满足每个要求。这减少了在你甚至运行测试之前它忘记某些东西的机会。这不是万无一失的,但它有帮助。
LLM 作为主观检查的评判者: 对于难以自动测试的标准——代码风格、可读性、对架构模式的遵守——考虑使用"LLM 作为评判者"。这意味着让第二个代理(或单独的提示)根据你的规范的质量指南审查第一个代理的输出。Anthropic 和其他人发现这对主观评估有效。你可能会提示:"审查此代码是否遵守我们的风格指南。标记任何违规。" 评判者代理返回反馈,这些反馈要么被纳入,要么触发修订。这在语法检查之外增加了一层语义评估。
一致性测试: Willison 倡导构建一致性套件——任何实现都必须通过的与语言无关的测试(通常基于 YAML)。这些充当合同:如果你正在构建 API,一致性套件指定预期的输入/输出,代理的代码必须满足所有情况。这比临时单元测试更严格,因为它直接从规范派生,可以跨实现重用。在规范的成功部分包含一致性标准(例如,"必须通过 conformance/api-tests.yaml 中的所有情况")。
在规范中利用测试: 如果可能,在你的规范和提示流程中纳入测试计划甚至实际测试。在传统开发中,我们使用 TDD 或编写测试用例来澄清需求——你可以对 AI 做同样的事情。例如,在规范的成功标准中,你可能会说"这些示例输入应该产生这些输出……"或"以下单元测试应该通过。" 如果代理有该能力,可以提示它在脑海中运行这些情况或实际执行它们。Simon Willison 指出,拥有强大的测试套件就像给代理超能力——当测试失败时,它们可以快速验证和迭代。在 AI 编码上下文中,在规范中为测试或预期结果编写一些伪代码可以指导代理的实现。此外,你可以在子代理设置中使用专用的"测试代理",它采用规范的标准并持续验证"代码代理"的输出。
带来你的领域知识: 你的规范应该反映只有有经验的开发者或有上下文的人才知道的见解。例如,如果你正在构建电子商务代理,并且你知道"产品"和"类别"具有多对多关系,请明确说明(不要假设 AI 会推断它——它可能不会)。如果某个库出了名的棘手,请提及要避免的陷阱。本质上,将你的指导倾注到规范中。规范可以包含诸如"如果使用库 X,请注意版本 Y 中的内存泄漏问题(应用解决方法 Z)"之类的建议。这种细节水平将平均的 AI 输出转变为真正强大的解决方案,因为你已经引导 AI 远离常见陷阱。
此外,如果你有偏好或风格指南(比如,"在 React 中使用函数组件而不是类组件"),请在规范中编码。然后 AI 将模仿你的风格。许多工程师甚至在规范中包含小示例,例如,"所有 API 响应都应该是 JSON。例如 {"error": "message"} 用于错误。" 通过给出一个快速示例,你将 AI 锚定到你想要的确切格式。
简单任务的极简主义: 虽然我们提倡彻底的规范,但专业知识的一部分是知道何时保持简单。对于相对简单、孤立的任务,过于繁重的规范实际上可能会造成更多混乱而不是帮助。如果你要求代理做一些简单的事情(比如"在页面上居中一个 div"),你可能只需说,"确保保持解决方案简洁,不要添加无关的标记或样式。" 那里不需要完整的 PRD。相反,对于复杂的任务(如"实现带有令牌刷新和错误处理的 OAuth 流程"),那就是你拿出详细规范的时候。一个好的经验法则:根据任务复杂性调整规范细节。不要对困难问题规范不足(代理会失败或偏离轨道),但也不要对琐碎问题过度规范(代理可能会纠缠或在不必要的指令上使用上下文)。
如果需要,维护 AI 的"角色": 有时,你的规范的一部分是定义代理应该如何行为或响应,特别是如果代理与用户交互。例如,如果构建客户支持代理,你的规范可能包括诸如"使用友好和专业的语气"、"如果你不知道答案,请要求澄清或提供跟进,而不是猜测"之类的指南。这些规则(通常包含在系统提示中)有助于使 AI 的输出与期望保持一致。它们本质上是 AI 行为的规范项目。保持它们一致,如果需要,在长会话中提醒模型(如果不加以控制,LLM 可能会在风格上"漂移")。
你仍然是循环中的执行者: 规范赋予代理权力,但你仍然是最终的质量过滤器。如果代理产生的东西在技术上符合规范但感觉不对,请相信你的判断。要么完善规范,要么直接调整输出。AI 代理的伟大之处在于它们不会被冒犯——如果它们提供的设计偏离了,你可以说,"实际上,那不是我的意图,让我们澄清规范并重做。" 规范是与 AI 协作的活工件,而不是你无法更改的一次性合同。
Simon Willison 幽默地将与 AI 代理合作比作"一种非常奇怪的管理形式",甚至"从编码代理那里获得良好结果令人不安地接近管理人类实习生"。你需要提供清晰的指令(规范),确保他们拥有必要的上下文(规范和相关数据),并提供可操作的反馈。规范设定了舞台,但执行期间的监控和反馈是关键。如果 AI 是"一个奇怪的数字实习生,如果你给他们机会,他们绝对会作弊",那么你编写的规范和约束就是你防止作弊并让他们专注于任务的方式。
这是回报:一个好的规范不仅告诉 AI 要构建什么,它还帮助它自我纠正并保持在安全边界内。通过融入验证步骤、约束和你来之不易的知识,你大大增加了代理输出第一次就正确(或至少更接近正确)的几率。这减少了迭代和那些"它到底为什么这样做?"的时刻。
将规范编写和代理构建视为迭代循环:尽早测试、收集反馈、完善规范并利用工具自动化检查。
初始规范不是结束——它是循环的开始。当你持续根据规范验证代理的工作并相应调整时,会产生最佳结果。此外,现代 AI 开发者使用各种工具来支持这个过程(从 CI 管道到上下文管理实用程序)。

持续测试: 不要等到最后才看代理是否满足规范。在每个主要里程碑之后,甚至每个函数之后,运行测试或至少进行快速手动检查。如果某些东西失败了,在继续之前更新规范或提示。例如,如果规范说"密码必须使用 bcrypt 哈希",而你看到代理的代码存储明文——停止并纠正它(并提醒规范或提示关于规则)。自动化测试在这里大放异彩:如果你提供了测试(或在进行时编写它们),让代理运行它们。在许多编码代理设置中,你可以让代理在完成任务后运行 npm test 或类似命令。结果(失败)然后可以反馈到下一个提示中,有效地告诉代理"你的输出在 X、Y、Z 上不符合规范——修复它。" 这种代理循环(代码 -> 测试 -> 修复 -> 重复)非常强大,是像 Claude Code 或 Copilot Labs 这样的工具正在发展以处理更大任务的方式。始终定义"完成"的含义(通过测试或标准)并检查它。
迭代规范本身: 如果你发现规范不完整或不清楚(也许代理误解了某些东西,或者你意识到你遗漏了一个需求),更新规范文档。然后明确地将代理与新规范重新同步:"我已按如下方式更新了规范……鉴于更新的规范,相应地调整计划或重构代码。" 这样规范仍然是唯一的真相来源。这类似于我们在正常开发中处理需求变更的方式——但在这种情况下,你也是 AI 代理的产品经理。如果可能,保留版本历史(即使只是通过提交消息或笔记),这样你就知道什么改变了以及为什么。
利用上下文管理和内存工具: 有一个不断增长的工具生态系统来帮助管理 AI 代理上下文和知识。例如,检索增强生成(RAG)是一种模式,代理可以根据需要从知识库(如向量数据库)中提取相关数据块。如果你的规范很大,你可以嵌入它的部分,让代理在需要时检索最相关的部分,而不是总是提供整个内容。还有一些框架实现了模型上下文协议(MCP),它根据当前任务自动向模型提供正确的上下文。一个例子是 Context7(context7.com),它可以根据你正在做的事情从文档中自动获取相关的上下文片段。实际上,这可能意味着代理注意到你正在处理"支付处理",它将你的规范或文档的"支付"部分拉入提示中。考虑利用这些工具或设置一个基本版本(即使是规范文档中的简单搜索)。
谨慎并行化: 一些开发者在不同任务上并行运行多个代理实例(如前面提到的子代理)。这可以加快开发速度——例如,一个代理生成代码,而另一个同时编写测试,或者同时构建两个功能。如果你走这条路,确保任务真正独立或明确分离以避免冲突(规范应该注明任何依赖关系)。例如,不要让两个代理同时写入同一个文件。一个工作流程是让一个代理生成代码,另一个并行审查它,或者让单独的组件构建后再集成。这是高级用法,管理起来可能会让人精神疲惫(正如 Willison 承认的,运行多个代理令人惊讶地有效,如果精神上令人疲惫!)。从最多 2-3 个代理开始以保持可管理性。
版本控制和规范锁定: 使用 Git 或你选择的版本控制来跟踪代理所做的事情。良好的版本控制习惯在 AI 辅助下更加重要。将规范文件本身提交到仓库。这不仅保留了历史,而且代理甚至可以使用 git diff 或 blame 来理解更改(LLM 非常擅长阅读差异)。一些高级代理设置让代理查询 VCS 历史以查看何时引入了某些东西——令人惊讶的是,模型可以"在 Git 方面非常有能力"。通过将你的规范保留在仓库中,你允许你和 AI 跟踪演变。有一些工具(如前面提到的 GitHub Spec Kit)将规范驱动开发集成到 git 工作流程中——例如,在更新的规范上门控合并或从规范项目生成检查清单。虽然你不需要这些工具来成功,但要点是像对待代码一样对待规范——勤奋地维护它。
成本和速度考虑: 使用大型模型和长上下文可能会很慢且昂贵。一个实用的技巧是明智地使用模型选择和批处理。也许使用更便宜/更快的模型进行初始草稿或重复,并为最终输出或复杂推理保留最有能力(和昂贵)的模型。一些开发者使用 GPT-4 或 Claude 进行规划和关键步骤,但将更简单的扩展或重构卸载到本地模型或更小的 API 模型。如果使用多个代理,也许不是所有代理都需要是顶级的;测试运行代理或 linter 代理可以是更小的模型。还要考虑限制上下文大小:如果 5k 就够了,不要提供 20k 令牌。正如我们讨论的,更多令牌可能意味着收益递减。
监控和记录所有内容: 在复杂的代理工作流程中,记录代理的操作和输出至关重要。检查日志以查看代理是否偏离或遇到错误。许多框架提供跟踪日志或允许打印代理的思维链(特别是如果你提示它逐步思考)。审查这些日志可以突出显示规范或指令可能被误解的地方。这与调试程序没有什么不同——除了"程序"是对话/提示链。如果发生奇怪的事情,回到规范/指令以查看是否存在歧义。
学习和改进: 最后,将每个项目视为完善规范编写技能的学习机会。也许你会发现某种措辞始终会混淆 AI,或者以某种方式组织规范部分会产生更好的遵守。将这些经验教训纳入下一个规范。AI 代理领域正在快速发展,因此新的最佳实践(和工具)不断涌现。通过博客(如 Simon Willison、Andrej Karpathy 等人的博客)保持更新,不要犹豫进行实验。
AI 代理的规范不是"写一次,完成"。它是指导、验证和完善的持续循环的一部分。这种勤奋的回报是可观的:通过尽早发现问题并保持代理对齐,你可以避免以后代价高昂的重写或失败。正如一位 AI 工程师所说,使用这些实践可以感觉像拥有"一支实习生军队"为你工作,但你必须很好地管理他们。一个持续维护的良好规范是你的管理工具。
避免常见陷阱
在结束之前,值得指出可能破坏即使是善意的规范驱动工作流程的反模式。GitHub 对 2,500+ 代理文件的研究揭示了一个鲜明的分歧:"大多数代理文件失败是因为它们太模糊。" 以下是要避免的错误:
模糊的提示: "给我构建一些很酷的东西"或"让它工作得更好"没有给代理任何锚定点。正如 Baptiste Studer 所说:"模糊的提示意味着错误的结果。" 对输入、输出和约束要具体。"你是一个有用的编码助手"不起作用。"你是一个为 React 组件编写测试的测试工程师,遵循这些示例,永远不要修改源代码"起作用。
没有总结的过长上下文: 将 50 页文档倾倒到提示中并希望模型弄清楚它很少起作用。使用分层摘要(如原则 3 中讨论的)或 RAG 仅显示相关内容。上下文长度不能替代上下文质量。
跳过人工审查: Willison 有一个个人规则:"我不会提交我无法向别人解释的代码。" 仅仅因为代理产生的东西通过了测试并不意味着它是正确的、安全的或可维护的。始终审查关键代码路径。"纸牌屋"隐喻适用:AI 生成的代码可能看起来很坚固,但在你没有测试的边缘情况下会崩溃。
将氛围编码与生产工程混为一谈: 使用 AI 进行快速原型设计("氛围编码")非常适合探索和一次性项目。但是在没有严格的规范、测试和审查的情况下将该代码发布到生产环境是自找麻烦。我区分"氛围编码"和"AI 辅助工程"——后者需要本指南描述的纪律。知道你处于哪种模式。
忽略"致命三要素": Willison 警告 AI 代理危险的三个属性:速度(它们工作得比你审查的速度快)、非确定性(相同的输入,不同的输出)和成本(鼓励在验证上偷工减料)。你的规范和审查流程必须考虑所有三个。不要让速度超过你验证的能力。
遗漏六个核心领域: 如果你的规范没有涵盖命令、测试、项目结构、代码风格、git 工作流程和边界,你可能遗漏了代理需要的东西。在交给代理之前,使用第 2 节中的六个领域检查清单作为健全性检查。
结论
为 AI 编码代理编写有效的规范需要将扎实的软件工程原则与适应 LLM 怪癖相结合。从目的的清晰性开始,让 AI 帮助扩展计划。像严肃的设计文档一样构建规范——涵盖六个核心领域并将其集成到你的工具链中,使其成为可执行的工件,而不仅仅是散文。通过一次给代理一个难题来保持代理的焦点紧密(并考虑聪明的策略,如摘要目录、子代理或并行编排来处理大型规范)。通过包含三层边界(始终/先询问/永不)、自检和一致性测试来预测陷阱——本质上,教 AI 如何不失败。并将整个过程视为迭代:使用测试和反馈持续完善规范和代码。
遵循这些指南,你的 AI 代理将远不太可能在大型上下文下"崩溃"或偏离到无意义的地方。
祝规范编写愉快!
本文使用 Gemini 格式化,图像使用 Nano Banana Pro 生成
我很高兴地分享我已经与 O'Reilly 发布了一本新的 AI 辅助工程书籍。如果感兴趣,书籍网站上有许多免费提示。
