氛围工程实用指南
首先,你要写下你正在解决什么问题,用户是谁,以及你的目标是什么。它不需要很广泛,但应该给智能体你软件的业务背景,以便当它工作时,其推理将建立在该背景之上。对于 Puppypal,product.md## 推介Puppypal 是一个本地优先的移动伴侣应用,通过提供适合年龄的日常例程、基于里程碑的带有鼓励性游戏化的冒险,以及应用内训练指南,帮助幼犬主人培养一只自信、适应性强的狗。## 用户- 第一次

我曾让 LLM 在几分钟内为我编写整个功能,也曾让它们生成数千行无法使用的垃圾代码。区别通常不在于模型本身,而在于我是把它当作老虎机还是当作另一位工程师。
作为一点背景,几天前,我使用 OpenCode 为 Puppypal 添加了一个功能,这是我正在构建的一个幼犬训练应用,目的是更好地抚养我们的幼犬 Bubbles。我用几句话描述了我想要的内容,它在代码中做了大约十几次更改,并宣布任务已完成。
我高兴地开始测试它,点击了一会儿后,我意识到它不仅没有完成我所描述的内容,还因为对其他部分代码正在使用的数据结构进行了更改而破坏了一些其他功能。在努力弄清楚出了什么问题并试图修复后,我决定直接 git reset 并应用正确的工程方法。
这种体验相当令人沮丧,所以随着时间的推移,像许多其他人一样,我转向了一种更稳健的 LLM 使用系统。
我意识到,如果我把智能体当作协作者,给它一个系统、一个要遵循的程序以及它需要的所有必要信息,它确实能提供非常高质量的软件。
所以这篇文章是我从氛围编码转向氛围工程的方式——一种用于 AI 优先开发的简单流程以及使其能够实现的一系列技术。我希望读完这篇文章后,你会想尝试一下。
1、氛围工程
那么我们如何从氛围编码走向看起来像真正工程的东西?
当我在这里说"氛围编码"时,我指的是向你的智能体抛出松散、不够具体的请求,并希望它猜到你的意思。有时这行得通,但往往留给你的是脆弱的代码和未完成的功能。 通过"氛围工程",我指的是像与另一位工程师那样与你的智能体合作:就目标达成一致,共享上下文,写下计划,并在让它接触代码库之前建立保护措施。
大多数人都会同意,仅仅描述你想要的最终结果,而不考虑它将如何实现,或者它对代码质量、架构或可维护性有什么影响,是一个坏主意。
这就像直接跳入一个外国代码库,没有任何计划,说"没问题,我会随机应变"。没有 AI 时这种方法就会失败,有了 AI,它失败得更快、更严重。
为了抑制这种风险,你必须把你的 LLM 智能体当作一个非常擅长遵循指令的初级开发人员,但同时也拥有对你代码库的 root 访问权限。
你不会给初级开发人员一个模糊的单行工单,没有文档,没有测试,然后在他们交付脆弱的东西时表现得惊讶。你会给他们关于产品和架构的背景,你想要的更改的清晰描述,也许是一个你们共同同意的计划,并为他们绝对不应该能够做的事情建立保护措施,比如访问你的生产数据库。
这同样适用于智能体。如果你希望它们在你的代码库中处理非平凡的任务,你需要提高你与它们合作的标准。
2、AI 开发的级别
在深入流程之前,有助于设定一个基准:我们到底在谈论什么级别的 AI 辅助?
在过去几年里,我在所有这些级别都开发过,我几乎一直都在使用智能体(如 OpenCode 或 Claude Code)。对我来说,它们在自主权和控制权之间取得了很好的平衡,并解决了我的所有需求。
第 1 级:基础
这是传统的编码方式。你使用常规工具编写、调试和管理所有内容。我在这里把所有"非 LLM"和基本 AI 工作流程归为一类,包括制表符自动补全。
在这个级别,工具只查看立即上下文,比如当前行或函数,并建议你可能正要输入的内容。Tabnine、标准自动补全和智能重构功能等工具位于此处。
第 2 级:在聊天中复制粘贴

使用 ChatGPT 进行编码的屏幕截图 | Kamen Zhekov
这是我们第一次在聊天窗口中与 LLM 进行真正的"交互",我们第一次尝到了它们的能力。我记得第一次使用 ChatGPT 时起了鸡皮疙瘩,但这种兴奋很快消退。
你复制文件或代码片段并用自然语言寻求帮助,但模型无法访问你的系统,所以它只能告诉你该做什么(编辑这个函数,运行这个命令),并且只能读取你之前为它整理的任何内容。这对小问题有效,但一旦你的项目增长,这个循环就会变得乏味。
第 3 级:引导智能体

从 CLI 使用 Claude Code 作为智能体的屏幕截图 | Kamen Zhekov
现在事情变得有趣了。智能体要么集成到你的 IDE 中,要么是独立的,要么生活在你的终端中,但最重要的是,它们可以在它们运行的文件夹中读取任何想要的内容,并在整个代码库中进行更改。
如果你给智能体一个任务,它将读取并写下它的待办事项列表,尝试理解你的代码,实现新的业务逻辑,审查自己的代码,优化现有函数,并总结它所做的事情。美妙极了。
这是我大部分时间使用的级别。Claude Code、Codex CLI、OpenCode 等工具位于终端中,让你在仍然卸载繁重工作的同时保持控制。
第 4 级:脱手工程

codex 智能体在 GitHub 仓库中进行 PR 审查的屏幕截图
这里的想法是,你给智能体一个高层目标,它处理一切:分解计划、编写代码、测试、迭代和打开 PR。它还可以担任自主 PR 审查者的角色。也许有多个智能体为此目标工作,也许只有一个,但你不进行任何编排,只对高层决策进行最少的交互。这是 Devin 或 GitHub 自主智能体等工具所在的地方。我还没有在我大部分工作中采用这个级别,因为我在乎质量和可维护性的项目仍然需要我在循环中。
3、工程流程
核心而言,AI 优先开发是给智能体正确的信息和一系列指令以供执行。智能体遵循这些指令,根据需要使用工具,并在认为任务完成时返回响应。
理解这一点是正确使用智能体的第一步,但我们还必须考虑智能体需要什么样的信息才能工作。
这是系统概览

AI 优先工程流程图
在你的代码库中,你有 3 个关键文件,解释你的应用程序做什么以及为谁构建——你的产品,它在技术层面上如何做——你的架构,以及你的智能体如何在你的代码库中工作。
有了这些信息,你给智能体它分解为一系列任务的目标,然后智能体执行这些任务。当它完成一个任务或目标时,你要求它审查自己的工作,识别问题并纠正它们。
3.1 定义你的产品
首先,你要写下你正在解决什么问题,用户是谁,以及你的目标是什么。它不需要很广泛,但应该给智能体你软件的业务背景,以便当它工作时,其推理将建立在该背景之上。
对于 Puppypal,product.md 文档如下所示:
## 推介
Puppypal 是一个本地优先的移动伴侣应用,通过提供适合年龄的日常例程、基于里程碑的带有鼓励性游戏化的冒险,以及应用内训练指南,帮助幼犬主人培养一只自信、适应性强的狗。## 用户
- 第一次养幼犬的主人:想要清晰、建立信心的指导和一种简单的进度跟踪方式。
- 有新幼犬的有经验主人:想要结构、灵活性和比临时笔记更好的跟踪。
## 问题
幼犬主人往往不知道在每个年龄应该优先考虑什么,如何系统地社交化,或者如何在锻炼限制与发展需求之间取得平衡。
错过早期社交机会(尤其是前几个月)和不一致的例程可能会导致以后出现可避免的行为挑战。
我们的解决方案:提供温和的日常计划,适应幼犬的确切年龄,使进度可见且具有激励性(幼犬积分、等级、掌握),并包含带有上下文提示的可搜索训练指南。
### 核心功能
- **多幼犬档案:** 在一台设备上跟踪多只幼犬,数据分离清晰。
- **今日视图 + 选中日期:** Today 默认为当天;Journey 可以设置一个选中日期,以便用户可以使用相同的 UI 审查/记录过去的日子。
- **日常例程(习惯):** 基于会话的日志记录(每天多次条目)用于散步/玩耍/训练/休息,以及基于计数的日志记录用于如厕。
- **冒险(里程碑):** 基于反思的日志记录(自信/警惕/害怕),温和重试流程,精通进度,和精通徽章。
- **幼犬积分 + 等级:** 全球进度系统,庆祝成长并加强一致性。
- **自动填充计划:** 自动用适合年龄的所需习惯和可配置数量的建议冒险填充选定的日子。
- **里程碑仪表板:** 跨里程碑类别的视觉进度,可以深入到活动中。
- **旅程历史:** 基于日历的历史和随时间的进度。
- **训练指南:** 可搜索的指南内容,包括"当前年龄指南"视图。
- **自定义:** 创建自定义活动并启用可选里程碑模块。
- **备份和恢复:** 通过平台原生的共享/导出流程将设备数据导出/导入为未加密文件。
### 高级功能
- **完全本地化:** 所有用户可见的内容都已本地化(EN/FR/NL),包括指南内容和内置活动名称/类别。
- **通知:** 本地提醒(如厕、每日签到、重试),每只幼犬的设置。
简单地写下这一点并在智能体在你的项目上工作时将其传递给它会增加很多价值,因为智能体所做的更改将考虑业务背景。
3.2 定义你的架构
定义技术要求、决策和约束。它可以是与应用程序构建方式相关的任何内容——你的应用是为哪些平台构建的,使用什么编程语言,使用什么数据库和哪些框架,它托管在哪里等等。
与产品背景类似,你希望你的智能体始终建立在你应用程序的技术背景中。如果缺少该背景,它可能会编写不兼容的更改或偏离你的代码,仅仅是因为它没有关于它是如何构建的信息。
对于 Puppypal 的 architecture.md 文件如下所示:
# 架构
本文档捕获 Puppypal 的架构和技术栈。
## 平台
- 移动端:iOS + Android
- 运行时:通过 Expo 的 React Native
- 产品立场:本地优先,能够离线(v1 中没有账户/同步)
## 语言
- TypeScript
## UI 和导航
- UI 框架:React Native
- 导航:React Navigation(底部选项卡 + 栈/模态框)
- 样式:NativeWind
- 图标:`lucide-react-native` 以匹配模型样式
- SVG:`react-native-svg`
## 状态管理
- 全局存储:Zustand
- 存储职责:仅协调(UI 调用存储操作;UI 不直接与 SQLite 对话)
## 持久化
- 数据库:通过 `expo-sqlite` 的 SQLite
- ORM/查询层:Drizzle ORM(SQLite + Expo 集成)
- 全文搜索:SQLite FTS5(需要时通过原始 SQL)
- 标识符:到处使用字符串 ID(自定义记录的 UUID)
- 派生数据策略:不持久化每日或总积分;从会话日志计算
- 迁移:迁移文件签入仓库;小而专注、可逆的更改
3.3 定义 AGENTS.md
在项目根目录中编写的良好的 AGENTS.md 文件在指导智能体如何在代码库内工作方面大有帮助。
这是一个专门用于智能体特定指导、限制和指令的文件。它是你希望智能体对每个请求都知道的信息,这是有意设计的。
它通常包含项目的简短描述、软件架构概述、你希望它遵守的任何编码约定,以及一些智能体特定的保护措施。你也可以用它写下你的智能体始终必须知道、应用和考虑的任何其他内容。在这方面,它可能与你的架构或产品文档有点重叠,但这也没关系。
对于 Puppypal,AGENTS.md 文件如下所示:
# Puppypal
此仓库包含 **Puppypal**:一个本地优先的**幼犬成长伴侣**移动应用。
## 主要指令
1. 始终为修改或引入的任何代码编写单元测试
2. 始终使用正确的类型
3. 始终在代码更改后运行 make check,并请求用户提升的权限
4. 创建具有适当文档字符串的自我文档化代码
## 应用程序做什么
- 通过适合年龄的日常例程(习惯)和基于里程碑的冒险指导幼犬主人。
- 通过幼犬积分、精通和轻量级等级系统跟踪进度。
- 提供可搜索的应用内训练指南(离线、捆绑内容)。
- 完全离线工作(没有账户,没有云同步)。
更广泛的产品文档位于:`agents/product.md`
### 移动应用程序位置
- Expo 应用程序位于 `mobile/`
- 本地运行:`cd mobile && npm start`
### 架构(分层)
生产应用程序遵循 `agents/documentation/architecture.md` 中的分层结构:
- `domain/`:仅纯业务逻辑(没有 React,没有 SQLite)
- `data/`:仓库 + SQLite/Drizzle 集成
- `store/`:全局协调状态(Zustand)
- `ui/`:屏幕/组件,没有直接数据库访问
- `navigation/`:React Navigation 设置(选项卡 + 栈/模态框)
- `app/`:应用程序引导(提供者、启动/字体、全局配置)
- `tests/`:应用程序测试(单元、集成)
更广泛的架构文档位于:`agents/architecture.md`
...
我相当频繁地更新 AGENTS.md,我依赖它来提供智能体在需要处理的任何任务之前需要知道的信息。这也使我自己的项目心理模型保持最新。
3.4 设定目标
现在你已经为你的产品、它的架构以及在代码库中工作的指导方针设置了背景。是时候开始实施了。

智能体任务执行流程图 | Kamen Zhekov
为了让你的智能体实现你想要的内容,你需要指定它的目标。有各种方法可以做到这一点,但你结构化得越好,给智能体的相关信息越多,结果就越好。
有不同的方法来实现收集这些信息和指定该目标的过程,最著名和最最近的是规范驱动的开发。我实际上通过 Agent OS 相当频繁地使用它,尽管我已经调整它以适应我的需求。如果你对它好奇,你可以查看下面的 GitHub 仓库,它是免费和开源的。
根据我的经验,使用规范作为描述智能体目标的方式适合我想要处理的大多数复杂任务。例如,在 Puppypal 中,我想将一些 React Web 视图迁移到 Expo 移动应用程序。
我开始了这个任务
将占位符 Today 屏幕替换为模型中的真实布局
并与智能体迭代,直到我们到达该任务的 spec.md:
# 规范:Today 视图 — 来自模型的 React Native UI 一致性
## 目标
在 React Native (Expo) 中实现 Today 视图,使其匹配模型预览的布局和交互,由模拟/内存存储支持,以便屏幕非一次性,并准备好以后交换到真实域 + 持久化。
## 用户故事
- 作为幼犬主人,我希望 Today 显示选定日期的例程(习惯、冒险和摘要),以便我可以跟踪和记录我幼犬的日常活动。
- 作为开发人员,我希望 Today UI 由可重用组件和稳定的面向 UI 的存储契约构建,以便我们可以用真实仓库替换模拟数据而无需重写屏幕。
- 作为多语言用户,我希望 Today 中的所有 UI 铬文本都已本地化(en/fr/nl),以便应用程序从未显示未翻译的界面字符串。
## 具体要求
**模型到 RN 屏幕映射**
- 将 `agents/documentation/mockups/mockup-preview/src/` 视为 Today 布局 + 交互的真实来源。
- 实现 RN Today 屏幕以替换 `mobile/src/ui/screens/` 下的现有占位符(例如 `mobile/src/ui/screens/TodayScreen.tsx` 或类似),匹配模型结构:选中日期页眉、指导原则芯片、每日摘要、习惯条和冒险列表。
- 将 Today 特定组件放在功能文件夹下,例如:`mobile/src/ui/features/today/*`(例如 `TodayHeader.tsx`、`GuidelineChips.tsx`、`HabitStrip.tsx`、`AdventureList.tsx`)。
**可重用 UI 组件架构**
- 从小型可重用组件组合 Today:`Card`、`IconButton`、`Chip`、`SectionHeader`、`ListRow`、`EmptyState` 和模态表单/页面布局。
- 特定于功能的组件使用功能本地组件,并将真正的共享原语保留在 `mobile/src/ui/components/` 中。
- 使用 `mobile/src/ui/theme/*` 中的主题标记和排版进行颜色/间距/字体;避免在 Today 组件中硬编码值。
- 确保触摸目标对手指友好(约 44px)并为 Today 页眉和习惯控件中的仅图标控件添加 `accessibilityLabel`。
**内存 UI 存储契约**
- 通过应用程序中使用的全局内存存储(Zustand)暴露 Today 面向的状态/操作;保持模拟数据导入在种子/适配器层后面。
- Today 所需的 UI 状态:
- `activePuppyId`(字符串)
- `selectedDate`(ISO 日期字符串)
- `todayPlanItems`(选定日期的习惯/冒险描述符列表)
- `habitSessions`(选定日期的记录习惯会话记录)
- `adventureAttempts`(Today 中列出的冒险的尝试/反思)
- Today 所需的 UI 操作:
- `selectPuppy(id)`
- `setSelectedDate(date)`
- `toggleHabitSession(habitId, options?)`(开始/停止或标记完成;需要时打开持续时间/如厕流程)
- `logPottyEvent(sessionId, details)`
- `addAdventureToDate(activityId, date)` / `removeAdventureFromDate(activityId, date)`
- `updateAdventureReflection(adventureAttemptId, reflectionText)`
- `openModal(modalName, payload)` / `closeModal()`
- 将计算/派生值(例如每日摘要总计、精通标记、today 内标志)保留在选择器中,以避免 Today 组件之间的重复。
...
这是非常广泛和密集信息的,所以虽然 SDD 是一个很棒的工具,但它不一定是你对智能体的每个任务的最佳方法。也许你只是想更改按钮的颜色,那么你可能只是默认进行氛围编码。但是当你处理复杂的更改时,SDD 是一个非常可靠的方法。
根据我的经验,当目标通常需要一些深入分析或理解,可能影响多个层或代码文件如业务逻辑,或接触数据模型并涉及编写迁移时,我会将目标制定为规范。
3.5 分解为任务
在智能体开始实现其目标之前的最后一步是将规范分解为具体任务列表。一个好的任务是足够具体的,智能体可以以专注的方式完成它,但仍然足够高级以具有自己的意义。
一个任务例如是实现某个业务逻辑的函数,但编写该函数的一行代码不是任务。
对于上面的 spec.md,这是 task.md 分解的样子:
# 任务列表:Today 视图
## 概述
实现 Today 屏幕及其直接相关的存储和模态流程,以便 Today 选项卡在布局和核心交互上匹配模型预览。此文件按顺序列出所有任务。
- [ ] 验证最小依赖表面并确保不需要新的未经批准的本机依赖;如果需要本机依赖,请通过 `npx expo install` 安装。
- [ ] 确保 `mobile/index.ts` 中存在 `import 'react-native-gesture-handler';`,仅在需要手势驱动交互时。
- [ ] 添加或扩展 `mobile/src/store/useAppStore.ts` 以暴露 Today 面向的状态/操作:`activePuppyId`、`selectedDate`/`dateKey`、`todayPlanItems`、`habitSessions`、`adventureAttempts` 以及操作 `setSelectedDate`、`selectPuppy`、`toggleHabitSession`/`startHabitSession`/`stopHabitSession`、`logPottyEvent`、`addActivityToDate`、`removeActivityFromDate`、`updateAdventureReflection`、`openModal`、`closeModal`。
- [ ] 如果需要为 Today 视图模型稳定性,添加 `mobile/src/store/types.ts` 条目(幼犬、习惯、活动、会话、尝试类型)。
...
- [ ] 实现 `mobile/src/ui/screens/HabitDurationScreen.tsx` 模态框:捕获持续时间、笔记、如厕详细信息,并更新存储中的 `habitSessions`;确保键盘安全布局。
- [ ] 实现 `mobile/src/ui/screens/AddActivityScreen.tsx` 模态框:最小搜索/添加流程(如果可用则使用 `fuse.js`)和添加到日期操作。
- [ ] 实现 `mobile/src/ui/screens/CustomActivityScreen.tsx` 模态框:创建自定义活动并将其添加到选定日期的简单表单(如果可用则使用 `react-hook-form`,否则使用受控表单)。
- [ ] 实现 `mobile/src/ui/screens/ActivityDetailScreen.tsx` 模态框:显示活动详细信息并允许添加/编辑反思;更新应在关闭后在 Today 中可见。
- [ ] 在 `mobile/src/navigation/RootNavigator.tsx` 中注册模态路由,仅在现有导航尚未暴露这些模态框时在 `mobile/src/navigation/types.ts` 中添加类型;更喜欢重用当前的模态注册。
- [ ] 将所有 Today UI 交互连接到存储操作/选择器(日期导航、幼犬切换、习惯会话更新、添加/删除活动、反思更新),并确保每只幼犬隔离。
## 验证命令
- `cd mobile && npm run typecheck`
- 手动:启动应用程序(`cd mobile && npm start`)并运行上面列出的手动冒烟检查。
## 注释
- 默认交互规则:持续时间/如厕习惯打开习惯持续时间模态框;简单勾选习惯内联切换完成。
- 对 `dateKey` 使用 `date-fns` `format(date, 'yyyy-MM-dd')` 以避免时区偏差问题。
- 不要直接导入模型预览资产;将任何需要的固定装置图像放在 `mobile/assets/mockup/` 下,并通过静态 `getImageSource` 助手解析。
当你要求你的智能体生成这个计划时,有很多重要的事情需要它考虑——它在每个步骤期望编辑的代码,它可以重用什么现有代码,它将如何验证其更改有效且没有破坏东西等等。这些是你作为开发人员会问自己的同样问题,强迫智能体考虑它们通常使它交付的质量高得多。
3.6 验证和纠正
对我来说,这可以说是这个流程中最重要的一部分。像人类一样,智能体很少能立即提出完美的解决方案。定义你的目标,将其分解为任务,最重要的是实施更改是容易出错的,推动你的智能体检查它所做的工作并在它识别问题时纠正它是非常重要的。
这是一个反馈循环:
- 智能体开始实施任务
- 它在编辑期间运行测试和检查器并修复失败
- 它完成任务并请求审查
- 另一个智能体读取实施的内容并识别问题
- 主要智能体读取识别的问题并解决它们
- 重复,直到没有发现关键问题
如果你仍然不相信自动化测试和其他自动化检查很重要,我希望这会推动你为你的 AI 智能体正确设置它们。
3.7 审查
我们还没有达到可以简单地把一切都交给智能体的地步,所以一旦任务完成,你会进行最终审查。因为智能体一直在验证和纠正它的工作,这个审查通常比你审查它的"初稿"要少痛苦得多,但你仍然必须验证更改。它可能错误地实施了一些业务逻辑,也许规范中有些不清楚,也许它错过了一个错误,你永远不知道。
4、尝试一下
如果你已经在玩智能体,或者你有兴趣尝试你读到的内容,我鼓励你选择一个你在乎的小项目,并尝试使用本文的流程端到端地处理几个规范:
- 安装和设置 OpenCode 和 Agent OS,并阅读一些关于 AgentOS 如何工作以及如何使用的信息这里
- 为你的项目设置一个 git 仓库
- 要求你的智能体运行
plan-product.md来创建你的产品和技术栈文档 - 当你心中有一个具体的更改时,要求你的智能体运行
shape-spec来形成你的第一个规范,然后在你对你描述的目标满意后运行write-spec - 使用
create-tasks创建任务列表,并使用implement-tasks启动实施 - 在一个新的 OpenCode 窗口中(或通过从主聊天中标记
@general智能体),要求它审查当前的 git 更改,并将其发现分为重要和次要发现。 - 将审查传递给你的主要智能体,并重复,直到没有发现重要问题或你对结果满意
我每天都将此流程用于我的工作,但让我更深入地研究它的项目是 Puppypal,如果你想阅读更多关于它的内容或者只是看看一些可爱的幼犬,请前往下面的文章。
5、前进的道路
我不认为有一种正确的方法来进行 AI 辅助开发。不同的团队和代码库需要不同的方法,AI 开发确实有一个真正的学习曲线。
对我来说,应用本文中描述的工作流程已经改变了我对编码智能体的期望。它提供可靠的成果,适用于多种问题,非常适合我的日常工作和个人项目。
这些方法都没有取代基础;它们依赖于基础。领域知识、产品意识和工艺仍然承担大部分重量。智能体帮助你更快地移动并探索更多选项,但它们依靠那个基础来做任何有用的事情。如果你不知道你在做什么,你如何自动化你的工艺?
原文链接:氛围工程实用指南 - 汇智网
更多推荐



所有评论(0)