# 多代理架构：分叉-汇聚模式的协作艺术


<!-- more -->


有一个反直觉的现象：同一个模型，拆成多个独立实例让它协作，效果往往比单个实例更好。

不是算力增加了（三个实例的总 token 消耗比一个实例多），不是能力提升了（每个实例都是同样的模型）。提升来自**角色分离**——当每个 Agent 只关注问题的一个方面时，它做得比"全能 Agent"更专注、更深刻。

Claude Code 的多代理架构就是建立在这个观察上的。

## 为什么一个 Agent 不够

单个 Agent 处理复杂任务时有一个结构性问题：**角色冲突。**

想象你让 Claude Code 做一件事："分析这个项目，然后提出重构方案。" 这个任务包含两个阶段：
1. **探索**——读文件、理解架构、发现问题（需要广泛但浅层的扫描）
2. **规划**——基于探索结果设计重构方案（需要深度但聚焦的思考）

如果同一个 Agent 做这两件事，它在探索阶段收集的详细信息会占据上下文，到了规划阶段可能没空间做深度推理。更糟的是，探索时的"发现心态"和规划时的"决策心态"在认知上是不同的——同一个上下文里同时保持两种心态，模型容易混淆。

人类怎么处理这个问题？我们开会。先让调研组去收集信息，汇总后让决策组设计方案。Claude Code 的多代理架构做的是同样的事。

## 三种内置代理角色

Claude Code 预置了三种子代理角色，每种都有明确的职责边界：

**Explore（探索者）**——只读权限，快速扫描。它的任务是"尽可能多地了解项目"：读文件、搜代码、列目录、看依赖。它不写代码、不改配置、不做决策。它只收集信息并生成报告。

Explore 的核心设计决策是**广度优先**。它不深入分析每个文件，而是快速扫描尽可能多的文件，建立项目的"地图"。输出的是一份结构化摘要：项目结构、技术栈、关键文件、潜在问题。

**Plan（规划者）**——基于 Explore 的报告做深度分析。它有只读权限，但关注点不同：Explore 回答"项目里有什么"，Plan 回答"该怎么改"。Plan 接收 Explore 的发现，结合用户需求，生成结构化的行动计划。

Plan 的核心设计决策是**深度优先**。它不关心项目的全貌，只关心与当前任务相关的部分。输出的是一份可执行计划：步骤、优先级、风险评估、预估工作量。

**General（通用）**——全权限，执行者。它接收 Plan 的方案，具体实施。读文件、写代码、跑测试、修 bug。它是三种角色中能力最全面的，但也是约束最明确的——它不应该做探索或规划，它应该执行既定方案。

General 的核心设计决策是**执行优先**。它不做战略决策，它把战略决策转化为具体操作。

## 分叉-汇聚模式

三种角色的协作模式可以概括为**分叉-汇聚（Fork-Join）**：

```
主 Agent
  │
  ├─► Explore (分叉) ──┐
  │                    ├─► Plan (分叉) ──┐
  │                    │                 ├─► General (执行)
  └────────────────────┴─────────────────┴─► 结果汇聚回主 Agent
```

主 Agent 接收用户请求，判断需要哪些子代理，按顺序 fork 出来。每个子代理在独立的上下文中运行——它有自己的对话历史、自己的工具调用、自己的 Think-Act-Observe 循环。子代理完成后，结果被汇聚回主 Agent，主 Agent 整合后回复用户。

关键设计是**上下文隔离**。Explore 不知道 Plan 在做什么，Plan 只看到 Explore 的报告（不是原始数据），General 只看到 Plan 的方案（不是探索过程）。每个子代理的上下文只包含它需要的信息。

上下文隔离的好处是**防止污染**。如果所有角色共享同一个上下文，Explore 的大量扫描数据会挤占 Plan 的推理空间。隔离后，每个子代理有自己的干净窗口，专注做一件事。

## 子代理的启动与终止

子代理不是永久运行的。它们是**按需创建、按任务销毁**的临时实例。

主 Agent 决定启动子代理时，会创建一个独立的 Agent 实例，注入特定的 system prompt（定义角色）、工具权限（定义能力边界）、任务描述（定义目标）。子代理运行自己的 Think-Act-Observe 循环，直到完成任务。完成后，子代理的输出被打包成结构化报告返回给主 Agent，子代理实例被销毁。

这意味着子代理没有持久状态。它不会"记住"上次的探索结果，不会"学习"从之前的规划中犯的错误。每次都是从零开始。

这不是缺陷，是设计选择。**无状态的子代理更容易推理**——你知道它的行为只取决于输入（system prompt + 任务描述），不取决于隐藏状态。

## 自定义代理

除了三种内置角色，Claude Code 还支持用户自定义代理。用户在 `.claude/agents/` 目录下创建 Markdown 文件，定义代理的角色、能力、行为准则。

一个自定义代理文件可能长这样：

```markdown
# 安全审计代理

## 角色
专门负责代码安全审计的 Agent。

## 能力
- 只读权限
- 可以读取文件和运行安全扫描工具

## 行为准则
- 重点关注注入漏洞、XSS、CSRF
- 发现漏洞时给出 CVSS 评分
- 按照 OWASP Top 10 分类
```

自定义代理的 existence 揭示了一个更深层的设计理念：**Agent 的角色应该被声明式地定义，而不是硬编码在程序里。** 和 Skill 一样，代理角色是一种"可配置的专业知识"——只不过 Skill 配置的是"怎么做"，代理配置的是"谁来做"。

## 多代理的代价

多代理不是免费的。它有明确的代价：

**Token 消耗倍增。** 每个子代理都有独立的 system prompt、独立的对话历史。三个子代理的 token 消耗大约是单代理的 2-3 倍（不是 3 倍，因为子代理的对话通常较短）。

**延迟增加。** 子代理是串行调用的（Explore → Plan → General），每个都要等前一个完成。总延迟是各子代理延迟之和。

**信息损失。** 每个传递环节都有信息压缩。Explore 的原始数据被压缩成报告给 Plan，Plan 的详细分析被压缩成方案给 General。最终执行者看到的可能只是原始信息的"摘要的摘要"。

多代理只在任务复杂度超过单代理处理能力时才有价值。简单的任务（"帮我改这个函数"）不需要 fork 子代理——直接让 General 干就完了。

## 多代理的哲学

Claude Code 的多代理架构背后有一条设计哲学：

**复杂任务不应该由一个全能 Agent 处理，而应该被分解为角色明确的子任务，由专注的子代理协作完成。**

这和人类组织的分工逻辑完全一致。你不会让同一个人既做市场调研又做产品设计又写代码——你让不同的人做不同的事，然后通过协调机制（会议、文档、流程）把成果整合。

多代理架构是**组织理论的 Agent 版本**。它不依赖模型变聪明，它依赖分工变清晰。

## 延伸阅读：BYF 的前台子代理与实时查看器

[BYF](https://github.com/ByronFinn/byf) 在 Claude Code 的多代理架构上做了两个方向上的演进。

**1. 前台子代理（Foreground Sub-agent）与实时查看器。** BYF 的子代理有两种运行形态：后台（通过 `/tasks` 管理）和前台（阻塞父代理，用户通过 `/agent` 打开全屏实时查看器）。前台子代理的事件通过 `routeSubagentEvent` 路由到父组件的 `ToolCallComponent`，用户可以看到子代理的每一步——生命周期状态变化、工具活动、审批等待、错误和最终结果。这不是模型的私有思考链，而是**可观察的活动记录**。

我自己的一个体会是：子代理的"可观察性"远比"快"重要。当一个子代理跑起来但屏幕上一片空白时，用户不知道它是卡住了还是在干活。BYF 的实时查看器解决的是这个问题——它让子代理的工作过程变得透明。

**2. TaskEntry 判别联合。** 这是 BYF 的一个设计债清理案例。后台任务管理器用一个 `ManagedProcess` 结构同时管理两种任务：真实 OS 进程（有 pid、stdin/stdout/stderr 流）和子代理（纯 JS Promise）。为了让 Promise 任务适配，代码中出现了一处 `as unknown as KaosProcess` 的类型强制转换——BYF 源码中唯一的 `as unknown`。

BYF 通过引入 `TaskEntry` 判别联合（`ProcessTaskEntry | PromiseTaskEntry`）彻底消除了这个逃生口。现在编译器强制你在访问 `entry.proc` 前用 `kind` 守卫做类型细化。这个重构不是在"改功能"，而是在"改类型"——但它让后续所有使用后台任务的代码都更加安全。

这和 Claude Code 的"三种子代理角色"是同一个思路的反面：**Claude Code 用角色区分不同代理的行为，BYF 用类型区分不同任务的形态。** 两种方法都指向同一个目标——让多代理系统更健壮、更可预测。

## 下一篇

多代理让 Agent 内部协作更高效。但 Agent 还需要和外部工具协作——数据库、API、第三方服务。下一篇文章我们要拆解 **MCP 协议（Model Context Protocol）**：它为什么被称为"AI 工具互联的 USB-C"？JSON-RPC over stdio 的设计取舍是什么？为什么 AI 工具需要一个标准协议？

---

> 本系列基于 [Claude Code 官方源码](https://github.com/anthropics/claude-code)项目进行架构分析，聚焦设计思想而非代码实现。

