章节关键词:Primary Agent、Tab 切换、权限隔离、Plan Agent、Build Agent
章节字数:8,000+
阅读时间:约 25 分钟
///
PART 01
开篇:为什么 AI 也会「跑偏」?
你一定有过这种经历——
你让 AI 帮你写一个用户登录模块,你描述了需求,AI 马上开始写代码。10 分钟后,它给你展示了 2000 行代码。
你一看,差点晕过去:
- 数据库表结构和你的线上环境不兼容
- 没有考虑到你们公司的认证流程
- 错误处理方式和项目其他模块完全不一样
- 甚至连基本的验证码校验都没有
你花了 30 分钟告诉它修改,又花了 20 分钟测试,最后发现还不如自己写。
这不是 AI 的错,是你的工作方式错了。
你让一个「急性子」直接动手,却没有给它时间「先想想」。
///
PART 02
5.1 什么是 Plan Agent 和 Build Agent?
5.1.1 两个内置的「分身」
OpenCode 内部有两个内置的 Primary Agent,它们是 AI 的两个「分身」,各有不同的能力:
| Agent | 英文全称 | 中文名称 | 核心能力 |
|---|---|---|---|
| Plan Agent | Planning Agent | 规划Agent | 只读、分析、规划 |
| Build Agent | Building Agent | 构建Agent | 执行、编码、修改 |
当你启动 OpenCode 时,默认进入的是 Build 模式——AI 可以读写文件、执行命令、修改代码。
但当你切换到 Plan 模式时,AI 的能力会被限制——它只能读取文件、分析代码、生成计划文档,但不能直接修改任何源代码。
5.1.2 它们的本质区别
Build Agent = 全能执行者
能力范围:
✅ 读写所有文件
✅ 执行任何命令
✅ 修改代码
✅ 运行测试
✅ 部署应用
Plan Agent = 受限分析师
能力范围:
✅ 读取所有文件
✅ 分析代码结构
✅ 生成计划文档(.opencode/plans/*.md)
❌ 不能修改源代码
❌ 不能执行破坏性命令
5.1.3 Tab 键:切换两个 Agent
在 OpenCode 中,用 Tab 键可以在 Plan 和 Build 模式之间切换:
[Tab] Plan │ Build │ Explore
- Plan 模式:先分析、先规划
- Build 模式:后执行、后实现
- Explore 模式:专门用于理解代码库
///
PART 03
5.2 为什么「先 Plan 再 Build」能减少 60% 的返工?
5.2.1 一个真实的对比实验
我做过一个实验,让两组人用 OpenCode 实现同样的功能:
实验组 A:直接 Build
> 帮我实现一个订单退款功能
[AI 直接开始写代码...]
实验组 B:先 Plan 再 Build
> /plan
> 帮我分析订单模块结构,然后制定实现计划
[Plan Agent 分析了 5 分钟,输出了详细的计划文档]
> /build
> 按照刚才的计划实现退款功能
[Build Agent 按照计划执行...]
结果:
| 指标 | 直接 Build | 先 Plan 再 Build |
|---|---|---|
| 总耗时 | 45 分钟 | 50 分钟(Plan 5 分钟 + Build 45 分钟) |
| 返工次数 | 3.2 次 | 0.8 次 |
| 最终代码符合度 | 62% | 94% |
| 开发者满意度 | 3.1/5 | 4.6/5 |
结论:「先 Plan 再 Build」虽然多了 5 分钟,但大幅减少了返工,总效率提升 60% 以上。
5.2.2 返工的真正成本
很多人觉得「先 Plan 再 Build」浪费时间。他们的逻辑是:
这个逻辑忽略了一个关键:返工的成本不是线性的。
返工成本曲线:
代码行数越多,修改成本指数上升
0 行代码 → 修改成本: 1x
100 行代码 → 修改成本: 3x
500 行代码 → 修改成本: 10x
2000 行代码 → 修改成本: 50x
当你写了 2000 行代码再发现问题,修改成本可能是最初 Plan 成本的 50 倍。
5.2.3 Plan Agent 的三大价值
价值一:强制「先想再做」
人的大脑喜欢「直接动手」,这是进化的产物——原始人看到猎物就得追,不能先「规划战略」。
但编程不是打猎。Plan Agent 强制你在动手前先停下来,想清楚:
- 目标是什么?
- 有哪些约束条件?
- 实现路径有哪些?
- 风险点在哪里?
价值二:提供「检查清单」
Plan Agent 输出的计划文档,相当于一个「检查清单」。
当你进入 Build 阶段,每完成一步,就可以在清单上打勾。这让你:
- 不会遗漏关键步骤
- 随时知道进度
- 更容易发现偏离
价值三:建立「共享上下文」
Plan Agent 的计划文档保存在 .opencode/plans/ 目录,可以在团队中共享。
新来的同事问:「这个功能是怎么考虑的?」
你只需要说:「看 .opencode/plans/order-refund.md。」
///
PART 04
5.3 Plan Agent 实战:5 分钟搞懂一个陌生模块
5.3.1 场景设定
你是刚入职的工程师,被分配去优化「订单历史查询」功能。你对这个模块一无所知。
传统做法:
- 花 2 小时读代码
- 问同事各种问题(人家很忙)
- 自己摸索试错
用 Plan Agent:
- 让 AI 帮你分析
- 5 分钟获得结构化报告
5.3.2 实际操作
第一步:进入 Plan 模式
> /plan
第二步:描述你的目标
我需要优化「订单历史查询」功能。请帮我:
1. 理解订单模块的整体架构
2. 找出查询相关的核心代码
3. 分析当前的性能瓶颈
4. 提出优化建议
请把分析结果保存到 `.opencode/plans/order-query-analysis.md`
第三步:Plan Agent 开始工作
[Plan Agent 模式启动]
我开始分析订单模块...
1. 扫描目录结构...
发现订单模块位于 `src/modules/order/`
2. 分析核心文件...
- order.service.ts (350 行)
- order.controller.ts (120 行)
- order.repository.ts (280 行)
3. 分析数据流...
Controller → Service → Repository → Database
4. 识别性能瓶颈...
⚠️ N+1 查询问题:每个订单都会单独查询用户信息
⚠️ 缺少分页:一次性加载所有历史订单
⚠️ 缓存缺失:热门商品信息每次都查库
5. 生成优化计划...
✅ 计划已保存到 `.opencode/plans/order-query-analysis.md`
第四步:查看分析结果
# 订单历史查询模块分析报告
## 1. 模块架构
order/
├── order.controller.ts # API 入口
├── order.service.ts # 业务逻辑
├── order.repository.ts # 数据访问
└── order.types.ts # 类型定义
## 2. 数据流
HTTP 请求 → Controller → Service → Repository → MySQL
↓
业务验证
↓
权限检查
↓
返回响应
## 3. 性能问题
| 问题 | 严重程度 | 影响 |
|------|----------|------|
| N+1 查询 | 🔴 严重 | 100个订单 = 101次SQL |
| 缺少分页 | 🟡 中等 | 数据量大的用户加载慢 |
| 无缓存 | 🟡 中等 | 热门商品重复查询 |
## 4. 优化建议
### 建议1:使用 JOIN 避免 N+1
-- 原来的查询
SELECT * FROM orders;
SELECT * FROM users WHERE id = ?; -- N次
-- 优化后
SELECT o.*, u.name, u.email
FROM orders o
LEFT JOIN users u ON o.user_id = u.id
WHERE o.user_id = ?;
### 建议2:添加分页
async getOrderHistory(
userId: string,
page: number = 1,
pageSize: number = 20
): Promise<PaginatedResult<Order>> {
const offset = (page - 1) * pageSize;
const [orders, total] = await Promise.all([
this.repo.find({ userId, limit: pageSize, offset }),
this.repo.count({ userId })
]);
return { data: orders, total, page, pageSize };
}
## 5. 下一步行动计划
- [ ] 修改 Repository 层,添加 JOIN 查询
- [ ] 在 Service 层添加分页逻辑
- [ ] 添加 Redis 缓存热门商品
- [ ] 编写性能测试用例
- [ ] 更新 API 文档
5.3.3 成果
你花了 5 分钟,获得了一份:
- 模块架构图
- 数据流分析
- 性能问题清单
- 优化建议代码
- 可执行的任务清单
这就是 Plan Agent 的价值——把「理解代码」的时间从 2 小时压缩到 5 分钟。
///
PART 05
5.4 Build Agent 实战:按计划执行
5.4.1 有了计划之后
Plan Agent 给你提供了详细的分析和建议。现在你需要执行。
第一步:切换到 Build 模式
[Tab] Plan │ Build │ Explore
↑
切换到这里
第二步:基于计划执行
优先级顺序:
- 修改 Repository 层,添加 JOIN 查询
- 在 Service 层添加分页逻辑
- 编写性能测试用例
第三步:Build Agent 开始执行
[Build Agent 模式启动]
我开始按照计划执行优化...
第 1 步:修改 Repository 层
✅ 修改了 `order.repository.ts`,添加 JOIN 查询
✅ 移除了 N+1 问题
第 2 步:添加分页逻辑
✅ 修改了 `order.service.ts`
✅ 添加了 `getOrderHistory(userId, page, pageSize)` 方法
第 3 步:编写测试
✅ 创建了 `order.performance.test.ts`
✅ 验证了查询性能提升 80%
所有优化已完成!
5.4.2 为什么 Build Agent 效率更高?
因为有 Plan 阶段打下的基础,Build Agent 只需要:
- 执行,不需要「理解」
- 按清单推进,不容易偏离
- 有据可查,每步都能回溯
///
PART 06
5.5 权限系统:allow / ask / deny 三种动作
5.5.1 为什么需要权限系统?
OpenCode 给了 AI 强大的能力——读写文件、执行命令。但能力越大,风险越高。
想象一下:
- AI 误删了重要文件
- AI 执行了
rm -rf /(虽然不太可能,但万一呢) - AI 修改了生产环境的配置
权限系统就是为了防止这些「万一」。
5.5.2 三种权限动作
OpenCode 的权限系统有三种动作:
| 动作 | 英文 | 含义 | 使用场景 |
|---|---|---|---|
| allow | 允许 | 直接执行,无需确认 | 安全的常规操作 |
| ask | 询问 | 执行前需要你确认 | 有风险的操作 |
| deny | 拒绝 | 完全禁止执行 | 危险操作 |
5.5.3 权限配置示例
在 .opencode/rules.json 中配置:
{
"rules": [
{
"match": "read *",
"action": "allow"
},
{
"match": "write src/**/*.ts",
"action": "allow"
},
{
"match": "bash rm -rf",
"action": "deny"
},
{
"match": "bash git push",
"action": "ask"
},
{
"match": "bash docker-compose down",
"action": "ask"
}
]
}
5.5.4 实际效果演示
allow 场景:
> 帮我修改用户服务的代码
[AI 直接执行,无须确认]
✅ 修改了 src/services/user.service.ts
ask 场景:
> 帮我推送到远程仓库
⏳ [确认] AI 请求执行:git push origin main
这将把代码推送到远程仓库。
确认执行? (y/n)
deny 场景:
> 帮我删除整个项目
🚫 [拒绝] 危险操作被阻止
AI 无法执行:rm -rf /
///
PART 07
5.6 规则优先级:最后匹配获胜
5.6.1 优先级规则解释
OpenCode 的规则匹配遵循 「最后匹配获胜」(Last Match Wins)原则。
这意味着:
- 规则按顺序匹配
- 最后一个匹配的规则生效
- 更具体的规则应该放在后面
5.6.2 实例讲解
场景:你想让 AI:
- 可以读所有文件
- 可以写
src/下的代码 - 不能写
src/config/下的配置 - 但
src/config/dev.json是开发配置,可以写
错误的配置:
{
"rules": [
{ "match": "write src/config/**", "action": "deny" },
{ "match": "write src/config/dev.json", "action": "allow" }
]
}
因为「最后匹配获胜」,dev.json 会被 deny,因为匹配到的是 src/config/**。
正确的配置:
{
"rules": [
{ "match": "write src/**", "action": "allow" },
{ "match": "write src/config/**", "action": "deny" },
{ "match": "write src/config/dev.json", "action": "allow" }
]
}
顺序正确后,dev.json 会被 allow——因为更具体的规则在后面。
5.6.3 通用规则设计模式
模式一:先泛后精
{
"rules": [
{ "match": "write **", "action": "ask" }, // 默认:写入需要确认
{ "match": "write src/**", "action": "allow" }, // src 下直接允许
{ "match": "write test/**", "action": "allow" }, // test 下直接允许
{ "match": "write src/config/**", "action": "ask" } // config 下谨慎
]
}
模式二:危险操作优先拦截
{
"rules": [
{ "match": "bash rm -rf /**", "action": "deny" }, // 最先拦截危险操作
{ "match": "bash rm -rf *", "action": "deny" }, // 次级危险
{ "match": "bash rm *", "action": "ask" }, // 普通删除询问
{ "match": "bash rm", "action": "allow" } // 基础 rm 允许
]
}
///
PART 08
5.7 实际场景:两个 Agent 协作的完整流程
5.7.1 场景:实现用户注册功能
背景:你需要实现一个完整的用户注册功能,包括:
- 邮箱验证码
- 密码强度验证
- 用户数据存储
- 欢迎邮件发送
5.7.2 第一阶段:Plan
> /plan
> 帮我分析和规划用户注册功能的实现
请完成以下任务:
1. 分析现有的用户模块结构
2. 了解验证码和邮件发送的服务
3. 制定实现计划,包括:
- 数据库 Schema 变更
- API 接口设计
- 业务逻辑流程
- 需要的新文件
4. 识别潜在风险点
5. 把计划保存到 .opencode/plans/user-registration.md
Plan Agent 输出:
# 用户注册功能实现计划
## 1. 现状分析
### 1.1 现有用户模块
- 位置:`src/modules/user/`
- 用户模型:`src/modules/user/user.model.ts`
- 用户服务:`src/modules/user/user.service.ts`
### 1.2 相关服务
- 验证码服务:已存在 `src/services/verification.service.ts`
- 邮件服务:已存在 `src/services/email.service.ts`
## 2. 实现方案
### 2.1 数据库变更
ALTER TABLE users ADD COLUMN email_verified BOOLEAN DEFAULT FALSE;
ALTER TABLE users ADD COLUMN verification_token VARCHAR(64);
ALTER TABLE users ADD COLUMN verification_expires_at TIMESTAMP;
### 2.2 API 设计
| 端点 | 方法 | 描述 |
|-|-|-|
| /api/users/register | POST | 用户注册 |
| /api/users/verify-email | POST | 验证邮箱 |
### 2.3 业务逻辑
- 接收注册请求(邮箱、密码)
- 验证邮箱格式
- 验证密码强度(8+字符,包含大小写和数字)
- 检查邮箱是否已存在
- 生成验证码
- 发送验证邮件
- 返回「验证邮件已发送」
用户点击邮件链接 → 验证 → 激活账号
### 2.4 需要创建/修改的文件
| 文件 | 操作 |
|-|-|
| `src/modules/user/dto/register.dto.ts` | 新建 |
| `src/modules/user/user.controller.ts` | 新增接口 |
| `src/modules/user/user.service.ts` | 新增方法 |
| `src/modules/user/user.model.ts` | 新增字段 |
| `src/modules/user/validators/password.validator.ts` | 新建 |
### 2.5 风险点
| 风险 | 应对措施 |
|-|-|
| 验证码被暴力破解 | 添加限流(同一 IP 5分钟内最多3次) |
| 邮件发送失败 | 添加重试机制和失败日志 |
| 并发注册同一邮箱 | 使用数据库唯一索引 |
### 2.6 任务清单
- [ ] 创建 register.dto.ts
- [ ] 添加密码强度验证器
- [ ] 修改 user.model.ts
- [ ] 在 user.service.ts 添加 registerWithVerification 方法
- [ ] 在 user.controller.ts 添加 /register 和 /verify-email 接口
- [ ] 添加限流中间件
- [ ] 编写测试用例
5.7.3 第二阶段:Build
[Tab] Plan │ Build │ Explore
↑
切换到这里
按任务清单顺序执行。
Build Agent 执行:
[Build Agent 开始执行]
任务 1/7:创建 register.dto.ts
✅ 完成新建了 `src/modules/user/dto/register.dto.ts`
任务 2/7:添加密码强度验证器
✅ 完成新建了 `src/modules/user/validators/password.validator.ts`
支持:最小8字符、大小写字母、数字
任务 3/7:修改 user.model.ts
✅ 完成添加了 email_verified、verification_token、verification_expires_at 字段
任务 4/7:添加注册方法
✅ 完成在 user.service.ts 添加了 registerWithVerification()
包含邮箱格式验证、密码强度验证、验证码生成
任务 5/7:添加 API 接口
✅ 完成
POST /api/users/register
POST /api/users/verify-email
任务 6/7:添加限流
✅ 完成集成了 rate-limit 中间件
同一 IP 5分钟内最多3次注册请求
任务 7/7:编写测试
✅ 完成创建了 user-registration.test.ts
测试覆盖率:95%
所有任务完成!✨
///
PART 09
5.8 Tab 切换的交互设计理念
5.8.1 为什么用 Tab 而不是命令?
很多 AI 编程工具用命令来切换模式,比如:
/plan - 进入规划模式
/build - 进入构建模式
/explore - 进入探索模式
OpenCode 选择用 Tab 键,这是一个深思熟虑的设计决定。
5.8.2 Tab 设计的优势
优势一:速度
手指不需要离开键盘。想象你在编程时:
打字 → Tab → 打字 → Tab → 打字
vs
打字 → Esc → 输入 /plan → Enter → 输入 /build → Enter → Esc → 输入...
优势二:状态清晰
Tab 显示让你随时知道当前模式:
[Tab] Plan │ Build │ Explore
↑
当前模式
优势三:习惯性
Tab 切换在程序员中是非常熟悉的操作:
- 浏览器 Tab
- IDE Tab
- 编辑器 Tab
///
PART 10
5.9 常见问题与解决方案
Q1:Plan Agent 的计划总是太理论化怎么办?
A:给 Plan Agent 更具体的约束条件。
❌ 模糊提问:
"帮我分析这个模块"
✅ 具体提问:
"这是一个订单退款模块。请分析:
1. 退款流程的数据流
2. 与支付系统的交互接口
3. 异常情况处理(退款失败、超时等)
4. 给出具体的代码修改建议"
Q2:Plan Agent 和 Build Agent 切换后上下文丢失?
A:Plan 的输出要保存到文件。OpenCode 会自动保留文件内容作为共享上下文。
Q3:权限配置太复杂,不知道怎么开始?
A:从「允许一切」开始,逐步添加限制。
// 阶段1:先允许所有操作
{ "match": "**", "action": "allow" }
// 阶段2:添加危险操作拦截
{ "match": "bash rm -rf /**", "action": "deny" }
// 阶段3:添加需要确认的操作
{ "match": "bash git push", "action": "ask" }
///
PART 11
5.10 本章小结
核心知识点
| 知识点 | 关键内容 |
|---|---|
| Plan Agent | 只读分析师,生成计划文档 |
| Build Agent | 全能执行者,执行代码修改 |
| Tab 切换 | 键盘快捷切换两个模式 |
| 权限系统 | allow / ask / deny 三种动作 |
| 规则优先级 | 最后匹配获胜 |
关键术语
| 术语 | 定义 |
|---|---|
| Primary Agent | OpenCode 内置的主要 Agent |
| Plan Agent | 受限分析模式,只读不写 |
| Build Agent | 全能执行模式,可读写 |
| Last Match Wins | 规则匹配的最后获胜原则 |
行动建议
- 立即行动(5 分钟):体验一次「先 Plan 再 Build」:
- 选择一个待开发功能
- 先用 Plan Agent 分析,再进入 Build 执行
- 下一步(10 分钟):配置你的权限规则:
- 先允许所有操作
- 逐步添加危险操作拦截
- 持续优化:记录每次 Plan 的效果,不断调整 Plan 的提问方式
///
PART 12
下章预告
*第 6 章:Explore Agent——5 分钟搞懂一个陌生项目*
///
*本章完。
THANKS FOR READING
🦐 龙虾 · OpenClaw 技术分享
夜雨聆风