Hi,大家好,欢迎来到维元码簿。
本文属于 《Claude Code 源码 Deep Dive》 系列,专注于多 Agent 协作中的 团队协作与编排 板块。如果你想了解整个系列,可以先看系列开篇 | Claude Code 源码架构概览:51万行代码的模块地图。
本文讲一件事:从单个子 Agent 到多 Agent 团队,Claude Code 怎么编排协作------什么是 Swarm、什么是 Coordinator、In-Process 和 Tmux Teammate 有什么区别。
读完全文,你将能回答这几个问题:
- Swarm 模式和普通子 Agent 有什么本质区别? Subagent 是"派一个人做事",Swarm 是"维护一个团队"------前者是功能,后者是运行时。
- Coordinator(指挥官)模式为什么比"民主讨论"更工程可靠? 全局视角决定并发策略、单一收敛点防止死锁、清晰的权责边界。
- In-Process teammate 和 tmux teammate 有什么区别? 同进程用 AsyncLocalStorage 零复制隔离,tmux 用独立进程 + 消息邮箱通信。
本篇覆盖的源码范围
| 模块 | 核心文件 | 核心代码行 | 文件总行 | 职责 |
|---|---|---|---|---|
| Swarm 编排引擎 | src/tools/shared/spawnMultiAgent.ts |
L385-930(tmux + in-process spawn 分支) | 1033 行 | 多 Agent 生成编排、Tmux/In-Process 分流 |
| Team 管理工具 | src/tools/TeamCreateTool/TeamCreateTool.ts + src/tools/TeamDeleteTool/ |
TeamCreate L37-130(schema + call) | ~300 行 | 创建/删除团队、Team File 管理 |
| In-Process Backend | src/utils/swarm/backends/InProcessBackend.ts |
L38-340 | 340 行 | In-Process 后端抽象、spawn/可用性检查 |
| In-Process Runner | src/utils/swarm/inProcessRunner.ts |
散布 | --- | 同进程队友的 query() 运行器 |
| Teammate 初始化 | src/utils/swarm/teammateInit.ts |
L28-112 | 112 行 | 队友 Stop Hook 注册、空闲通知 |
| Team 文件管理 | src/utils/swarm/teamHelpers.ts |
散布 | --- | Team File 读写、成员增删、活跃状态 |
| Coordinator 模式 | src/coordinator/ |
散布 | --- | Coordinator System Prompt、专用工具集 |
前情提要:从单个 Agent 到团队
在前三篇姊妹篇中,我们知道了怎么创建一个子 Agent、怎么隔离它、怎么跟它通信。但面对复杂项目------比如同时需要"研究代码结构"、"实现重构"、"验证结果"------单个子 Agent 不够用。
这就是 Swarm 要解决的问题。Swarm 让多个 Agent 以"团队"形式协作:一个 Leader(通常是你的主 Agent)分配任务,多个 Teammate 各司其职。Coordinator 模式进一步把这种"分配任务"的能力从用户意图提升为系统架构级别。

Swarm 团队:从"派个人做事"到"维护一个团队"
Swarm 不是"多几个子 Agent"------它是"一个持续的协作运行时"。 这是理解 Swarm 和普通 AgentTool 调用的关键区别。
团队的生命周期
一个 Swarm 团队的完整生命周期:
- 创建团队 :
TeamCreate(team_name: "my-team", description: "重构用户模块") - 注册 Leader:Leader 自动注册,拥有完整权限
- 加入队友 :
AgentTool(team_name, name: "researcher", prompt: "分析 UserService")→spawnTeammate() - 队友执行:Teammate 在自己的上下文中运行,通过 mailbox 与 Leader 通信
- 空闲通知 :Teammate 完成工作后,Stop Hook 触发 →
setMemberActive(false)→ 发送空闲通知给 Leader - Leader 调度:Leader 根据空闲状态决定"继续这个队友"还是"新建一个"
- 团队解散 :
TeamDelete(team_name)→ 清理文件、停止队友、移除注册
Team File:团队的持久化注册表
Team File 是一个 JSON 文件,存储团队的完整状态:
typescript
// Team File 结构(简化)
{
teamName: "my-team",
createdAt: 1713123456789,
members: [
{
agentId: "leader@my-team",
name: "team-lead",
agentType: "general-purpose",
color: "#2563eb",
isActive: true,
planModeRequired: false,
backendType: "in-process"
},
{
agentId: "researcher@my-team",
name: "researcher",
agentType: "Explore",
color: "#22c55e",
isActive: false, // 空闲中!
planModeRequired: false,
backendType: "in-process"
}
]
}
Team File 的作用不是"配置文件"------它是团队的持久化注册表 。如果 Leader 崩溃后重启,可以从 Team File 恢复团队成员状态。isActive 字段让 Leader 一眼看到哪些队友在忙、哪些在空闲。
inbox poller:队友怎么知道自己被点名了
Tmux Teammate 在独立进程中运行,它怎么知道 Leader 给它发了任务?答案是 inbox poller------一个轮询 mailbox 文件的机制:
- Leader 通过 SendMessage 写入 mailbox 文件
- Teammate 的 inbox poller 定时检查 mailbox
- 检测到新消息 → 作为 user message 注入到 Teammate 的初始 messages[]
- Teammate 开始执行任务
In-Process Teammate 不需要 mailbox------因为在同进程中,任务描述直接通过 startInProcessTeammate() 传入。
In-Process vs Tmux:两种队友形态
这是 Swarm 系统中最核心的工程选择------同进程还是独立进程?

In-Process Teammate:AsyncLocalStorage 的零复制隔离
In-Process Teammate 和主 Agent 在同一个 Node.js 进程中运行。隔离完全由 AsyncLocalStorage 保证。
typescript
// src/utils/swarm/backends/InProcessBackend.ts L38-71
export class InProcessBackend implements TeammateExecutor {
readonly type = 'in-process' as const
async spawn(config: TeammateSpawnConfig): Promise<TeammateSpawnResult> {
// 1. 创建 TeammateContext
// 2. 创建独立 AbortController(不链接到父)
// 3. 在 AppState.tasks 中注册
// 4. 通过 startInProcessTeammate() 启动 Agent 循环
// 5. 返回 spawn 结果(agentId, taskId, abortController)
}
}
优势:
- 零序列化开销------不经过文件 I/O 传递消息
- 即时启动------不需要启动新进程
- 共享终端 UI------可以在 split pane 中显示队友状态
限制:
- 不能嵌套------In-Process Teammate 不能再 spawning 子 Teammate
- 不能后台------生命周期绑定到 Leader 的进程
- 共享进程资源------内存、CPU 都在同一个 V8 实例中
Tmux Teammate:完全独立的进程
Tmux Teammate 是完全独立的 Claude Code 进程,通过 tmux split-window 创建分屏:
typescript
// src/tools/shared/spawnMultiAgent.ts L399-444(简化)
const spawnCommand = `cd ${workingDir} && env ${envStr} ${binaryPath} \
--agent-id ${teammateId} \
--agent-name ${sanitizedName} \
--team-name ${teamName} \
--agent-color ${teammateColor} \
--parent-session-id ${getSessionId()} \
${inheritedFlags}`
await sendCommandToPane(paneId, spawnCommand)
优势:
- 完全隔离------独立进程、独立内存、独立 V8
- 可独立重启------崩溃不影响 Leader
- 完整 Claude Code CLI------可以有自己的工具、自己的 UI
代价:
- 进程启动开销------秒级(vs 毫秒级)
- 消息序列化------mailbox JSON 文件的读写
- 不共享 Prompt Cache------不同进程有独立的 API 连接
Coordinator 模式:指挥官优于民主
这是多 Agent 系统设计中最深刻的一个选择------不是技术问题,是架构哲学问题。
两种范式:民主 vs 指挥官
设计多 Agent 系统,本质上有两条路:
范式 A:Peer-to-Peer(民主讨论)
Agent A ←→ Agent B
↕ ↕
Agent C ←→ Agent D
所有 Agent 平等,通过共享状态或直接通信协作。优点:灵活,无单点。缺点:任何 Agent 都可以影响任何其他 Agent,并发状态几乎无法调试。
范式 B:Coordinator(指挥官模式)
Coordinator(指挥官)
↙ ↓ ↘
Worker A Worker B Worker C
Coordinator 是唯一对用户输出的通道。Worker 只和 Coordinator 通信------Worker 之间不直接对话。
Claude Code 选了范式 B。为什么?Coordinator 的 System Prompt 中有一句关键的话:
"Coordinator is responsible to the user. Worker results are INTERNAL SIGNALS --- not conversation partners."
Worker 的结果是"内部信号",不是"对话伙伴"------这避免了多 Agent 系统最经典的陷阱:两个 Agent 开始互相讨论、争论、无限循环。

Coordinator 的三个核心优势
① 全局并发决策。 只有 Coordinator 有全局视角,能判断"这两个 Worker 操作不同文件集合,可以并行"或"这两个 Worker 操作同一个模块,必须串行"。
"Parallelism is your superpower. Workers are async. Launch independent workers concurrently whenever possible --- don't serialize work that can run simultaneously."
② 单一收敛点。 Worker 的输出只汇到 Coordinator,Coordinator 再统一向用户输出。不会出现"Agent A 告诉用户方案 X,Agent B 告诉用户方案 Y"的矛盾。
③ 清晰权责边界。 Worker 有明确的 role 定义------Researcher 只做研究、Implementer 只做实现、Verifier 只做验证。Worker 不做决策,Coordinator 做决策。
Coordinator 的工具集
Coordinator 的工具有限但精确:
- AgentTool:创建新 Worker
- SendMessage:向现有 Worker 发送后续指令
- TaskStop:停止运行中的 Worker
没有额外的"协调工具"------三个工具就够了。因为 Coordinator 本身就是一个 Agent,它能用 Write 写文件、能用 Bash 跑命令。它不需要特殊的协调能力------它需要的是全局视角和决策能力。
Worktree 隔离与远程 Agent
Worktree:文件系统级隔离
isolation: "worktree" 让子 Agent 在临时 Git worktree 中运行------一个独立的文件系统视图:
typescript
// src/tools/AgentTool/AgentTool.tsx L527-568(简化)
const cleanupWorktreeIfNeeded = async () => {
if (!worktreeInfo) return {}
const changed = await hasWorktreeChanges(worktreePath, headCommit)
if (!changed) {
await removeAgentWorktree(worktreePath, worktreeBranch, gitRoot)
return {} // 无更改,自动清理
}
// 有更改,保留 worktree
return { worktreePath, worktreeBranch }
}
Worktree 的清理策略很聪明:没有产生更改就自动删除,产生了更改就保留。 这比"总是清理"或"总是保留"更合理------兼顾了资源效率和用户的数据安全。
远程 Agent:Bridge 协议
isolation: "remote" 让 Agent 在远程 CCR 环境中运行(目前是 ant 用户的功能)。这是一个 Feature Gate 控制的能力,需要 Bridge 协议支撑会话创建、消息传递和文件同步。
本章小结
- Swarm 是持续的协作运行时------不是"多建几个 Agent",而是维护一个团队的存在状态。Team File 是持久化注册表
- In-Process 和 Tmux 是两种互补的队友形态------前者零开销但受限,后者完全隔离但有成本。选哪个取决于任务需求
- Coordinator 模式的核心是"收敛"而非"指挥"------全局视角决定并发、单一出口防止混乱、清晰边界保证可控
- Worktree 隔离的清理策略体现了工程中的"刚好够用"哲学------无更改自动清理,有更改保留结果
如果这篇文章对你有帮助,欢迎点赞收藏 支持一下。如果你对 Claude Code 源码感兴趣,欢迎关注本系列 后续更新。有任何想法或疑问,欢迎评论区留言讨论 👋