职责概述

Claude Code 的 Agent 协作系统(代号 Swarm)允许多个 AI 实例协同工作。一个 Leader Agent 可以生成多个 Teammate Agent,它们在独立的终端面板或进程内运行,通过文件邮箱系统交换消息。本页深入分析 Agent 层级关系、消息传递协议、任务委派模式和错误处理机制。

架构设计

Agent 协作系统采用三层架构,从后端到业务逻辑清晰分层:

Leader 层(主进程)
TeamCreateTool — 创建团队
AgentTool — 生成子 Agent
SendMessageTool — 消息发送
调度层
swarm/backends/ — 后端注册表
registry.ts — tmux / iTerm2 / in-process
TeammateExecutor — 统一接口
执行层
inProcessRunner.ts — 进程内运行器
PaneBackendExecutor — 面板执行器
runAgent() — 核心循环
通信层
teammateMailbox — 文件邮箱
permissionSync — 权限同步
teamHelpers — 团队文件
上下文隔离
AsyncLocalStorage — 队友上下文
AgentContext — Agent 上下文
TeammateContext — 团队上下文

三种执行后端

TmuxBackend
tmux 面板管理,每个 Teammate 独立终端
tmux / iTerm2
ITermBackend
iTerm2 原生分屏,通过 it2 CLI 控制
macOS iTerm2
InProcessBackend
同进程内运行,AsyncLocalStorage 隔离
跨平台

后端自动检测优先级

在 tmux 内?
→ TmuxBackend
→ 继续
在 iTerm2 内?
it2 可用 → ITermBackend
无 it2 → 回退 tmux
tmux 可用?
→ Tmux 外部会话
→ InProcess 回退

核心数据流

Agent 生成与生命周期

Step 1: 团队创建
Leader 调用 TeamCreateTool,创建团队文件(记录 leadAgentId、members、teamAllowedPaths)。团队名与 Leader session 关联。
Step 2: Teammate 生成
调用 getTeammateExecutor(preferInProcess) 获取后端。InProcess 模式调用 InProcessBackend.spawn();Pane 模式创建终端面板并启动新 Claude CLI 进程。
Step 3: 上下文初始化
生成 TeammateIdentity(name, teamName, color, parentSessionId)。注册 Stop Hook 用于空闲通知。应用团队级权限规则(teamAllowedPaths)。
Step 4: 执行循环
调用 runInProcessTeammate(),内部使用 runAgent() 运行。支持自动 compact(超过阈值时压缩历史)。每次迭代创建独立的 AbortController(Escape 仅停止当前轮)。
Step 5: 空闲通知
Agent 完成当前任务后标记 isIdle=true,通过文件邮箱发送 idleNotification 给 Leader。包含 idleReason(available/interrupted/failed)和最近 DM 摘要。
Step 6: 等待新指令
waitForNextPromptOrShutdown() 每 500ms 轮询邮箱。优先处理 shutdown 请求(最高优先级),然后处理 Leader 消息(优先于队友消息),最后检查任务列表。
Step 7: 循环或终止
收到新消息 → 回到 Step 4 继续执行。收到 shutdown 请求 → 传递给模型决策(approve/reject)。收到 abort → 清理退出。

消息传递流程

Leader → Teammate
writeToMailbox(teammateName, message) 写入文件。消息包含 from、text、timestamp、color、summary 字段。包装为 <teammate-message> XML 注入 Teammate 对话。
Teammate → Leader
通过 SendMessageTool 调用 writeToMailbox(TEAM_LEAD_NAME, message)。Leader 端 TeammateIdle Hook 或轮询检查新消息。
Peer-to-Peer
Teammate 之间通过相同邮箱系统通信,但消息优先级低于 Leader 消息(防止饥饿)。

权限请求流程

Teammate 需要权限
canUseTool 返回 'ask'。InProcess 模式有两种路径:UI 队列(ToolUseConfirm)或邮箱回退。
路径 A: UI 对话框(优先)
通过 getLeaderToolUseConfirmQueue() 将权限请求推入 Leader 的 UI 队列,显示 worker badge。Leader 在 UI 中审批,结果回传 Teammate。
路径 B: 邮箱回退
发送 PermissionRequest 到 Leader 邮箱,注册回调等待响应。Leader 处理后通过 Teammate 邮箱回复。Teammate 每 500ms 轮询。

关键类型与接口

TeammateIdentity

// swarm/backends/types.ts:191-200
type TeammateIdentity = {
  name: string           // 如 "researcher", "tester"
  teamName: string       // 团队名
  color?: AgentColorName // UI 颜色标识
  planModeRequired?: boolean
}

TeammateSpawnConfig

// swarm/backends/types.ts:205-225
type TeammateSpawnConfig = TeammateIdentity & {
  prompt: string
  cwd: string
  model?: string
  systemPrompt?: string
  systemPromptMode?: 'default' | 'replace' | 'append'
  worktreePath?: string
  parentSessionId: string
  permissions?: string[]
  allowPermissionPrompts?: boolean
}

TeammateExecutor 统一接口

// swarm/backends/types.ts:279-300
type TeammateExecutor = {
  readonly type: BackendType
  isAvailable(): Promise<boolean>
  spawn(config: TeammateSpawnConfig): Promise<TeammateSpawnResult>
  sendMessage(agentId: string, message: TeammateMessage): Promise<void>
  terminate(agentId: string, reason?: string): Promise<boolean>
  kill(agentId: string): Promise<boolean>
  isActive(agentId: string): Promise<boolean>
}

InProcessRunnerConfig

// swarm/inProcessRunner.ts:471-502
type InProcessRunnerConfig = {
  identity: TeammateIdentity
  taskId: string
  prompt: string
  agentDefinition?: CustomAgentDefinition
  teammateContext: TeammateContext
  toolUseContext: ToolUseContext
  abortController: AbortController
  model?: string
  systemPrompt?: string
  systemPromptMode?: 'default' | 'replace' | 'append'
  allowedTools?: string[]
  allowPermissionPrompts?: boolean
  description?: string
  invokingRequestId?: string
}

CLI 标志继承

// swarm/spawnUtils.ts:38-89 — 传递给子进程的标志
function buildInheritedCliFlags(options?): string {
  // --dangerously-skip-permissions (如 Leader 使用)
  // --model (模型覆盖)
  // --settings (设置文件路径)
  // --plugin-dir (插件目录)
  // --teammate-mode (队友模式)
  // --chrome / --no-chrome
}

环境变量转发

// swarm/spawnUtils.ts:96-128 — 转发给 tmux 队友的环境变量
const TEAMMATE_ENV_VARS = [
  'CLAUDE_CODE_USE_BEDROCK',    // API 提供商
  'CLAUDE_CODE_USE_VERTEX',
  'CLAUDE_CODE_USE_FOUNDRY',
  'ANTHROPIC_BASE_URL',         // 自定义端点
  'CLAUDE_CONFIG_DIR',          // 配置目录
  'CLAUDE_CODE_REMOTE',         // CCR 标记
  'HTTPS_PROXY',                // 代理变量
  'SSL_CERT_FILE',
  // ...更多
]

设计模式与亮点

1. 双模式执行架构

系统同时支持 Pane 模式(tmux/iTerm2,每个 Teammate 独立进程)和 InProcess 模式(同进程 AsyncLocalStorage 隔离)。Pane 模式进程完全隔离但需要 tmux;InProcess 模式零依赖但需要上下文隔离。

2. 文件邮箱通信

所有 Agent 间通信通过文件邮箱系统(teammateMailbox)。这避免了进程间通信的复杂性,同时保证消息持久化。邮箱格式基于 JSON Lines,每行一条消息,标记 read/unread 状态。

3. 嵌套 AsyncLocalStorage

InProcess Teammate 使用三层上下文隔离:

// inProcessRunner.ts:1160-1161
await runWithTeammateContext(teammateContext, () =>
  runWithAgentContext(agentContext, () =>
    runAgent({ ... })
  )
)

TeammateContext 提供团队级隔离,AgentContext 提供分析归因,两者通过 Node.js AsyncLocalStorage 传播,无需显式参数传递。

4. 消息优先级队列

邮箱轮询按严格优先级处理消息:

  1. 最高 — Shutdown 请求(防止饥饿)
  2. — Leader 消息(代表用户意图)
  3. 普通 — Peer 消息(FIFO 顺序)
  4. — 任务列表自动领取

5. 分层 AbortController

InProcess Teammate 使用两级 AbortController:

  • abortController — 生命周期级,杀死整个 Teammate
  • currentWorkAbortController — 工作级,Escape 仅停止当前轮

这允许用户中断当前操作而保留 Teammate 存活,等待新指令。

6. 自动 Compaction

长时间运行的 Teammate 会积累大量历史消息。runInProcessTeammate 每轮检查 token 计数,超过自动 compact 阈值时压缩对话历史,并重置内容替换状态以保持一致性。

开发者实践指南

创建自定义 Agent 只需定义 agentDefinition,系统自动处理生成、通信和权限。

如何创建自定义 Agent

// 通过 .claude/agents/ 目录定义自定义 Agent
// 文件名即 Agent 类型名,如 researcher.md
type CustomAgentDefinition = {
  agentType: string        // 如 "researcher"
  whenToUse: string        // 何时使用的描述
  getSystemPrompt: () => string
  tools?: string[]         // 允许的工具列表('*' = 全部)
  model?: string           // 模型覆盖
  memory?: string          // 记忆范围
  source: 'projectSettings' | 'userSettings'
  permissionMode?: 'default' | 'bypassPermissions'
}

Agent 工具集控制

InProcess Teammate 自动注入团队协作必需工具,即使自定义了工具列表:

// inProcessRunner.ts:981-994 — 强制注入的团队工具
tools: agentDefinition?.tools
  ? [...new Set([
      ...agentDefinition.tools,
      SEND_MESSAGE_TOOL_NAME,     // 消息发送
      TEAM_CREATE_TOOL_NAME,      // 团队创建
      TEAM_DELETE_TOOL_NAME,      // 团队删除
      TASK_CREATE_TOOL_NAME,      // 任务创建
      TASK_GET_TOOL_NAME,         // 任务获取
      TASK_LIST_TOOL_NAME,        // 任务列表
      TASK_UPDATE_TOOL_NAME,      // 任务更新
    ])]
  : ['*']  // 默认全部工具

调试 Agent 协作

架构师决策指南

设计权衡

InProcess vs Pane:InProcess 模式共享进程资源,内存效率高但一个 Agent 崩溃可能影响整个进程。Pane 模式进程完全隔离,但需要 tmux 依赖和更多系统资源。

文件邮箱 vs 内存队列:文件邮箱天然持久化(进程重启不丢消息),但增加了磁盘 I/O。对于 tmux 队友,文件是唯一可行的 IPC 方式;对于 InProcess 队友,理论上可以用内存队列,但保持一致简化了实现。

轮询 vs 事件驱动:500ms 轮询邮箱增加延迟,但避免了文件监听(fs.watch 在某些 OS 上不可靠)和信号机制(进程间信号有限)的复杂性。

扩展性考量

  • Team 大小无硬性上限,受系统资源限制(tmux 面板 / 进程内存)
  • 每个 Teammate 的对话历史独立管理,自动 compact 防止内存溢出
  • 邮箱轮询间隔 500ms 是延迟与 CPU 使用的平衡点
  • 权限桥接通过 Leader UI 队列实现,避免 Leader 进程繁忙时阻塞 Teammate

已知限制

  • Pane 模式 Teammate 不支持 Windows(依赖 tmux/iTerm2)
  • 文件邮箱在高频消息场景下可能成为瓶颈
  • Peer-to-Peer 消息可能被 Leader 消息饥饿(设计如此)
  • InProcess 模式下内容替换状态需要跨迭代保持一致性

代码索引

文件行数说明
utils/swarm/backends/types.ts~312后端类型定义、TeammateExecutor 接口
utils/swarm/backends/registry.ts~465后端注册、自动检测、缓存管理
utils/swarm/backends/InProcessBackend.ts~200InProcess 后端实现
utils/swarm/backends/TmuxBackend.ts~300Tmux 后端实现
utils/swarm/backends/ITermBackend.ts~250iTerm2 后端实现
utils/swarm/inProcessRunner.ts~1553InProcess Teammate 核心运行器
utils/swarm/spawnUtils.ts~147CLI 标志继承、环境变量转发
utils/swarm/teammateInit.ts~130Teammate 初始化、Stop Hook 注册
utils/swarm/permissionSync.ts~100权限请求/响应同步
utils/swarm/leaderPermissionBridge.ts~100Leader UI 权限队列桥接
utils/teammateMailbox.ts~200文件邮箱读写、消息格式
tools/AgentTool/~500Agent 工具实现、runAgent()
tools/SendMessageTool/~100消息发送工具
tasks/InProcessTeammateTask/~200InProcess 任务状态管理
utils/agentContext.ts~50AgentContext AsyncLocalStorage
utils/teammateContext.ts~50TeammateContext AsyncLocalStorage