docs: 重写协调者与蜂群,从源码解剖改为协作模式设计分析

移除 TypeScript 代码、源码路径和 7 种任务类型枚举,
聚焦 Coordinator 先理解再分配的设计哲学、
Swarm 竞争认领的并发安全和模式选择指南。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
claude-code-best
2026-04-20 10:52:28 +08:00
parent 79baf14a8f
commit 271fd840e9

View File

@@ -1,251 +1,101 @@
---
title: "协调者与蜂群模式 - 多 Agent 高级编排"
description: "从源码角度解析 Claude Code 多 Agent 协作Coordinator Mode 的 System Prompt 设计、Worker 生命周期、Task 通信协议和 Swarm 蜂群的任务分配机制。"
title: "协调者与蜂群"
description: "两种多 Agent 协作模式Coordinator 的星型编排和 Swarm 的竞争认领。理解各自的设计权衡和适用场景。"
keywords: ["协调者模式", "蜂群模式", "Agent Swarm", "多 Agent 协作", "任务编排"]
---
{/* 本章目标:从源码角度揭示 Coordinator Mode 和 Agent Swarms 的架构设计 */}
## 核心问题
## 两种协作模式的架构差异
单个 AI Agent 的上下文窗口有限。当任务复杂到需要同时理解多个模块、执行多个并行操作时,单个 Agent 会力不从心。
多 Agent 协作的目标:让多个 AI Agent 分工合作,各自拥有独立的上下文窗口,协同完成复杂任务。
## 两种协作模式
| 维度 | Coordinator Mode | Agent Swarms |
|------|-----------------|--------------|
| **门控** | `feature('COORDINATOR_MODE')` + `CLAUDE_CODE_COORDINATOR_MODE=1` | `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1` 环境变量 |
| **拓扑** | 星型:Coordinator 居中Worker 外围 | 星型+P2P 混合:Team Lead 协调Teammate 间可直接通信 |
| **角色** | 明确分工Coordinator 编排、Worker 执行 | Team Lead 协调 + Teammate 自主认领任务 |
| **通信** | `SendMessage` 定向通信 + `<task-notification>` | Mailbox 消息系统message / broadcast |
| **适用** | 需要集中决策的复杂任务 | 并行度高、需要 Teammate 间直接协作的任务 |
| **拓扑** | 星型Coordinator 居中编排 | 星型 + P2PTeammate 间可直接通信 |
| **角色** | Coordinator 理解决策Worker 执行 | Team Lead 协调Teammate 自主认领 |
| **适用** | 需要集中决策的复杂任务 | 并行度高、任务独立的场景 |
两者不是互斥的——理论上 Coordinator Mode 可以在 Agent Teams 架构之上运行(概念层叠加,非嵌套团队),将 Coordinator 作为特殊的 Team Lead但这部分集成`workerAgent.ts` 中的 `getCoordinatorAgents`)目前为 stub 实现,尚未完整落地
两者不是互斥的——可以组合使用,但那属于高级用法
## Coordinator Mode星型编排架构
## Coordinator Mode先理解,再分配
### 激活机制
### 设计哲学
```typescript
// src/coordinator/coordinatorMode.ts:36
export function isCoordinatorMode(): boolean {
if (feature('COORDINATOR_MODE')) {
return isEnvTruthy(process.env.CLAUDE_CODE_COORDINATOR_MODE)
}
return false // 外部构建始终 false
}
```
Coordinator Mode 最核心的约束:**Coordinator 必须先理解问题,再分配任务。**
Coordinator Mode 需要双重门控:构建时 `feature('COORDINATOR_MODE')` 和运行时环境变量。`matchSessionMode()` 在会话恢复时自动同步模式状态——如果恢复的会话是 coordinator 模式,它会翻转环境变量以确保一致性。
### Coordinator 的工具集
Coordinator 被剥夺了所有"动手"工具,只保留编排能力:
| 工具 | 用途 |
|------|------|
| **Agent** | 启动新 Worker`subagent_type: "worker"` |
| **SendMessage** | 向已有 Worker 发送后续指令 |
| **TaskStop** | 中途停止走错方向的 Worker |
| **subscribe_pr_activity** | 订阅 GitHub PR 事件review comments、CI 结果) |
Coordinator **不写代码、不读文件、不执行命令**——它的核心职责是:理解需求、分配任务、综合结果,以及在无需工具时直接回答用户问题。
### Worker 的工具权限
Worker 的可用工具由 `getCoordinatorUserContext()``coordinatorMode.ts:80`)动态注入到 System Prompt
```typescript
// 简化模式下:只有 Bash + Read + Edit
const workerTools = isEnvTruthy(process.env.CLAUDE_CODE_SIMPLE)
? [BASH_TOOL_NAME, FILE_READ_TOOL_NAME, FILE_EDIT_TOOL_NAME]
: Array.from(ASYNC_AGENT_ALLOWED_TOOLS)
.filter(name => !INTERNAL_WORKER_TOOLS.has(name))
```
`INTERNAL_WORKER_TOOLS`TeamCreate、TeamDelete、SendMessage、SyntheticOutput被显式排除——Worker 不能嵌套创建团队或发送消息,防止不可控的递归。
### Scratchpad跨 Worker 的共享知识库
当 `isScratchpadGateEnabled()`(内部检查 `tengu_scratch` feature gate启用时Workers 获得一个 Scratchpad 目录Coordinator 通过其系统上下文知晓该目录的存在:
```
Scratchpad 目录:
- Workers 可自由读写,无需权限审批
- 用于持久化的跨 Worker 知识
- 结构由 Coordinator 决定(无固定格式)
```
这是一个关键的协作原语——Worker A 的研究结果可以写入 ScratchpadWorker B 直接读取,无需通过 Coordinator 中转。
### `<task-notification>` 通信协议
Worker 完成后Coordinator 收到 XML 格式的通知:
```xml
<task-notification>
<task-id>agent-a1b</task-id> ← Worker 的 agentId
<status>completed|failed|killed</status>
<summary>Agent "Investigate auth bug" completed</summary>
<result>Found null pointer in src/auth/validate.ts:42...</result>
<usage>
<total_tokens>N</total_tokens>
<tool_uses>N</tool_uses>
<duration_ms>N</duration_ms>
</usage>
</task-notification>
```
通知以 `user-role message` 形式送达Coordinator 通过 `<task-notification>` 标签区分它和用户消息。`<task-id>` 用于 `SendMessage` 的 `to` 参数,实现定向续传。
### Coordinator 的核心职责综合Synthesis
Coordinator System Prompt`coordinatorMode.ts:111-369`,约 260 行)明确要求 Coordinator **不能懒惰地委派理解**
```
反模式(禁止):
"Based on your findings, fix the auth bug"
→ 把理解的责任推给了 Worker
> "Based on your findings, fix the auth bug" — 把理解的责任推给了 Worker
正确做法:
"Fix the null pointer in src/auth/validate.ts:42.
The user field on Session (src/auth/types.ts:15) is
undefined when sessions expire but the token remains cached.
Add a null check before user.id access."
→ Coordinator 自己理解了问题,给出精确指令
```
> "Fix the null pointer in src/auth/validate.ts:42. The user field is undefined when sessions expire but the token remains cached." — Coordinator 自己理解了问题,给出精确指令
这是 Coordinator Mode 最核心的设计约束Coordinator 必须先理解,再分配
**设计考量**:如果 Coordinator 不理解问题就分配任务Worker 会因为缺乏上下文而做出错误的决策。Coordinator 的理解质量直接决定了 Worker 的执行质量
## Agent Teams (Swarm):蜂群式协作
### Coordinator 的工具限制
Swarm 模式基于任务系统 V2详见[任务管理](../tools/task-management.mdx)),核心机制是**共享任务列表 + 竞争认领 + Mailbox 消息系统**
Coordinator 被剥夺了所有"动手"工具——不写代码、不读文件、不执行命令。只保留编排能力:启动 Worker、发送指令、停止走错方向的 Worker。
### 团队初始化
**设计洞察**限制工具不是能力的削弱而是职责的清晰化。Coordinator 专注于"想"Worker 专注于"做"。如果 Coordinator 也能动手,它很容易跳过编排直接自己干,失去了多 Agent 的意义。
```
Team Lead 创建团队TeamCreateTool
设置 teamName → setLeaderTeamName()
所有 Teammate 自动获得相同的 taskListId
Teammate 启动时:
1. CLAUDE_CODE_TASK_LIST_ID 环境变量(显式覆盖)
2. Teammate 上下文的 teamName共享 Lead 的任务列表)
3. CLAUDE_CODE_TEAM_NAME 环境变量
4. Lead 设置的 teamName
5. getSessionId()(兜底)
```
### Scratchpad跨 Worker 共享知识
多级优先级确保了 Team Lead 和所有 Teammate 指向同一个任务列表,无需额外协调
Workers 共享一个 Scratchpad 目录可以自由读写。Worker A 的研究结果可以写入 ScratchpadWorker B 直接读取,无需通过 Coordinator 中转
### 架构组件
**设计考量**:不是所有知识都需要通过 Coordinator 中转。中间结果(如搜索结果、分析报告)适合 Worker 间直接共享,只有最终结论和决策才需要 Coordinator 参与。
官方 Agent Teams 架构定义了四个核心组件:
### 通信协议
| 组件 | 角色 |
Worker 完成后Coordinator 收到结构化通知,包含状态、结果摘要和 token 使用统计。Coordinator 可以向任何 Worker 发送后续指令,实现"分配 → 执行 → 反馈 → 追加"的循环。
## Agent Teams (Swarm):竞争认领
### 设计哲学
Swarm 基于一个简单的假设:**如果任务列表是共享的、可见的,多个 Agent 会自然地分工合作。**
不需要一个中央调度器——每个 Teammate 看到任务列表,自己决定认领哪个任务。这和人类团队的工作方式一致:站会上大家看到看板,自己选择下一步做什么。
### 核心机制
| 机制 | 说明 |
|------|------|
| **Team Lead** | 创建团队、分配任务、综合结果的主 Claude Code 会话 |
| **Teammate** | 独立的 Claude Code 实例,各自拥有独立的上下文窗口 |
| **Task List** | 共享的任务列表Teammate 竞争认领和完成 |
| **Mailbox** | 消息系统,支持 Teammate 间直接通信 |
| **共享任务列表** | 所有 Teammate 看到同一个任务池 |
| **竞争认领** | 第一个锁定任务的 Teammate 获得执行权 |
| **Mailbox 消息** | Teammate 间可直接通信,无需经过 Lead |
| **异常恢复** | Teammate 崩溃后,其未完成任务被自动重置 |
### Mailbox 消息系统
### 竞争认领的并发安全
官方架构中的 Mailbox 是 Teammate 间通信的核心原语,支持两种消息模式(`broadcast` 模式来自源码推断,官方文档未明确细分):
两个 Teammate 可能同时想认领同一个任务。文件锁保证原子性——第一个写入者获得锁定,第二个收到 `already_claimed` 错误后选择下一个任务。
| 模式 | 作用 | 场景 |
|------|------|------|
| **message** | 定向发送给指定 Teammate | 传递具体指令、请求协作 |
| **broadcast** | 广播给所有 Teammate | 全局通知、状态同步 |
**设计考量**:竞争是特性而非缺陷。它确保任务自然地分配给最先空闲的 Agent不需要中央调度。但需要防止"饿死"——如果某个 Agent 总是慢半拍,它可能永远抢不到任务。实践中这个问题不严重,因为 AI Agent 的执行速度差异不大。
Mailbox 的关键特性:
- **自动投递**:消息自动送达目标 Teammate 的对话上下文
- **空闲通知**TeammateIdleTeammate 完成当前任务进入空闲时,自动通过 Mailbox 通知 Team Lead
- **直接通信**:与 Coordinator Mode 不同Teammate 之间可以直接通信,无需经过 Lead 中转
### Teammate 的生命周期
### Hook 事件
Teammate 异常退出时其未完成任务被自动重置为无主状态。Team Lead 通过共享任务列表或空闲通知感知到变化,可以重新分配或创建新 Teammate。
Agent Teams 提供三个关键 Hook 事件,用于在团队生命周期中注入自定义逻辑:
**设计哲学**:单个 Agent 的崩溃不应该阻塞整个团队。任务系统保证工作不会因为个别 Agent 的失败而丢失。
| Hook | 触发时机 | 典型用途 |
|------|---------|---------|
| **TaskCreated** | 新任务添加到任务列表时 | 自动分配、优先级排序 |
| **TaskCompleted** | 任务标记为完成时 | 结果通知、依赖解锁 |
| **TeammateIdle** | Teammate 完成所有任务进入空闲时 | Lead 重新分配、动态扩缩容 |
### 当前限制
### 限制
- 不支持嵌套团队Teammate 不能创建子团队)
- 每会话一个团队
- Lead 固定不可更换
当前 Agent Teams 实现的限制:
- **不支持嵌套团队**Teammate 不能再创建子团队
- **每 session 一个团队**:一个会话只能属于一个团队
- **Lead 固定**Team Lead 创建后不可更换
- **不支持 in-process Teammate 的会话恢复**:进程重启后 in-process 类型 Teammate 的状态丢失
### 持久化存储
团队状态通过文件系统持久化,确保进程重启后可恢复:
```
~/.claude/teams/{team-name}/config.json ← 团队配置
~/.claude/tasks/{team-name}/ ← 共享任务列表(文件锁保护)
```
### 任务认领与竞争
`claimTask()` 是 Agent Teams 的核心并发原语:
```
Teammate A 调用 TaskList → 发现 task #3 是 pending
Teammate B 同时发现 task #3 是 pending
两者同时尝试 TaskUpdate(task #3, {status: "in_progress"})
文件锁保证原子性:
- 第一个写入者获得 owner 锁定
- 第二个写入者收到 already_claimed 错误
获得任务的 teammate 执行工作
完成后 TaskUpdate(task #3, {status: "completed"})
→ 依赖此任务的其他任务自动解锁
→ tool_result 提示 "Call TaskList to find your next task"
```
### Teammate 的生命周期管理
```
Teammate 异常退出
unassignTeammateTasks()
→ 扫描任务列表,找到 owner === teammateName 的未完成任务
→ 重置为 pending + owner=undefined
Team Lead 感知途径:
1. 任务状态变化pending 重置)—— 通过共享任务列表
2. Mailbox 空闲通知TeammateIdle hook—— Teammate 停止时自动通知 Lead
Team Lead 重新分配任务或创建新 Teammate
```
## 任务类型全景
支撑多 Agent 协作的是 7 种任务类型(`src/tasks/types.ts`
| 任务类型 | 运行位置 | 状态管理 | 适用场景 |
|----------|---------|---------|---------|
| **LocalAgentTask** | 本地子进程 | `LocalAgentTaskState` | 标准子 Agent 任务 |
| **LocalShellTask** | 本地 shell | `LocalShellTaskState` | 后台 shell 命令 |
| **InProcessTeammateTask** | 同进程内 | `InProcessTeammateTaskState` | 轻量级进程内队友 |
| **RemoteAgentTask** | 远程服务器 | `RemoteAgentTaskState` | 分布式 AgentCCR |
| **DreamTask** | 后台静默 | `DreamTaskState` | 后台自主整理记忆 |
| **LocalWorkflowTask** | 本地 | `LocalWorkflowTaskState` | 工作流编排 |
| **MonitorMcpTask** | 本地 | `MonitorMcpTaskState` | MCP 监控任务 |
`InProcessTeammateTask` 与 `LocalAgentTask` 的关键差异:前者共享进程的内存空间和基础设施状态(如 MCP 连接池),但有独立的对话上下文和工具权限;后者是完全隔离的子进程,启动开销更大但更安全。
## Coordinator vs Agent Teams 的选择
## 模式选择指南
| 场景 | 推荐模式 | 原因 |
|------|---------|------|
| "重构认证系统,需要多模块协调" | Coordinator | 需要集中决策Worker 间有依赖 |
| "修复 10 个独立的 lint 警告" | Agent Teams | 任务独立Teammate 可完全并行 |
| "修复 10 个独立的 lint 警告" | Swarm | 任务独立Teammate 可完全并行 |
| "研究方案 A 和方案 B然后选一个实现" | Coordinator | 先并行研究,再集中决策 |
| "在大仓库中搜索所有 TODO 并分类" | Agent Teams | 无依赖,各自领任务即可 |
| "在大仓库中搜索所有 TODO 并分类" | Swarm | 无依赖,各自领任务即可 |
## 接下来
- **子 Agent** — 理解单个子 Agent 的创建和生命周期
- **Worktree 隔离** — 理解多 Agent 的文件系统隔离
- **任务管理** — 理解支撑协作的任务系统