指挥后台工作进程
本指南介绍如何以指挥者而不是工作进程的身份运行一段对话:会话负责读取和验证,后台智能体负责编辑。
输入 /vibe 后会发生什么变化
标题为“输入 /vibe 后会发生什么变化”的部分有两件事,其中只有第一件由机制强制保证:
- 会话自身的工具降级为只读,另外还剩五个工作进程动词。它影响仓库的唯一途径是通过工作进程,而它了解发生了什么的唯一途径是读取工作进程动过的文件。
- 它被告知要通过读取来验证,而不是靠相信。 工作进程的报告只是关于它做了什么的一种声称,而不是它确实做成了的证据。
第一件才是关键。一个仍能 grep、仍能编辑的指挥者,在压力之下就会亲自动手去做这些工作,而这正是这套机制存在的目的——避免这种失败模式。
/vibe migrate the auth module to the new session API工作进程从空白开始
标题为“工作进程从空白开始”的部分工作进程从未见过你的对话,以后也永远不会看到。简报就是它的全部上下文。
这正是这套模式保持低成本的原因——二十个工作进程各自持有指挥者的历史,代价会是指挥者上下文的二十倍——也正是这一点让简报难以撰写。“顺便把另一个也做了”,对指挥者读起来是一条完整的指令,对一段全新的会话则完全等于什么都没说。
一份好的简报会点明文件、命令以及“完成”的定义:
在
lib/features/auth/中,把对SessionStore.read(key)的每一处调用替换为SessionStore.get(key)。新方法返回Future<String?>,而旧方法返回String?,因此调用方需要await。完成后运行fvm flutter analyze lib/features/auth,并报告所有你无法修复的错误。
五个动词
标题为“五个动词”的部分| 动词 | 作用 |
|---|---|
vibe_spawn |
依据一份简报启动一个工作进程。立即返回。 |
vibe_list |
所有人的层级、状态、已用时间和最近一次结果 |
vibe_send |
为已结束回合的工作进程追加一个后续回合 |
vibe_wait |
阻塞,直到某个工作进程结束 |
vibe_kill |
停止某一个工作进程 |
启动工作进程在设计上就是异步的。每次启动都阻塞的指挥者,等于一次只跑一个工作进程,这不过是用更慢的方式做它本来就在自己做的事。只有当你确实缺了某个具体答案就无法继续时,才使用 vibe_wait。
两个层级
标题为“两个层级”的部分| 层级 | 适用场景 |
|---|---|
fast |
规格明确的机械性工作——编辑、重命名、草拟、运行命令 |
good |
设计、判断,或审查一个 fast 工作进程的产出 |
一种常见的做法是把 fast 工作进程扇出到相互独立的文件上,然后再启动一个 good 工作进程,审查它们共同的产出。
这一部分决定了这套模式到底有没有价值。
vibe_list→ w1 [fast] auth-migrate — done (48s): Edited lib/features/auth/session.dart … w2 [fast] tests — running (12s)然后读取它提到的那些文件。指挥者拥有 read、search、lsp 和 ast_grep;保留这些工具正是全部意义所在。把报告照单全收的指挥者,只是在替其他智能体的乐观说辞做摘要。
在一轮工作进程结束后执行 lsp(action: "diagnostics", file: "*"),通常是最快的单项检查。
当工作进程跑偏时
标题为“当工作进程跑偏时”的部分终止它,重新写一份简报。一份全新且经过修正的简报比一场争论更便宜,而且 vibe_send 只对已经结束回合的工作进程有效。
vibe_kill(worker_id: "w2")vibe_spawn(brief: "…corrected…", label: "tests", tier: "fast")- 最多八个并发工作进程。 这是花费上的上限,而不是技术限制:每一个都是完整的模型会话,而扇出二十个工作进程的指挥者,已经不再清楚它们都在做什么了。
- 没有工作进程能比这个模式活得更久。 运行结束时,它们每一个都会被停止,转录中会说明一共多少个。对话已经继续往下走了,后台智能体却还在编辑文件——这是绝对不能出现的一种失败。
- 工作进程本质上就是普通的子智能体。 相同的深度上限、相同的护栏策略、相同的运行日志子项。vibe 改变的是由谁驱动它们,而不是它们被允许做什么——因此工作进程的 write 和 exec 调用仍会弹出批准提示。
什么时候不该用它
标题为“什么时候不该用它”的部分vibe 模式适用于能拆解成一份份独立简报的工作。如果下一步依赖上一步的产出,你描述的其实是流水线或编排,这两者都能以正确的方式表达依赖关系,而不必让指挥者用 vibe_wait 去模拟它们。