一个模型已经能搜索代码、修改文件和运行测试,为什么还要多模型分工?
最常见的答案是“不同模型各有所长”,但这句话不足以指导工程实践。真正需要解决的是:任务应该在哪个边界拆开,模型之间交接什么,谁拥有写权限,如何避免两边同时修改同一文件,以及最后由什么证据判断工作完成。
多模型系统的价值不在于模型数量,而在于让不同阶段拥有独立上下文、明确权限和可验收输出。 如果只是让三个模型在同一段对话里轮流发表意见,成本增加了,责任边界却没有变清楚。
这一章以 Pi Agent 这类终端编码工具为例,构建一条能在真实仓库中落地的多模型工作流。方法同样适用于其他支持模型切换、会话分支、命令行非交互模式或扩展机制的编码工具。
先区分三个容易混淆的概念
模型切换
同一个 Agent 循环在不同阶段更换模型,但继续使用相同工具和会话历史:
同一会话:快速模型探索 → 深度模型实现 → 快速模型总结
它的优点是交接成本低,缺点是后一个模型会继承前面的全部假设与噪声。适合任务阶段自然变化,但不适合需要真正独立意见的代码审查。
多模型路由
宿主根据任务类型、风险或预算选择模型:
格式整理 → 低成本模型
跨模块设计 → 强推理模型
视觉理解 → 支持图像的模型
高风险代码审查 → 独立审查模型
路由发生在调用模型之前,通常仍只有一个 Agent 在控制工具。它解决的是“这一步应该用哪个模型”,不是并发协作。
多 Agent 编排
多个拥有独立上下文的 Agent 分别执行子任务,编排器负责依赖、交接和汇总:
┌→ Agent A:调查后端
任务编排器 ──────┼→ Agent B:调查前端
└→ Agent C:检查测试
↓
汇总与验收
多 Agent 能并行,但也会引入文件冲突、重复读取、预算竞争和结论合并。只有子任务边界清晰、产物可以独立验证时,并行才真正有收益。
Pi Agent 提供了什么,又刻意没有提供什么
根据 Pi 官方仓库当前文档,Pi 的定位是一个最小终端编码 harness。默认向模型提供 read、write、edit 和 bash 四个工具,并通过 Skills、Prompt Templates、Extensions 和 Packages 扩展能力。
与多模型工作流直接相关的能力包括:
- 通过
/model或快捷键在多个 Provider 和模型间切换; - 通过
models.json接入自定义 Provider、本地模型或兼容网关; - 会话以树结构保存,可以
/tree回到旧节点,也可以/fork或/clone建立分支; - 长上下文支持手动或自动 compaction;
- Extension 可以注册命令、工具、权限门、模型交接和 sub-agent;
- print、JSON、RPC 与 SDK 模式可用于外部编排。
Pi 同时明确说明:它不把 sub-agent 和 plan mode 作为内置默认功能,而是让用户通过扩展或第三方包按自己的流程实现。官方扩展示例中提供了跨 Provider handoff、plan mode 和 sub-agent,但它们是可选实现,不应描述成 Pi 默认就会自动组织多模型团队。
这个取舍很适合作为架构提醒:工具支持多个模型,不等于工作流已经定义了模型之间的责任。
不要按品牌分工,要按产物分工
“模型 A 写代码、模型 B 做审查”仍然太模糊。更稳定的做法是为每个角色定义输入、权限和必须交付的产物。
| 角色 | 主要输入 | 权限 | 必须产出 |
|---|---|---|---|
| 侦察者 | 用户目标、只读仓库 | 只读、可运行安全查询 | 相关文件、调用链、风险与未知项 |
| 架构者 | 侦察报告、业务约束 | 只读 | 改动边界、接口契约、测试计划 |
| 实现者 | 已批准方案、目标文件 | 可写、可运行测试 | 最小代码改动与验证结果 |
| 审查者 | 原始需求、最终 diff | 只读 | 按严重度排序的问题与证据 |
| 验证者 | 代码、验收命令 | 只执行确定性检查 | 退出码、失败日志、覆盖结果 |
这里故意没有写具体模型名。模型更新很快,角色契约应该比模型生命周期更长。选择模型时再根据上下文容量、工具调用可靠性、推理质量、延迟和成本匹配角色。
验证者首先应该是程序
很多“多模型流水线”最后安排一个更强模型判断前面是否完成。这个设计仍然把事实交给概率输出。
更可靠的验收顺序是:
- 编译器、类型检查和格式化;
- 单元测试、集成测试与静态分析;
- 页面截图、协议回放或性能基准;
- 独立模型审查无法由程序表达的设计风险;
- 人工确认发布、删除和外部消息等高风险动作。
模型可以建议测试命令,但不能只说“看起来应该通过”。验收记录必须包含真实命令、退出码和关键输出。
模型提出假设
↓
程序执行验证
↓
原始结果进入交接产物
↓
模型解释结果,而不是替代结果
一份可执行的交接协议
模型之间不要只交接一段自然语言总结。建议使用固定结构:
task: 修复工具页面生成漂移
goal: 源文件、生成页和运行时缓存版本保持一致
scope:
allowed:
- scripts/build-tools.sh
- static/tools
forbidden:
- content/posts
facts:
- CHECK=1 当前返回 1
- 7 个页面都只在资源版本上不同
assumptions:
- 生成页继续提交到 Git
decisions:
- 资源版本改为内容哈希
open_questions:
- Docker 是否也需要执行一致性检查
acceptance:
- CHECK=1 scripts/build-tools.sh
- go test ./...
evidence:
- command: CHECK=1 scripts/build-tools.sh
exit_code: 1
summary: 7 generated pages drifted
这份交接把事实、假设和决策分开。后续模型可以挑战假设,但不需要重新猜测哪些命令真正执行过。
尤其不要只写“测试已通过”。应该记录测试范围和退出码,因为“运行了一个测试”和“运行了全部相关测试”是两件事。
一条实用的五阶段工作流
阶段一:侦察
侦察者只读仓库,不修改文件。它负责回答:
- 需求对应哪些模块;
- 当前实现的真实数据流是什么;
- 工作区是否已有未提交改动;
- 有哪些测试和构建入口;
- 哪些结论仍只是猜测。
这一步适合速度快、成本低且工具调用稳定的模型。输出是一份短报告,而不是完整解决方案。
阶段二:设计
架构者读取用户目标和侦察报告,提出最小改动方案。对于跨模块修改,它需要明确:
- 哪个文件是单一数据源;
- 哪些接口会改变;
- 兼容路径如何处理;
- 失败时是否会留下部分状态;
- 需要哪些回归测试。
这一步更依赖推理质量,可以使用更强模型,但工具权限仍保持只读。设计先经过人或主 Agent 接受,再交给实现者。
阶段三:实现
实现者获得明确的允许修改范围和验收命令。它不应该重新扩大目标,也不应该顺手重构无关模块。
如果任务可以拆成互不相交的文件集合,可以并行多个实现者;只要两个实现者可能编辑同一文件,就应改为串行,或者使用独立 Git worktree 后再显式合并。
阶段四:独立审查
审查者最好只接收:
- 原始需求;
- 最终 diff;
- 必要的仓库上下文;
- 已执行测试的证据。
不要把实现者的长篇理由全部塞给审查者。理由可能形成锚定,让审查者重复实现者的判断。真正需要独立性时,应使用新会话,必要时使用不同模型系列或 Provider。
审查者只报告具体问题:触发条件、影响、文件位置和建议验证方式。没有发现问题时也要说明残余测试缺口。
阶段五:验收与收口
主 Agent 汇总审查结果,决定哪些必须修复,再执行完整验收矩阵。最终交付应包含:
- 实际变更;
- 测试与构建结果;
- 未完成或刻意推迟的事项;
- 是否存在工作区改动、提交或外部发布。
模型之间可以讨论方案,但只有这一阶段有权宣布任务完成。
在 Pi 中如何落地
方式一:同一会话手动切换模型
最简单的做法是在阶段边界使用 /model。例如侦察完成后,把报告保存为消息或仓库外的临时交接文件,再切换到适合设计或实现的模型。
这种方式适合小任务,因为工具状态和上下文连续。但要注意:切换模型不会自动清理旧假设。进入审查阶段时,更推荐新建分支或新会话。
方式二:使用会话树建立独立分支
Pi 的会话记录具有树结构。可以在共同的用户目标处 /fork,让两个模型从同一事实起点分别提出方案,再由主会话比较结果。
用户目标
├─ 分支 A:方案一与风险
├─ 分支 B:方案二与风险
└─ 主分支:比较后选择
这比在一个上下文里连续问“还有别的方案吗”更独立,也保留了完整历史。对于代码审查,可以从原始需求建立干净分支,只把最终 diff 加入上下文。
方式三:使用 handoff 扩展
Pi 官方扩展示例包含跨 Provider 的 handoff 命令。它适合把当前任务压缩成结构化上下文,然后交给另一个模型继续。
使用这类扩展时要检查三件事:
- 交接内容是否保留真实测试证据;
- 是否意外包含密钥或大量无关日志;
- 新模型获得的工具权限是否与角色相符。
handoff 解决上下文搬运,不自动解决验收和权限问题。
方式四:多个进程或 sub-agent 扩展
真正并行时,可以启动多个 Pi 进程,或使用官方示例中的 sub-agent 扩展。每个执行单元应有独立任务、预算和目录。
对会修改代码的角色,推荐使用 Git worktree 隔离:
git worktree add -b agent/backend ../project-backend
git worktree add -b agent/frontend ../project-frontend
两个 Agent 分别工作,最后由主流程审查提交并合并。不要让多个进程在同一个工作区同时写文件,否则一个 Agent 的格式化或生成命令可能覆盖另一个 Agent 尚未提交的修改。
sub-agent 也不应该无限递归创建。编排器需要限制最大并发数、总模型调用数、截止时间和预算。
模型选择看五个维度
不要只用公开榜单给角色分配模型。编码 Agent 更应该看真实工作流指标:
工具调用可靠性
模型能否稳定生成正确参数,遇到工具错误后是否会调整,而不是重复同一调用。
上下文与检索能力
大型仓库需要找到真正相关的文件。上下文窗口很大不代表模型会利用得好,还要观察它是否能压缩和引用证据。
修改精度
实现者应该产生范围小、能通过测试的 diff,而不是为了完成局部需求重写整个模块。
独立审查能力
审查者需要主动寻找反例、边界条件和遗漏测试。使用与实现者不同的模型系列,通常比同模型自我审查更容易获得不同视角,但最终仍要以实际发现质量衡量。
延迟与成本
侦察、日志分类和格式整理不必全部使用最昂贵模型。应记录每个角色的输入输出 token、缓存命中、耗时、重试和最终采纳率。
一个简单的路由策略
路由不需要一开始就训练分类器。确定性规则更容易调试:
只读、低风险、上下文较小
→ 快速模型
跨模块设计、安全或数据一致性
→ 强推理模型
明确实现任务且有完整测试
→ 工具调用稳定的编码模型
最终代码审查
→ 与实现者不同的独立模型
编译、测试、格式化、生成校验
→ 不调用模型,直接运行程序
等积累足够运行数据后,再根据任务成功率、成本和人工返工率调整规则。不要在没有观测数据时构建复杂的“智能路由器”。
并行之前先画依赖关系
只有没有写冲突且输入已经就绪的任务才能并行:
需求澄清
↓
仓库侦察
↓
接口设计
├──────────────┐
↓ ↓
后端实现 前端实现
└──────┬───────┘
↓
集成测试
↓
独立审查
如果前端依赖尚未确定的接口,提前并行只会制造返工。先冻结契约,再并行实现,通常比“所有 Agent 立即开工”更快。
权限必须跟角色走
Pi 官方文档明确提醒:默认运行时继承启动进程的文件、命令、网络和凭据权限,不内置完整权限沙箱。Pi Package 和 Extension 也可以执行任意代码,因此安装第三方扩展前需要审查来源。
多模型工作流会放大这个风险,因为更多执行单元意味着更多凭据副本和命令入口。建议:
- 侦察者和审查者使用只读工作区;
- 实现者只写自己的 worktree;
- 不向子 Agent 传递生产密钥;
- 网络访问使用目标白名单;
- 发布、删除和外部消息始终经过人工确认;
- 第三方扩展固定版本并审查源码;
- 高风险任务在容器、虚拟机或专用沙箱运行。
第二章建立的工具风险等级、确认和审计机制,在多 Agent 场景中仍然适用,而且应该由编排器统一执行,不能交给每个子 Agent 自行决定。
如何判断多模型真的有收益
至少记录以下指标:
| 指标 | 说明 |
|---|---|
| 一次通过率 | 实现后无需返工即通过验收的比例 |
| 审查采纳率 | 审查发现中最终被确认并修复的比例 |
| 重复工作率 | 多个角色重复读取或实现相同内容的成本 |
| 人工介入次数 | 需要人补充上下文、解决冲突或纠偏的次数 |
| 总耗时 | 从任务开始到确定性验收完成 |
| 总成本 | 所有模型调用、缓存和失败重试的合计 |
如果加入第二个模型后只增加 token,没有提高一次通过率或审查发现率,就应该退回单 Agent。多模型不是默认更高级的形态,只是一种在特定任务结构下有效的工程工具。
常见失败模式
所有角色共享同一段长上下文
这样虽然省去交接,却让错误假设在所有角色之间传播。独立审查应从更干净的上下文开始。
多个实现者共用一个工作区
文件修改、依赖安装和生成命令会相互覆盖。使用不相交文件边界或独立 worktree。
交接只有自然语言结论
没有命令、退出码和文件引用时,后续模型无法区分事实与推断。使用固定交接结构。
让模型自己宣布测试通过
模型输出不是执行证据。编排器必须实际运行测试并读取退出状态。
每一步都调用最强模型
这会显著增加延迟和成本,还可能让简单任务过度设计。模型能力应与角色风险匹配。
sub-agent 可以无限派生
没有并发、深度和预算上限时,一个普通任务可能扩散成大量重复调用。编排器必须持有全局停止条件。
不使用 Pi 也能复用这套方法
Pi 的价值在于模型选择、会话树和扩展接口足够开放,适合实验自己的流程。但这套分工并不依赖某个具体产品:
- 支持模型切换的终端工具,可以手动执行阶段式工作流;
- 支持非交互模式的工具,可以由 CI 或脚本编排;
- 支持子任务的 Agent 平台,可以把角色契约写进任务描述;
- 只支持单模型的工具,也可以通过多个独立会话完成实现与审查分离。
真正需要保留的是四个边界:独立上下文、最小权限、结构化交接和确定性验收。
本章小结
多模型分工不是“给每个模型一个职位名称”,而是一套软件交付协议:
侦察者提供事实
架构者冻结契约
实现者产生最小 diff
审查者寻找反例
程序负责最终验收
主 Agent 控制权限、预算和停止条件
Pi 提供了多 Provider、模型切换、会话分支和扩展机制,但它刻意把具体工作流留给用户。这个设计让我们看到一个更普遍的结论:Agent 框架负责提供能力,可靠的分工仍然来自清晰的输入输出契约。
下一章可以继续向编排层推进:用 Go 实现一个带依赖图、并发限制、预算和检查点的任务调度器,把本章的角色协议变成可运行代码。