拆.
提示词——AI 怎么'听懂'你的话 · 第 08

Mode 切换的 3 态机器

Plan / Build / Stop

4500读完约 23 分钟craft:B+发布于 2026-06-21

一、原理:AI Agent 的双阶段工作流

让 AI Agent 直接动手做事有个核心问题——它经常做错方向

你让它"加一个用户登录功能",它可能马上就开始改 5 个文件、改架构、加新依赖。改完了你发现它对"用户登录"的理解跟你不一样——你想要的是 OAuth 第三方登录,它做的是邮箱密码登录。已经改完的代码要么回滚、要么改造,时间和 token 都浪费了。

这个问题不是 LLM 能力不足,是工作流设计的缺失。人类工程师做事的方式从来不是"一上来就动手"——他们先想清楚要做什么、确认理解对了、有了清晰的计划再动手。但很多 AI Agent 跳过了"想清楚"这一步——直接进入"动手"。

为什么?因为 LLM 的训练倾向于"给出完整回答"。它在 SFT 阶段学到的"理想行为"是"用户问什么,我做什么"——不是"用户问什么,我先确认理解再做"。这种"直接动手"的倾向在普通问答场景里是优点,在 Agent 场景里是 bug。

解决方案是显式的双阶段工作流

Plan 阶段——只能读、不能改。AI 在这个阶段做的事是:理解任务、探索代码、问用户问题、写一份明确的计划。计划写完后等用户确认。

Build 阶段——按计划动手。AI 在这个阶段做的事是:按 Plan 阶段定下的方案改代码、跑测试、汇报进度。

这种双阶段分离有几个好处。

好处 1:错误及早发现。如果 AI 对任务的理解错了,错误暴露在 Plan 阶段(一份不对的计划),不是 Build 阶段(一堆改错的代码)。修计划比修代码便宜得多。

好处 2:用户有审查机会。Plan 阶段产出一份可读的文档,用户能在动手前看到。这给了用户介入的窗口——可以纠正方向、提供更多信息、否决方案。

好处 3:上下文压力分散。复杂任务一次性做完会占用大量 context。分两段做让每段都更聚焦——Plan 阶段只关心方案设计,Build 阶段只关心实现细节。

但实现"双阶段"在 prompt 层有挑战——LLM 怎么知道现在是 Plan 还是 Build?怎么阻止它在 Plan 阶段动手?怎么从 Plan 平滑过渡到 Build?

这就是 mode 切换的设计问题。opencode 的方案是一个 3 态机器:Plan 模式、Build 模式、Stop(强制停止)模式。每个模式有自己的 prompt 文件,切换时通过特殊机制注入新模式的 prompt。

二、案例:opencode 的 plan-mode / build-switch / max-steps

opencode 的 mode 切换涉及几个 prompt 文件——都在 packages/opencode/src/session/prompt/

  • plan.txtplan-mode.txt — Plan 模式的 prompt
  • build-switch.txt — 从 Plan 切到 Build 时的提醒
  • max-steps.txt — 强制停止时的提示(详见 1.9 章)
  • plan-reminder-anthropic.txt — Plan 模式下针对 Claude 的特别提醒(已废弃)

我们逐个看。

Plan 模式的 prompt

opencode 实际上有两份 Plan 模式 prompt——plan.txt(旧版)和 plan-mode.txt(新版)。新版用 experimentalPlanMode flag 切换启用。这种"新旧并存"反映了 mode 设计的演化。

plan-mode.txt 的核心是 5 阶段工作流

Phase 1: Initial Understanding
- Use explore subagents to understand the codebase
- Run up to 3 parallel explores for related areas
- Ask user clarifying questions if needed

Phase 2: Planning
- Spawn 1 plan subagent to design the implementation
- Use Phase 1's findings as input

Phase 3: Synthesis
- Collect agent responses
- Use question tool to confirm trade-offs with user

Phase 4: Final Plan
- Write the synthesized plan to a plan file
- Include: recommended approach, key file paths, verification steps

Phase 5: Call plan_exit tool
- At the very end of your turn, call plan_exit
- Do not stop unless asking a question OR calling plan_exit
- Do NOT use question tool to ask 'Is this plan okay?' - that's what plan_exit does

这个设计有几个值得拆开看的细节。

细节 1:多 agent 并行——Phase 1 让 AI 并行起最多 3 个 explore subagent。这把"探索代码"这件 IO 密集的事并行化,节省时间。

细节 2:人机循环——Phase 3 明确要求"用 question tool 跟用户确认 trade-offs"。这给了用户在 Plan 阶段就介入的机会,不是等到 Build 完才发现方向错了。

细节 3:可交付件——Phase 4 把 Plan 写成一份明确的文件(.opencode/plans/ 目录下的 markdown)。这份文件成为 Plan → Build 过渡的"交接物"——Build 阶段直接读这个文件按计划执行。

细节 4:明确的终止信号——Phase 5 要求调用 plan_exit 工具。这给了 harness(opencode 的主循环)一个清晰信号"Plan 完了"——可以触发 mode 切换。如果没有这个明确终止,主循环不知道什么时候让用户确认。

Build 切换的 5 行 prompt

当用户在 Plan 完成后批准切到 Build 模式时,opencode 在 user message 里注入一段叫 build-switch.txt 的提醒。完整内容只有 5 行:

<system-reminder>
Your operational mode has changed from plan to build.
You are no longer in read-only mode.
You are permitted to make file changes, run shell commands, and utilize your arsenal of tools as needed.
</system-reminder>

注意几件事:

  • <system-reminder> XML 标签包装——告诉 LLM 这是系统层面的提醒
  • 不是新的完整 system prompt——只是一段追加的提醒
  • 用积极语气("You are permitted")而非禁令式("You are no longer prohibited from")
  • 总共 5 行——故意短

为什么这么短?因为前面 Plan 阶段已经把约束铺好了(read-only),Build 阶段只需要"放开约束"——一句"现在你可以动手了"就够。详细的"该做什么"由 Plan 阶段产出的 plan 文件指导,不需要在 mode 切换 prompt 里重复。

这种少即是多的设计哲学在 mode 切换里特别重要。如果 build-switch.txt 写得很长——比如重新解释 Build 阶段该做什么、怎么做、注意什么——会跟 Plan 阶段写的 plan 文件冲突。短到只说"模式切换了",能让 plan 文件成为唯一的指令源。

为什么不只用一个 mode

你可能会问——为什么需要 Plan / Build 两个模式?让 AI 自己决定什么时候 plan、什么时候 build 不行吗?

答案是"理论上可以,实际不行"。LLM 在没有显式 mode 切换时的实际行为是:

  • 90% 的情况下跳过 plan,直接 build
  • 10% 的情况下花太长时间 plan,根本不进入 build

没有明确的 mode 区分,LLM 在"想清楚"和"动手"之间的平衡是混乱的。显式 mode 切换强制了这种平衡——Plan 阶段必须有 plan 文件、必须等用户确认、必须明确终止。这种"显式强制"让 LLM 没法跳过 plan 直接 build,也没法在 plan 上无限循环。

三、设计启示:怎么设计 AI Agent 的 mode 系统

这一章的核心论点:双阶段工作流是 AI Agent 的必备机制——单阶段 Agent 必然在方向错误的代价上栽跟头

如果你设计 AI Agent,关于 mode 系统有几条原则。

1. 至少要有 plan / build 两个 mode。哪怕你的产品看起来简单("用户问问题、AI 答"),只要涉及多步骤行动,就需要 plan 阶段。不一定叫 plan——叫 "preview"、"draft"、"propose" 都行。本质是"做之前先确认方向"。

2. mode 之间用文件交接,不用 message 交接。Plan 阶段产出一份 plan 文件,Build 阶段读这个文件。不要让 plan 内容只存在于 message 历史里——message 会被 compaction 截断、丢失、误读。文件是更可靠的交接物。

3. mode 切换需要明确的"切换瞬间"。要么是工具调用(opencode 的 plan_exit)、要么是 slash command(/build)、要么是 UI 按钮。不要让 LLM"自己感觉差不多了"就切——这种隐式切换很不稳定。

4. 切换 prompt 越短越好。新 mode 的完整指令应该在 mode 自己的 prompt 里(plan-mode.txt 那种),不在切换的 reminder 里。切换 reminder 只说"模式变了"就够。

5. 给用户审查 plan 的机会。Plan 完成后强制暂停,等用户看完 plan 文件再触发 Build。如果 Plan 完了自动接 Build,那 Plan 没意义——用户来不及干预。

6. Plan 阶段限制能力。Plan 阶段的 AI 应该只能 read,不能 write、不能 bash、不能改环境。把"做的能力"剥离,让 AI 只能用"思考"和"探索"。否则它会忍不住偷偷动手。

7. Build 阶段不要重新规划。一旦进入 Build,AI 应该按 plan 文件执行,不要"想想还有没有更好的方案"。如果发现 plan 不对,应该停下来问用户而不是擅自改方案。

8. 明确的 stop 机制。AI 有时候会陷入无限循环——build 不完、plan 不停、tool call 一波接一波。需要一个强制 stop 机制(max-steps)兜底。这是下一章 1.9 的话题。

最后一个观察。Plan / Build 二分背后是一种深层的产品哲学——AI Agent 不应该假装能独立完成所有事。它需要用户在关键节点参与决策。强制 mode 切换是这种哲学的实现机制——通过 Plan 阶段强制暴露 AI 的思路,给用户检查机会;通过明确的 plan_exit 切换,让用户的批准成为下一阶段的前提。

这跟"全自动 AI"的产品姿态是相反的。"全自动"假设 AI 能独立做对所有事——只在最终输出时给用户看。"双阶段 mode"假设 AI 经常做错方向——需要在做之前让用户看到方案。两种姿态选哪个不是技术问题,是产品判断。opencode 选了后者,第 7 篇的 Permission 系统和 Question 工具是这种判断的进一步延伸。

下一章 1.9 我们看 max-steps——3 态机器里的"强制 stop"是怎么实现的。这是 prompt engineering 里一个特别精妙的设计——把外部约束伪装成 LLM 自己的认知。