欢迎参加本课程,该课程由我们与 JetBrains 合作开发。基于规范的驱动开发(Spec-Driven Development)目前是使用代理编码助手构建严肃应用程序的最佳工作流。给您的代码代理一个 Markdown 文件或一段长提示,详细说明要构建的内容,它将实现该规范。与其手动编写代码,不如专注于写下代理尚不具备的上下文信息。我很高兴本课程的讲师是 Paul Everett,他是 JetBrains 的开发倡导者。
谢谢 Andrew。等等,我不知道你戴眼镜了。“你说得对,我其实并不需要这副眼镜。”“好吧,我就这么想。总之,基于规范的驱动开发主要有三个好处,你会立刻开始看到这些优势。”第一,你可以通过对规范的小改动来控制大规模的代码更改。像“使用 SQLite 搭配 Prisma”这样的一句话可能会影响数百行代码,将其改为 MongoDB 也会产生同样的下游放大效应。这使得编写规范非常高效,远比写代码效率高得多。
第二,规范有助于消除会话之间的上下文衰减,保留不可协商的核心内容。由于代理是无状态的,因此在启动时为其加载最高质量的上下文至关重要。最后,规范提高了意图保真度。你定义问题、成功标准、约束等,而代理可以在此基础上展开以创建更完整的计划。我通常编写规范的一种方式是与 Cloud Code、Gemini 或 GitHub Copilot 等代理进行对话,利用我对不同权衡的知识来做出关键的架构选择。
然后让代理将关键决策总结在一个 Markdown 文件中。编写规范需要思考,这是一项艰苦的工作。你必须决定要构建什么产品、功能是什么以及技术架构如何。如果没有规范,你将会把这些重要决策交给编码代理的随机性来决定。如果你只是想快速行动并碰运气,这也许还可以接受,但这肯定会导致代码的可维护性降低,有时甚至会产生非常奇怪的产品。
例如,我曾见过一个团队在开发复杂的软件产品时没有明确的规范,这导致了诸多下游麻烦。不同的开发者指挥着不同的编码代理快速但相互矛盾地构建产品,从而引发混乱。基于规范的驱动开发涉及在项目层面制定宪法以定义不可变的标准,然后通过功能开发循环进行迭代。这些循环将每个功能隔离在独立的分支上,包含计划、实施和验证步骤,并在不同功能之间留下干净的起点,从而减少麻烦和上下文切换。
这种工作流既支持从零开始的新项目(Greenfield),也支持现有代码库的项目(Brownfield)。在新项目中,你从头开始开发。你会在与代理的对话中制定宪法。在现有代码库项目中,你将基于现有的代码库生成项目宪法。在这两种情况下,你随后都将通过这些功能开发循环进行迭代,以小步骤管理版本控制。在本课程中,你还将看到如何编写自己的代理技能来自动化基于规范的驱动工作流。
你说得对,如果你只需一个简短的提示就能完成所需的工作,那当然很好。我绝对支持在有效时使用“懒惰提示”(Lazy Prompting)。但我认识的那些优秀开发者几乎总是为任何具有相当复杂性的项目编写详细的规范,因为他们拥有独特的上下文以及对构建什么或如何构建的观点,这优于让缺失这些上下文的代理随机选择。
如果你的编码代理将花费 20 或 30 分钟去编写代码,这可能相当于传统开发者数小时的工作量,那么坐下来花三四分钟写出非常清晰的指令通常会更好。许多人也为本课程做出了贡献,包括来自 JetBrains 的 Constantine Chiker 和 Zena Smeova,以及来自 DeepLearning.AI 的 Isabel Zaro。让我们进入下一个视频,开始编写一些规范吧!
当你听到“编码”时,可能会想到“氛围编程”(Vibe Coding)。让我们比较一下两者,看看基于规范的驱动开发如何通过回归工程化来带来更好的结果。氛围编程能快速产生结果。你写一个描述你想要的提示,比如“给我创建一个按钮”,然后听天由命。接着你看结果:“这是一个大按钮。有点接近,但在一些重要方面偏离了。”于是你指出代理的错误,它再试一次,如此反复直到你满意为止。
结果就是你会与代理进行漫长的对话,而这段历史甚至不会被保存下来。这种方法对于创建一个按钮来说还可以接受,但它无法扩展到大型持续项目中。虽然高级提示很快,但它们会导致代码变得一次性使用并积累越来越多的技术债务。我们需要工程化:一份维护良好的规范,它创建一个永久的技术产物。基于规范的驱动开发是对不受监督的 AI 生成混乱的专业回应。
这是一个范式转变,其中解释“做什么”和“为什么做”的规范与实现“怎么做”的代码解耦。有了规范,我们就在人类之间以及人类与代理之间建立了一种契约。作为人类,你的主要任务现在转变为:学习如何将你的意图转化为清晰的规范。基于规范的驱动开发结合代理编码助手主要有三大优势。
第一,你能够通过改变少量的规范来控制大规模的代码更改。规范中概述应用外观和感觉的几句话可能会转化为数百行的 CSS 代码。这种基于规范的驱动方法减少了与这些超快速编码代理协作所需的认知负荷。第二,规范消除了导致多轮代理会话偏离轨道的上下文衰减问题。
随着你与编码代理一起工作,其上下文窗口会填满,往往导致代理在努力应对已满的工作记忆时出现更多错误。规范跨会话甚至跨代理持久存在,将代理锚定在代码库中工作并实现功能所需的核心上下文中。第三,规范提高了意图保真度,意味着代理更有可能生成符合你目标代码。
这是因为在代理开始生成代码之前,规范迫使你定义问题、成功标准、约束、用户流程等。规范是氛围编程(产生一些杂乱代码)与工程化一个可行的软件产品之间的关键区别。无论你是从零开始启动一个新项目,还是希望将这种规范驱动的方法实施到一个已经运行多年的项目中,规范都有助于解决漂移和生产率问题。
作为比较,请想象一下……
编译器将人类可读的源代码转换为机器代码。STD 指导代理并将提示词转化为从规范到源代码的过程。更棒的是,这些规范使用人类语言编写,使得利益相关者能够轻松理解。最近,基于规范的驱动开发(Spec-Driven Development)作为一种解决生产力担忧的方案而兴起。多个 STD 项目、围绕规范编写构建的工具,以及关于捕捉意图的会议演讲,都是更广泛推动的一部分,旨在将从软件开发生命周期中汲取的工程经验教训应用到代理式编码中。
基于规范的驱动开发是与代码代理一起使用的,而非简单的聊天机器人。聊天机器人可以谈论代码,但它无法访问你项目的代码,也无法使用你安装的工具。它只是对你的提示词做出响应。代理则不同。它们接收你的提示,制定计划,并在过程中利用推理引导自己达成结果。重要的是,代理可以访问你的代码库和你的开发工具。在 STD 工作流中,我们将这些代理视为能力极强的结对程序员。它们提供技术知识和速度,而你作为高级架构师则提供蓝图。
在课程推进过程中请记住:代理是肌肉,而规范是大脑。通过练习,你确保生成的软件不仅功能完备,而且与你的长期目标保持一致。基于规范的驱动开发在项目初期就告诉代理如何构建你想要的东西,然后在每个功能模块中逐步完善。借助 STD,我们帮助代理获得最高质量的情境信息:首先是关于项目的决策细节,其次是每个功能的具体细节。这份规范非常详细。
STD 的一项关键技能是掌握合适的详略程度。如果你将代理视为能力极强的结对程序员,你往往能把握正确的细节层级:提供大量关于目标、使命、目标受众和约束的情境信息,而减少那些代理可以自行解决的底层决策细节。那么,这个 STD 工作流看起来是什么样的呢?首先,我们制定宪法(Constitution)。使命是什么?技术栈和路线图如何规划?
“宪法”只是形式化这些项目级细节的一种方式。许多开发者为此使用顶层的 agents.md 文件,但项目宪法与代理无关且结构更清晰。宪法记录了人类与代理之间关于关键决策的共识,也记录了人类彼此之间的共识。“使命”解释了项目的愿景、受众和范围等“为什么”。提前定义这些参数在软件项目中非常常见,有助于指导持续的决策。
技术栈面向工程团队,确立对开发和部署技术及约束的共同理解。路线图是一份活文档,包含一系列阶段,每个阶段都通过其自身的功能规范流程来实现。一旦宪法起草完毕,我们就以可重复的流程处理每个功能:首先规划功能,然后实施它,最后验证结果。在功能之间是重新规划阶段:修订宪法、更新路线图,甚至改进流程本身。
正如刚才听到的那样,STD 的关键技能之一是提供合适详略程度的信息以创建最高质量的情境。在功能阶段和重新规划阶段,由你来引导代理。可以这样想:想象你是一位建筑师,你将详细的建筑图纸交给 builders(建造者)。接下来就看他们的了。你的角色是设计、监督施工,然后审查并接受结果或要求更改。
你希望避免告诉建造者如何完成他们的工作,而是专注于提供他们所不知道的情境信息。基于规范的驱动开发让你从最初的构思走向最终的交付。最重要的是,它使你在之后持续改进。这是现代开发者开始使用的一种 STD 工作流。很快我们将查看起点,即项目宪法。但首先,让我们做一些设置准备。
要使用项目仓库进行设置,请遵循下一个阅读项中的说明。以下视频的设置是可选的。如果你已经熟悉在 WebStorm 等 IDE 中设置像 Claude Code(注:原文此处误写为 Claw Code,后文更正)这样的代码代理,请随意跳过这个可选视频。我们在下一个视频中见。
在发送第一个提示词之前,让我们谈谈设置工作区的一些事情。如果你已经熟悉在 WebStorm 等 IDE 中设置像 Claude Code 这样的代码代理,请随意跳过这个可选视频。基于规范的驱动开发是一种最佳实践,不绑定于任何特定的 IDE 或代码代理。因此,你可以选择你已经在使用的设置,或者本课程中看到的相同设置。
VS Code 配合 CLI、Zed 编辑器配合本地模型,都非常适合基于规范的驱动开发。由于我们计划开发一个 Web 应用程序,本课程将使用 WebStorm IDE 和 Claude Code(注:原文误写为 Cloud Code)作为代码代理。下载和安装两者的说明已包含在前一个阅读项中。让我们打开 WebStorm 并启动一个新项目,命名为 Agent Clinic。
这将是 TypeScript 项目,带有 Git 仓库以密切跟踪代码和规范的版本控制。虽然许多 IDE(包括 WebStorm)都提供聊天面板,但我们知道你与代码代理交互的方式多种多样。在基于规范的驱动开发中,密切跟踪代码版本控制非常重要。假设我们要使用代理创建初始提交。每次它需要执行命令时,除非以不安全模式启动 Claude Code(注:原文误写为 clawed code),否则都会请求你确认。
请密切关注 Claude Code 要求你做的事情。代码的最终责任在于你。在接下来的课程中,你将看到几个关于使用 Git 进行基于规范的驱动开发的技巧和最佳实践。太好了,我们的设置准备好了,你也准备好了吗?让我们开始吧。你需要告诉代理关于你的项目、使命、受众和其他决策的信息。
在本课中,我们将与代理合作编写宪法(Constitution)。你的项目到底是什么?假设你正在为公司开发一个新的 Web 应用。其开发背后的核心理念是什么?它如何适应贵公司首选的技术栈?计划了哪些功能?这三个基本原则构成了宪法,这是一套指导未来功能开发并向利益相关者解释项目形态的全局高层需求。
例如,对于技术栈你有许多选择。你希望根据适当的权衡和你使用的工具来缩小选项范围。
公司。我们需要把这些内容写下来,供智能体、你的队友以及未来的人参考。但我们不是独自书写,而是在与智能体的对话中完成撰写。你会惊讶于我们会提出多么精彩的问题、未曾考虑过的架构模式、已经能胜任工作的外部包,以及诸如速度与数据保真度之间的权衡取舍。愿景、技术栈和路线图不仅仅适用于从零开始的全新项目,现有的代码库也依赖这三大支柱。我们将在稍后的视频中讨论如何将规范驱动开发的工作流程引入现有项目。以下是本课程中使用的示例项目:我们正在编写“智能体诊所”,这是一个让 AI 智能体能从人类工作中获得喘息之地的地方。“智能体诊所”是对流行学习项目“宠物诊所”的有趣戏仿。
编码智能体正在做大量工作,这很有压力。幻觉、上下文腐烂、记忆问题以及同事子智能体的协调都会损害智能体健康。让我们建立一个诊所,让它们能在这里解决这些问题。这是一个全栈 Web 应用,后端使用 Next.js,前端使用 React。该应用允许你管理预约、治疗诸如幻觉之类的病症,以及提供如上下文注入之类的治疗方案。让我们看看如何为这样一个项目编写详细的规范。让我们与智能体聊天吧。首先,我们将项目描述提供给智能体,并告知它我们的利益相关者已在 readme.md 中提供了输入,该文件已添加到仓库中。
在重要提示中,我们直接提到了 Claude Code 的“询问用户问题”工具。该工具完全可选,但我们只是喜欢它在界面中的呈现方式。此外,对于项目宪法,告诉智能体与你一起制定使命、技术栈和路线图。规范驱动开发在“人在回路”的方法中效果最佳,即你审查微小的更改。因此,告诉智能体将路线图组织成小步骤。随着我们共同工作,你会看到智能体提出一些非常好的问题。你可能会看到不同的问题。第一个问题是:“使命文档应采用什么语气?”我选择,你猜对了,“有趣”。这涵盖了使命部分。
接下来是关于技术栈的问题。我们的工程师习惯于在后端使用 TypeScript,所以让我们将其添加到需求中。接下来是关于路线图,它询问粒度应有多细。我选择第一个选项。我们完成了初步访谈。让我们提交答案。智能体会要求你提供写入权限,这使更改处于你的控制之下。如果你愿意接受安全方面的权衡取舍,可以选择批准本次会话中特定命令的所有实例。你将在本课程的其他部分看到这一点。
现在,我们完成了工作,在 specs 目录中有三个文件:Mission.md、TechStack.md(原文误拼为text,根据语境修正理解)、Roadmap.md。现在是“人在回路”的时间了。让我们进行审查。例如,使命部分遗漏了目标受众。这是合理的,智能体怎么可能知道你的业务呢?与其直接编辑,不如继续对话。为了保持所有工件的一致性,更好的做法是让智能体手动更改它们,否则你可能会忘记更新相关文档。我们希望在这个项目中使用 SQLite。由于这是一个快速原型,我们并未提及这一点,但智能体在建议中推断出来了。它现在成为了我们的技术栈的一部分。
进行最终审查至关重要,务必在前期将所有内容弄对。让我们提交宪法,使其成为项目的活文档。“智能体诊所”现在拥有了指导我们项目的宪法、使命、路线图和技术栈。我们要准备好攻克第一个功能了。我们现在有了包含功能的路线图,但如何构建它们呢?当然要用规范,从第一个路线图功能开始。让我们看看“智能体诊所”的路线图。这是我们的第一阶段功能:“你好,HANA”。但现在开始编码还为时过早。我们需要讨论规范并澄清所有细节。一个好的计划概述了方法、工作顺序以及如何验证成功。
让我们从全新的智能体上下文开始。智能体可以从官方来源——宪法中获取所需信息。我们将在一个单独的分支上处理此功能,并将这一情况告知智能体。我们的提示将帮助启动与关于该功能规范、任务计划、收集需求以及验证记分卡的对话。智能体会要求你做出关键决策。注意潜在的冲突或问题。你不一定要同意智能体提出的解决方案,务必澄清任何让你感到不安的地方。首先,关于第一阶段范围,我们将保持原样不变。对于需求,让我们固定 HANA 版本并强制执行严格 TypeScript。
关于确认方式,手动 curl 看起来不错。然后提交。这很快,一定是因为使用了 Nano(指智能体)。工作已完成,球回到了我们这边进行审查由智能体创建的功能规范。让我们先审查功能计划。在开始时将这些文档弄对至关重要,以保持智能体走在正确的轨道上。如果发现错误,请让智能体修复它,以确保需求和验证保持同步。例如,我们希望在这个第一个功能规范中有一个美观的占位符主页。我们通过智能体进行更改。
接下来是需求部分,也已更新以反映主页的变更。这是指出任何重要技术需求或约束的正确位置。不要在这里匆忙行事,但也不要陈述诸如变量名之类的次要技术细节。我们要控制流程,但不要过度指导智能体。最后是验证部分,确保智能体能检查它是否做对了。同样,这些内容也已为主页进行了更新。功能规范已完成。让我们在 IDE 中创建一个提交。很好,我们制定了一种功能规范策略:创建了功能分支、与智能体访谈了该功能应做什么的内容、将结果放入 Markdown 文档中、审查了这些规范文件并提交。
你在规范中所做的更改将在下游扩展成数百行代码,因此在此花费的时间是值得的。现在是实施的时候了。我们正在为项目路线图中的第一个功能制定计划。我们完成了功能规范,现在让我们完整实现此功能。为了回顾一下,我们先快速审查这个功能规范的计划:这是第一个功能“你好 HANA”。规范文档包含了我们所需的信息。开始实施时,你需要通过 /clear 命令清除上下文。让我们回到智能体并输入提示以执行所有任务组。有时你可能会选择分批进行,
一次处理一个任务组,以实现更小的步骤和提交。这项技术在那些小错误可能会累积放大的领域特别有用,例如在安全或数据库管理方面。当 Claw 运行时,你可以观察它在控制台中显示的更改以实时查看其进度。之后,我们可以在提交窗口中关注最终更改并浏览这些变更。
这让我们能够尽早开始审查工作。在这种范式下,开发者的关键角色是充当架构师或主管,确保向智能体提供清晰的契约。我们还可以看到已完成工作的摘要。正如你所见,智能体会为每个任务组的工作提供额外的详细信息。现在,让我们进入 package.json 文件并在那里运行应用程序。服务器在控制台中启动,浏览器显示了该功能规范的成果。虽然看起来没什么特别的,但看到屏幕上有像素呈现的感觉很好。我们刚刚实现了一个功能,智能体完成了它的验证工作。在下一课中,我们将进行我们的验证。拥有一个就绪的功能固然好,但先不要合并。
在这个最后的特性步骤中,我们与智能体协作审查工作。幸运的是,程序员拥有用于此验证任务的良好工具。毕竟,程序员长期以来每周都要花费数小时进行代码审查。从提交视图开始,让我们逐一查看更改。将你的审查重点放在高级关注点上,例如功能是否按规范工作,而不是诸如实现了哪些 CSS 类等细节。例如,home.tsx 文件非常精简。“Nano”确实意味着极简主义。我们想要一个具有清晰地标(header、main 和 footer)的布局组件,但希望将这些作为子组件实现并创建一个 CSS 文件。
事实证明,代码中的这个错误源于计划中的失误。我们并没有要求这样做。让我们让智能体进行修复,从而同时纠正规范和实现。这种由智能体生成内容、我们负责验证的过程被称为“人在回路”(human in the loop)。由于智能体编写代码的速度非常快,软件开发者最近一直在讨论“认知债务”,即跟踪代码在做什么以及它是如何演变的心理负担。因此,为了使这个过程快速、易于控制并减少认知债务,更改应该是可管理的。智能体正在使我们的变更生效,同时也验证这些变更没有破坏任何内容。
好消息是,智能体已完成工作并给了我们一个快速摘要。你也可以在编辑器中看到这一点。功能计划已更改,添加了一个包含这些新步骤的第五组代码。现在代码中有了布局组件,并且添加了 CSS 文件。看起来这三个子组件只是被放在了同一个文件中,但这不符合惯例。让我们使用 IDE 的移动工具将这些文件分开存放。这类更改在编辑器中很容易处理,而且我们一直都很擅长于此。不需要智能体介入,对吧?让我们直接动手做吧。
别急。这可能导致漂移(drift),使得其他工件如规范、自述文件等不同步。让我们要求智能体修复任何提及之处,并确保这不会在将来浪费一些时间。所有更改都已完成。我们是否破坏了什么?测试会有所帮助,但智能体没有安装我们的测试包。由于这对所有功能都是必需的,我们将在下一课中介绍它。现在,我们准备标记这项工作为完成并合并我们的结果。请注意,在此分支中,宪法的部分内容与功能一起更新了。如何处理规范的版本控制以及如何关联哪些规范创建了哪些代码更改,是社区中一个正在发展的话题。对路线图的变化很小,只是在路线图中勾选了一个步骤。因此,将这些更新保留在同一分支上是可以的。
如果整体宪法的更改更复杂,最好在一个单独的分支中进行此操作。现在,我们准备标记这项工作为完成并合并我们的结果。我们刚刚使用基于规范的驱动开发来开发和验证了第一个功能。但是等等,难道我们不应该再看看项目的更广泛范围吗?我们成功实现了第一个功能。迫不及待想再次重复这一过程。但不要急于求成,退一步进行反思和重新规划。“慢即是快”。我们有一个名为“验证”的工作流步骤。测试对于验证很有用,但我们没有给智能体所有的测试偏好设置。让我们创建一个重新规划分支来更新我们宪法中的技术栈。正如你在前一个视频中看到的那样,规范版本控制是一个正在发展的话题。宪法是一份活文档。最好在其自己的单独分支中进行更新,以便你可以跟踪哪些版本的宪法制生了哪些代码。我们将使用提示来陈述我们的策略。
看起来智能体更新了 package.json 只是为了有一个脚本,而没有依赖项。这一点值得注意,稍后当我们运行测试时会用到。添加测试框架的更改适用于未来的代码。但让我们告诉智能体根据这次宪法更新来修改现有的功能规范和实现。经过这两次提示后,我们得到了一些很好的更改。智能体设置了此测试变更,但没有自己编写测试。让我们告诉智能体编写一些新测试。
有了这个设置,我们可以在编辑器中方便地运行测试。让我们在调试器下运行,以便作为“人在回路”的一部分有机会逐步执行代码。看起来不错。现在我们将测试纳入验证环节了。让我们提交更改。
有时我们会意识到在产品计划中想要以不同的方式做事。例如,在实现第一个功能后,我们收到了产品经理的更新通知。因为 40% 的用户使用移动设备,我们希望强调响应式设计。让我们告诉智能体我们想要响应式设计,并纠正产品规范和功能规范以及任何相关代码。由于我们处于开发的早期阶段,这次更新是一个小更改。因此,在重新规划期间直接实施它是合理的。但如果新工作量大,最好将其作为独立的功能阶段安排在路线图上,而不是仅在重新规划中执行。请运用你的判断力。记住,我们希望规范捕捉决策,而不仅仅是代码。我们试图保持两者同步以帮助团队沟通。智能体已经实施了我们的响应式修复,不仅更新了代码,还更新了产品和功能规范。现在轮到我们履行自己的职责并审查更改了。让我们查看差异(diffs)。看起来不错,让我们提交一下。请记住,以小步骤工作并频繁提交可以防止审查过载你的大脑。在重新规划的第一部分工作时……
让我们退一步,进行一些项目整理工作。例如,重新审视项目路线图并查看下一个任务是否仍然合理?路线图中显示的是下一节课要涵盖的下一个功能,它是否正确吗?浏览路线图时,看起来第二、三、四和五个功能有些关联。让我们更新路线图,以便一次性处理这些内容。我们将提交更改并很快开始这个新功能。
重新规划步骤可以针对某个功能或整个项目,也可以涉及改进跨项目及组织的规范驱动开发工作流。例如,也许你有一些非技术利益相关者希望监控项目进度,并希望每次合并时更新变更日志。大多数 AI 编码代理都支持“技能”,这是一组指令和资源的包,为代理提供新的能力和专业知识。
技能非常适合定义明确、可重复的工作流,这些工作流需要特定于项目或组织的上下文。实现变更日志更新就是一个非常适合使用技能的地方。你可以手动编写这个技能,但许多代理实际上拥有帮助你编写技能的技能。让我们使用代理来帮助我们编写和维护变更日志技能。
代理开始工作。我们需要考虑的一点是,这个技能是否仅针对此项目独特存在,还是应该成为所有项目的标准部分。这是一种风格选择,随着你的使用你会获得更好的理解。你将学会用技能自动化规范驱动开发工作流。例如,验证步骤可能包括更新自述文件、代码检查、格式化、运行测试以及其他质量检查。
你可以与代理合作将这些内容打包为一个验证技能。可重复的过程,更少的手工工作。代理完成了任务。我们可以滚动窗口查看它创建了什么以及如何使用它。注意,它选择在全局技能区域中创建此内容。现在该技能将在所有项目中可用。
此外,Cloud Code 使用新技能在此项目中生成了一个变更日志。变更日志是你与利益相关者(包括代理)沟通的方式。因此,让我们打开它并手动审查一下。看起来不错。我们完成了这次重新规划工作。让我们提交更改,然后合并分支。
现在作为开发人员的大部分工作在规划和验证而非实现上,因此在功能之间留出时间进行重新规划。在下一个视频中,我们将处理另一个路线图上的功能。我们拥有改进后的章程和改进的工作流,我们正在变得更好。但在继续下一个路线图功能之前,让我们解决应对常见痛点——AI 疲劳的策略。
代理可以生成大量代码和许多更改。这种海量的代码使得人工循环验证变得令人疲惫。需要审查的内容太多了。为了对抗这种混乱,确保每个功能阶段之间有清晰的划分。我们应该以正确的思维状态开始每个功能。
是否有未完成的工作?上次合并的功能分支是否已合入主分支?下一个路线图项目是否是正确的事情要做?我是否清除了 AI 的上下文,以确保规范捕捉的是意图而非记忆快照,并让它将有限的上下文预算专注于下一项工作?花点时间做好开始有助于你完成。
我们已经完成了所有这些操作。让我们清除上下文并开始下一个功能,代理和 AI 疲劳。注意一下,我们一直在输入相同的内容。我们将在未来的课程中讨论如何将这种重复的提示简化为自定义工作流。
与往常一样,代理提出了很好的问题。第一个问题是关于是否将所有这些功能保留在一个阶段中。我们在上一节课已经决定将它们放在一起,所以我们会说是的。对于迁移部分,我们将选择纯 SQL。对于验证步骤,让我们选择一、二和三。很好。现在提交吧。
当代理起草规范时,我们可以看到它的一些选择。观察代理的推理过程很有用。如果你使用的是具有详细模式的代理,这可能会让你更深入地了解其中间想法。看起来不错。但我们想做一个小改动以捕捉我们的意图,即使用 Pico CSS 作为我们的 CSS 框架。
接下来我们审查功能规范中的三个文件,从需求开始。让我们要求代理更改需求以确保其他任何文件都反映出这一变化。当工作完成后,提交功能规范。这次我们让代理来生成提交信息。
有了第二个功能的规范准备就绪,让我们进入实现阶段。规划阶段和功能阶段之间的划分有助于我们避免上下文溢出——无论是我们的还是代理的。如果功能看起来太大而无法一次性实现,请让代理先实施部分功能计划。这将使更改的大小保持在可控范围内。
我们的代理已经实现了第二阶段的功能。我们观看了代理的进展,所以对做了什么有一个大致的了解。但这还不够。慢下来,思考一下。让我们深入审查这些更改。每个人对审查代理结果的程度都有自己的风格。
为了发挥代理的优势并减少 AI 疲劳,请坚持高层级的需求。避免纠结于变量名之类的细枝末节。只需确保它创建出你可以署名提交的代码即可。例如,它在 props 中使用了内联类型信息。我们希望将 prop 定义放在独立的 TypeScript 类型中。
让我们告诉代理在代码中的任何地方修复这个问题。你可能没有在你的规范中包含这个决定。请记住,像提取 prop 类型这样的演变并不是失败。随着你发现新细节而演进规范并捕捉这些内容,会带来更好的未来结果。
我们完成了审查。这是进行另一次小步提交的绝佳时刻。最后一步,验证。让我们回顾一下代理计划在此功能规范中为验证步骤做什么。看起来不错。让我们来执行验证。
请记住,我们要通过运行应用程序来确保更改是好的。但我们还要防止认知债务,方法是验证我们是否理解这些更改。测试是通过流程进行工作的绝佳场所。让我们阅读一些测试,并在调试器下运行它们以进行深入探索。
有时你需要验证你是否没有被欺骗。告诉代理生成几个子代理,以此功能更改对整个项目进行深度审查。这种深度审查给代理更多空间来思考这些更改,而使用子代理则保留了主代理的上下文窗口,而不是使其受到污染。
这些子代理将返回许多问题。
这些建议看起来都不错,所以我们继续推进。代理去执行了一系列修复、运行测试,并将项目调整到了良好的状态。请把这个技巧记在你的工具箱里:代理通常在二次审查时能发现重要问题。一旦我们完成了验证,功能开发就算结束了。现在是提交代码的时候了。作为本功能的最后一步,让我们使用上一课中创建的“变更日志”技能。现在我们已经记录了该功能分支上的所有更改,再提交一次,然后合并分支。
在之前的课程中,我们看到了功能之间的“重新规划”步骤。让我们通过查看路线图来快速执行这一操作:下一个功能看起来依然合适吗?看起来很完美,项目状态良好,已准备好迎接新功能。这种清晰的功能间隔有助于管理“AI疲劳”。现在你可以去喝杯咖啡休息一下了。我们开始看到一个可重复的标准驱动开发(STD)功能开发生命周期,它记录了我们的决策。
在下一步中,让我们测试这个假设:我们是否有足够的资源来构建最小可行产品(MVP)?我们已经取得了很大进展,通过规范工作流实现了两个功能,但管理层当然要求提供一个 MVP。我们是否取得了足够的进展来进行实验?让我们对标准的规范提示进行变体处理:这次,我们要告诉代理实现路线图上的剩余部分,并就现有功能规范提供一些指导。
一般来说,只有当你确信“宪法”和规范的质量时,才应实施如此大的代码块。你提供给代理的上下文越好,你就越有信心获得符合你意图的结果。同时,你必须确保自己能够处理审查和验证工作。但既然我们承担了这一风险,现在让我们将 MVP 视为对我们“宪法”和已完成功能规范的极端测试。
如果我们得到的结果与预期不同,这意味着我们需要负责任地执行另一个重新规划阶段,以消除导致代理偏离正轨的因素。代理向我提出了一些问题,这些问题和建议都很好。很多规范文件最初都是通过与代理的来回对话形成的。完成访谈并选择“提交答案”后,让我们将 MVP 规范写入磁盘。
审查规范总是好的做法:你经常会注意到代理为了填补空白而做出的错误假设。让我们快速查看一下计划、需求和验证内容。一如既往,我们喜欢以小步骤工作并频繁提交代码。让我们保存规划阶段的规范。规划阶段已完成,现在是让代理进行大规模实施的时候了。
代理现在做了大量工作。完成后就是展示成果的时刻了:让我们看看 MVP 的效果。我们将运行脚本来启动应用程序。正如你所见,每个部分现在都更多地由从数据库查询的示例数据驱动。通常情况下,我们会在此时验证代码结果,但这是一个 MVP,所以让我们要求代理来验证规范。
事实证明这很有用:代理展示了 MVP 在规划中发现的漏洞。我们可以将这些评估结果分享给利益相关者进行 MVP 审查,然后合并或归档该分支。我们的规范驱动工作流成功了:在制定宪法和实现两个功能后,MVP 在我们的指导下产出了一个有用的演示。
当然,并非所有软件项目都涉及构建 MVP。许多项目属于所谓的“遗留系统”(Brownfield),它们始于现有的代码库。接下来,让我们看看如何向遗留项目引入这种工作流。人们常说规范驱动开发甚至 AI 仅适用于“绿地”(Greenfield,即从零开始)项目,但 STD 也适用于现有的遗留项目。
在本课中,我们将向现有项目引入 STD。为了简化操作,我们将从一个你已经熟悉的项目开始——即代理诊所 MVP。我们将在一个新的云代码会话中,在不同的项目目录下启动 main 分支(不包含规范文件夹),从而将其变为遗留项目。我们在 readme.md 文件中有一些项目背景信息,to-do.md 中列出了一些待办工作。
你的遗留项目可能在问题跟踪器、电子表格或 Word 文档中有完整的产品计划。还记得我们的工作流吗?我们从“宪法”步骤开始。我们将使用与第 4 课几乎相同的提示,但这次我们要告诉它在现有工件中查找路线图项目。在这种情况下是一个待办文件。
请记住,代理将从现有的代码库中发现并“逆向工程”出规范驱动(SD)的工件。宪法将有助于使代理未来进行的代码更改与过去开发人员已创建的内容保持一致。如果你有更多上下文,可以随时添加。例如,你可能被派入该项目是为了在实现高度请求的功能的同时提高其效率。
流程是相同的,但随着代理拥有更多的工件、代码、提交记录和文档等,对话可能会更加丰富。你会在这里看到大量的工具调用,因为代理正在探索代码库。让我们看看我们为遗留项目生成的宪法:在使命部分中,我们有目标受众、项目理念以及关于项目的额外信息。
文本栈显示 Claude 提取了项目文件结构、框架版本以及我们被要求澄清的内容。在路线图中,我们可以看到工作按阶段组织,与待办文件相匹配。让我们为生成的宪法文件创建一个提交,并附带提交信息。请记住,在 SDDD 中,规范是版本控制策略的一部分。
我们的遗留项目现在已建立在 SD 基础之上。从现在开始,工作流与我们之前讨论的完全相同:首先,我们获取路线图上的下一个功能并与代理进行规划对话。我们将执行第一阶段的功能反馈表单工作。
非常好,我们现在有了该功能的分支和规范。让我们审查功能规范、计划、需求和验证内容,然后提交功能规范。在与代理聊天进行任何修正后,我们进入实施阶段。一旦代理完成工作,我们就执行验证以确保代码良好且功能按预期运行。
我们的功能循环已完成:我们可以提交并合并分支到主域(domain)。现在是重新规划的时候了。请为此留出时间,因为你刚刚将 SDDD 引入项目,可能会发现许多需要调整的地方。我们现在有了一个基于规范驱动开发的遗留项目,无需大量手动工作即可实现。
这为我们提供了一个良好的流程:通过工程手段分步操作并保持控制力。规范现在是项目的记忆,请不要遗忘它。你现在已经掌握了 SD 工作流。想要更快、更轻量级的方案吗?在本课中,我们将自动化一些流程,但要以我们自己的方式通过自定义过程来实现。
之前我们展示了代理技能(Agent Skills),这是一种赋予代理新能力和专长的开放标准。例如,我们在启动功能时会重复使用相同的提示……
规范:做这个,做那个,写这三个文件。让我们用技能并利用代理的帮助来自动化这个过程并编写它。要求代理使用其技能创建器与我们讨论此事。需要注意的是,社区中有许多这类技能可供安装和使用。当代理运行时,它可能会提出一些后续问题,这些通常都很好。面试结束后,我们提交回复,代理继续执行任务。在代理处理技能时,请密切关注输出结果:它是否做出了你想要的成功选择?正如你所见,代理将技能写入了该目录。需要注意的是,技能可以是针对特定项目的,也可以是全局的。
技能可以通过多种方式调用。在提示词中,先提及该技能再说具体要做什么。此外,你还可以要求代理从另一个技能调用一个技能。根据技能的开放标准,代理使用“渐进式披露”过程来决定何时通过描述来调用技能。但它们的判断并不总是完美的,尤其是当上下文窗口变大时。使用与文件标记相同的启发式方法:如果你知道需要使用某个技能,就直接命名它。这可以节省一些思考令牌(token)。
代理内置了如“/cle”之类的斜杠命令。虽然最初很受欢迎,但许多代理正从自定义斜杠命令转向技能。有时你需要给代理更多资源,比如访问某些 API、私有知识库、数据库等。迄今为止,扩展代理的通用方式是 MCP(模型上下文协议)。例如,代理需要关于软件包的当前质量语境。最受欢迎的选择是 Context 7,这是一个 MCP,它将更新后的软件包文档带入代理的上下文中。现在你的代理可以保持与 React 9.2 及更高版本同步,而不是过时的 React 9.0。
MCP 服务器仍然很流行,但使用代码工具(如 CLI 命令行界面)的技能通常能更优雅地实现相同的目的。Context 7 现在建议将其作为一个技能,该技能调用 Context 7 的 CLI 工具。让我们为 Claude Code 安装 Context 7 包。在安装过程中,我们会立即看到一个选择:MCP 服务器或 CLI 加技能。我们将使用第二个选项。如果是第一次,你需要注册一个账户。我们已经这样做了并登录成功。完成后,我们可以回到 Claude Code 中,使用包含 Context 7 的示例提示词来投入使用。
当代理运行时,我们看到它检测到需要使用 Context 7。完成后,代理显示它现在知道如何查找有关我们技术栈的信息。从 MCP 服务器到技能加 CLI 的趋势正在加速。人们重新思考 MCP,因为 CLI 工具可以用更少的设置和更少的上下文使用来采取行动。随着你规模化工作流实施,如技能等,你将希望跨机器、与队友甚至外部世界共享它。
一些代理(如 Claude Code)拥有插件,这是一组可安装和更新的代理扩展集合。有一个不断增长的免费插件社区。去查看一下,看看是否有任何能提升你的 SD(规范驱动开发)生产力。请记住,插件尚未成为跨代理的标准。像应用或依赖项一样,插件可以执行代码,因此在安装和更新时请确保信任它们。
GitHub 的 Spec Kit 是尝试将规范驱动开发工作流与代理形式化的努力之一。为项目安装 Spec Kit 后,你可以在代理中访问斜杠命令,类似于本课程中使用的工作流:规范、宪法计划任务和实施。另一个流行的替代方案是 Vision AI 的 OpenSpec。OpenSpec 遵循类似的“提议、探索、应用、归档”工作流,其中提议和探索对应计划步骤;应用对实施;归档对重新规划。它还具有快速功能的规范模式。
这两个包都包含有用的功能,如分支管理、验证脚本和规范的文档格式。我鼓励你尝试这些开源工作流以帮助完善你自己的流程。有时在功能开发中途,你会产生一个想法。你想用代理研究它,但不想停止当前的分支工作。例如,数据库的选择,但你尚未对此想法做出承诺,所以不想将其列入路线图。对话产生了一些好主意和好问题。
我们接受了大多数建议,但对其中一个改变了想法。你不想丢失它,所以让我们通过告诉代理在已知位置编写报告来保留研究积压项。这个文件是你对话和结果的记录。稍后,你可以要求代理将此研究与路线图关联,并附上积压文件链接。随着积累增多,你可以编写一个技能来自动化你的研究过程。
规范驱动开发帮助代理以你的方式编写代码。你可以采用现有的 STD 框架或工具,然后使用技能对其进行定制,以你和团队的方式操作项目。规范驱动开发将工作重心从“怎么做”转移到“做什么”和“为什么做”。由于代理和模型进步迅速,你不希望你的工作流仅绑定于单一选择。在本课中,我们看到标准如何让我们在不改变工作流甚至工具的情况下切换代理。
这些代理标准为这一目标提供了帮助:MCP 用于外部工具,agents.md 用于规则,Agent Skills 用于捕获带有额外上下文的重复性工作流程,以及 ACP(代理客户端协议)用于连接代理和客户端。例如,Codeex 是 OpenAI 领先的 AI 代理之一。它在桌面应用、编辑器以及终端中运行。
让我们看看它的实际效果。这是我们在第 12 课中的功能规范技能,已复制到 Codeex 中(它们存储在不同的路径)。迁移后运行良好。这让你可以在同一项目中来回切换代理,同时保持你的 SD 工作流。我们还可以使用不同的编辑器配合不同的代理,利用 ACP(Agent Client Protocol)标准。ACP 使得连接代理和编辑器变得容易。如果你的代理和客户机支持 ACP,那就是完美匹配。
为了让这种即插即用更加容易,ACP 注册表自动化了在客户机内查找、安装和连接代理的过程。ACP 注册表覆盖整个生命周期,使得混合搭配变得更加容易。例如,在 JetBrains 中,AI 聊天窗口引导至从 ACP 注册表的安装。IDE 随后可以显示兼容代理的列表。Open Code 是一个流行的开源代理,ACP 注册表使其易于添加到我们的 IDE 中。
点击安装会自动完成 Open Code 本身的安装(如果需要)及其与 IDE 的集成,这很不错。完成后,你的 IDE 现在拥有了与新代理的原生集成。你可以在同一编辑器中与其他代理一起使用这个新代理,作为……
SDDD(规范驱动开发)。这些新的代理标准带来了新的可能性。但它们究竟是如何工作的呢?ACP 架构旨在简化代理与客户端的集成过程。事实上,该协议匹配的是 LSP(语言服务器协议)中使用的标准。ACP 比你想象的更强大,例如它涵盖了编辑器中的下一步编辑建议和计划模式。为了进一步利用 ACP 的优势,你可以编写自定义代理并安装在本地工具中。
应该选择哪个代理?行业变化迅速,基准测试网站如雨后春笋般涌现,提供不同评估的排行榜。当然,这些排行榜变化也很快。因此,务必保持最新信息,并根据对你而言重要的标准做出决定。我们的规范工作在更高层面,不与任何特定的代理或 IDE 绑定。在本课程中,我们证明了我们构建的工作流和工具是独立于代理的。随着更多标准的出现,这种灵活性将会增强。
完成本课程做得很好。你已经看到了如何从“氛围编码”(即希望代理能按你意愿行事)转变为规范驱动的开发,从而更接近你的实际需求。你已经撰写了宪法(行为准则),通过对话规划功能,作为人类在环验证结果,并利用技能和标准自动化了工作流。你今天编写的规范将成为你项目明天的记忆。保持它们的精准,不断改进你的流程。
请记住,最好的代码始于伟大的规范。你和许多我认识的工程师可能都目睹过因行动过快而带来的后果。让我们重拾一些工程学的严谨性,让你始终作为你软件的主导者。我真心关心在所有事物中寻找乐趣和意义,我很期待看到你如何利用这些知识去做一些很酷的事情。保持自信(Sleazy),去干一番精彩事业吧。