职责概述

解决的问题:单个 AI 对话很难处理"重构整个微服务架构"这种大任务。需要一种机制把大任务拆成小任务,分配给多个 AI Agent 并行执行,再汇总结果。Agent 架构就是 CC 的"多 AI 协作"方案。

应用场景:① 用户说"把这个项目从 JS 迁移到 TS" → 主 Agent 拆分出多个子 Agent 分别处理不同模块 ② 后台 Agent 异步执行耗时任务(如全量测试),不阻塞主对话 ③ 代码审查 Agent 在完成后自动触发 review ④ 多个 Agent 组成团队,通过消息传递协调工作。

一句话理解:就像一个项目经理带着几个开发——经理拆任务、分配给组员、收集结果,组员各自独立干活,有事儿互相喊。

架构设计

任务类型层次

AgentTool 入口(tools/AgentTool/AgentTool.tsx)
call() — 统一入口,根据参数路由到不同运行模式
输入参数:prompt, subagent_type, run_in_background, name, team_name, isolation, cwd
任务调度层
runAgent.ts — 同步/异步子 agent 执行引擎
forkSubagent.ts — Fork 子 agent(同一进程独立对话)
spawnInProcess.ts — In-process teammate 生成
远程 agent 会话管理
Task 实现层(tasks/)
LocalAgentTask — 本地 agent 任务状态管理
LocalShellTask — 后台 shell 命令任务
InProcessTeammateTask — 进程内 teammate
RemoteAgentTask — 远程 agent 会话
DreamTask — 梦境代理(后台思考)
通信层
SendMessageTool — 点对点/广播消息
TeamCreateTool / TeamDeleteTool — 团队管理
TaskOutputTool — 任务输出查询
TaskStopTool — 任务终止

5 种 Task 类型对比

TaskType前缀执行环境生命周期通信
local_agent a 同进程,独立 query() 循环 同步或后台化 通过 parentMessage 注入
local_bash b Shell 子进程 同步或后台化 文件输出 + 轮询
in_process_teammate t 同进程,独立 query() 循环 持续运行直到关闭 SendMessage 邮箱
remote_agent r 远程服务器(API session) 异步轮询 Session 状态同步
dream d 同进程,自动 Dream 提示 自动启动/完成 文件系统(consolidation lock)

核心数据流

AgentTool.call() 路由流程

1. 参数解析
解析 prompt, subagent_type, run_in_background, name, team_name, isolation, cwd 参数。获取权限模式和 agent 定义。来源:AgentTool.tsx:239-275
2. 路由判断
team_name + name → spawnTeammate(In-process teammate)
isolation='remote' → 远程 agent
Fork 启用 → forkSubagent
run_in_background → registerAsyncAgent
默认 → 同步 runAgent
3. 执行引擎
runAgent.ts 创建独立的 query() 循环,组装工具集(filterToolsForAgent),初始化 MCP 服务器,构建 system prompt,启动消息处理。
4. 结果处理
同步 agent 直接返回结果。异步 agent 返回 async_launched 状态 + taskId。Teammate 返回 teammate_spawned + 邮箱信息。

Agent 层次结构

主 Agent (Leader)
REPL 主循环
▼ AgentTool.call()
同步子 Agent
同进程 query() 循环
阻塞主循环
可后台化
异步后台 Agent
同进程独立运行
不阻塞主循环
TaskOutputTool 查询进度
In-process Teammate
持久化 agent
SendMessage 通信
独立权限模式
远程 Agent
服务器端 session
轮询获取结果
脱机执行
Fork 子 Agent
独立对话上下文
从 assistant message 继承
Worktree 隔离
Dream Agent
自动后台思考
consolidation lock
回滚支持

SendMessage 通信模式

handleMessage — 点对点消息
向指定 teammate 注入用户消息。消息进入 pendingUserMessages 队列,teammate 在下一个 query 循环中消费。来源:SendMessageTool.ts:149
handleBroadcast — 广播
向所有活跃 teammate 发送相同消息。每个 teammate 独立接收和处理。来源:SendMessageTool.ts:191
handleShutdownRequest/Approval — 关闭协商
请求关闭 teammate 需要对方批准。实现分布式关闭协议:request → approval/rejection。来源:SendMessageTool.ts:268-432
handlePlanApproval/Rejection — 计划审批
plan_mode_required 的 teammate 需要提交计划等待 leader 审批。审批通过后 teammate 才能执行。来源:SendMessageTool.ts:434-518

关键类型与接口

TaskType 与 TaskStatus(Task.ts:6-29)

export type TaskType =
  | 'local_bash'          // Shell 命令任务
  | 'local_agent'         // 本地 agent 任务
  | 'remote_agent'        // 远程 agent 任务
  | 'in_process_teammate' // 进程内 teammate
  | 'local_workflow'      // 工作流任务
  | 'monitor_mcp'         // MCP 监控任务
  | 'dream'               // 梦境代理

export type TaskStatus =
  | 'pending' | 'running' | 'completed' | 'failed' | 'killed'

export function isTerminalTaskStatus(status: TaskStatus): boolean {
  return status === 'completed' || status === 'failed' || status === 'killed'
}

Task 接口(Task.ts:72-76)

export type Task = {
  name: string
  type: TaskType
  kill(taskId: string, setAppState: SetAppState): Promise<void>
}

TaskStateBase 共享状态(Task.ts:45-57)

export type TaskStateBase = {
  id: string
  type: TaskType
  status: TaskStatus
  description: string
  toolUseId?: string
  startTime: number
  endTime?: number
  totalPausedMs?: number
  outputFile: string     // 输出文件路径(磁盘持久化)
  outputOffset: number   // 输出读取偏移量
  notified: boolean      // 是否已通知用户
}

Task ID 生成(Task.ts:98-106)

const TASK_ID_PREFIXES: Record<string, string> = {
  local_bash: 'b', local_agent: 'a', remote_agent: 'r',
  in_process_teammate: 't', local_workflow: 'w',
  monitor_mcp: 'm', dream: 'd',
}

export function generateTaskId(type: TaskType): string {
  const prefix = getTaskIdPrefix(type)
  const bytes = randomBytes(8)  // 36^8 ≈ 2.8 万亿组合
  let id = prefix
  for (let i = 0; i < 8; i++) {
    id += TASK_ID_ALPHABET[bytes[i]! % TASK_ID_ALPHABET.length]
  }
  return id  // 例如 "a3f7k2j9n"
}

InProcessTeammateTaskState(tasks/InProcessTeammateTask/types.ts:22-76)

export type InProcessTeammateTaskState = TaskStateBase & {
  type: 'in_process_teammate'
  identity: TeammateIdentity       // agentId, agentName, teamName, color
  prompt: string
  model?: string                   // 可选模型覆盖
  selectedAgent?: AgentDefinition  // 可选 agent 定义
  abortController?: AbortController
  currentWorkAbortController?: AbortController
  awaitingPlanApproval: boolean    // 等待计划审批
  permissionMode: PermissionMode   // 独立权限模式
  result?: AgentToolResult
  progress?: AgentProgress
  messages?: Message[]             // 对话历史(UI 镜像,最多 50 条)
  pendingUserMessages: string[]    // 待消费的用户消息队列
  isIdle: boolean                  // 是否空闲(等待消息)
  shutdownRequested: boolean       // 关闭请求标志
  onIdleCallbacks?: Array<() => void>  // idle 通知回调
}

AgentTool 输出类型(AgentTool.tsx:140-191)

// 同步完成
{ status: 'completed', prompt: string, ...agentToolResult }

// 异步启动
{ status: 'async_launched', agentId, description, prompt, outputFile, canReadOutputFile }

// Teammate 启动(内部类型)
{ status: 'teammate_spawned', prompt, teammate_id, agent_id, name, color,
  tmux_session_name, tmux_window_name, tmux_pane_id, team_name,
  is_splitpane, plan_mode_required }

// 远程启动
{ status: 'remote_launched', taskId, sessionUrl, description, prompt, outputFile }

SendMessage 路由类型(SendMessageTool.ts:92-131)

export type MessageRouting = {
  recipient: string       // 目标 teammate 名称或 'all'
  content: string         // 消息内容
  summary?: string        // 消息摘要
  action?: 'message' | 'broadcast' | 'shutdown_request' | 'shutdown_approval'
          | 'shutdown_rejection' | 'plan_approval' | 'plan_rejection'
}

设计模式与亮点

统一 Task 抽象
所有任务类型(agent、shell、teammate、remote、dream)共享 TaskStateBase,通过 Task 接口的 kill() 方法统一管理生命周期。状态存储在 AppState.tasks Map 中,以 taskId 为 key。
核心
Fork 子 agent 模式
forkSubagent.ts 实现了一种独特的 agent 隔离:在同一进程内创建完全独立的对话上下文。通过 buildForkedMessages() 从当前 assistant message 构建子 agent 的初始消息,支持 worktree 隔离。
高级
邮箱式通信
In-process teammate 使用 pendingUserMessages 队列实现异步邮箱通信。Leader 通过 SendMessageTool 投递消息,teammate 在下一个 query 循环中消费。onIdleCallbacks 避免 leader 轮询。
高效

更多亮点

开发者实践指南

如何添加新的 Task 类型

步骤 1:在 Task.tsTaskType 联合类型中添加新类型,在 TASK_ID_PREFIXES 中指定前缀。
步骤 2:在 tasks/ 下创建目录,实现 Task 接口(name, type, kill())。定义继承 TaskStateBase 的状态类型。
步骤 3:在 tasks.tsgetAllTasks() 中注册新任务。

如何使用 AgentTool 调度子 agent

// 同步子 agent(阻塞等待完成)
{ prompt: "分析这个文件", subagent_type: "code-reviewer" }

// 异步后台 agent
{ prompt: "重构整个模块", run_in_background: true }

// In-process teammate(持久化 agent)
{ prompt: "你负责测试", name: "tester", team_name: "dev-team" }

// 远程 agent
{ prompt: "运行大规模分析", isolation: "remote" }

// Fork 子 agent(实验性)
{ prompt: "探索代码库", subagent_type: "explorer" }

Teammate 通信模式

// Leader 向 teammate 发送消息
SendMessageTool: { recipient: "tester", content: "请测试登录功能" }

// Leader 广播消息
SendMessageTool: { recipient: "all", content: "代码已合并", action: "broadcast" }

// Leader 请求关闭 teammate
SendMessageTool: { recipient: "researcher", action: "shutdown_request" }

// Teammate 提交计划等待审批(内部机制)
// teammate 自动将计划发送给 leader,leader 通过 PlanApproval 响应

注意事项

循环防护:Teammate 不能嵌套生成 teammate(isTeammate() && teamName && name 会抛出异常)。Team roster 是扁平结构,只允许一层 teammate。
In-process teammate 限制:In-process teammate 不能创建后台 agent(生命周期绑定到 leader 进程),也不能嵌套生成 teammate。

架构师决策指南

设计权衡

同进程 vs 多进程
所有 agent 都在同一 Node.js 进程中运行(远程 agent 除外)。优势:零 IPC 开销,共享 MCP 连接,状态管理简单。代价:agent 共享事件循环,长时间运行的 agent 可能影响主循环响应性。通过 run_in_backgroundbackgroundAgentTask() 缓解。
邮箱队列 vs 直接调用
Teammate 通信采用邮箱队列(pendingUserMessages)而非直接函数调用。优势:解耦 Leader 和 Teammate 的执行循环,支持异步消息传递和优雅关闭协商。代价:消息传递有延迟(一个 query 循环的延迟),不适合实时协作。

扩展性考量

性能考量

架构演进方向

从单 agent 到多 agent:代码库的演进路径清晰可见——最初的 LocalAgentTask 处理简单子 agent,后加入 LocalShellTask 处理后台命令,再引入 InProcessTeammateTask 实现持久化 teammate,最后加入 RemoteAgentTask 支持远程执行。每一步都是增量扩展,保留了向后兼容性。

可视化处理拓扑图

AgentTool.call() 是所有子 agent 请求的统一入口。它根据参数组合进行多级路由判断,最终将任务分发到 5 种执行路径之一。以下拓扑图展示完整的路由决策、执行引擎和结果回收流程。

AgentTool.call() 入口AgentTool.tsx:239 — 解析 prompt, subagent_type, run_in_background, name, team_name
Team Name + Name 检查L290 — team_name + name 同时存在?
spawnTeammate()In-process teammate 生成
返回 teammate_spawned
否 ↓
isolation='remote' 检查L548 — 远程隔离模式?
teleportToRemote()CCR 远程 session
返回 remote_launched
否 ↓
Agent Type 路由L350-400 — Fork 开关 / subagent_type 匹配 / 权限过滤
Fork PatheffectiveType=undefined
继承父 prompt
Built-in Agentsubagent_type 匹配
内置 agent 定义
Custom AgentagentDefinitions
自定义 agent
Agent 不存在 / 权限拒绝filterDeniedAgents() → throw Error

Phase 2 — 系统提示注入与执行引擎

selectedAgent 确定L400 — agentDefinition + model + MCP server 检查
系统提示构建L540-600 — Fork 与 Normal 两条路径
Fork: 继承父 systemPromptbuildForkedMessages()
cache-identical 前缀
Normal: Agent 专属 promptgetSystemPrompt() + envDetails
enhanceSystemPromptWithEnvDetails()
shouldRunAsync 判断L640 — background / coordinator / forkForce / proactive
异步: registerAsyncAgentvoid runAsyncAgentLifecycle()
返回 async_launched
同步: runAgent iteratorwhile(true) 消息循环
forward progress
runAgent() — 独立 query() 循环runAgent.ts — assembleToolPool + initMCP + buildPrompt + query()

Phase 3 — 同步 Agent 消息循环

runAgent() AsyncIteratorrunAgent.ts — yield Message 逐一产出
while(true) 消息迭代循环 — AgentTool.tsx:850-1000
每次迭代:
① agentIterator.next() 获取下一条消息
② Promise.race([nextMessage, backgroundSignal]) 竞速
③ 消息推入 agentMessages[],更新 progress
④ result.done === true → 跳出循环
超时自动后台化:elapsed >= PROGRESS_THRESHOLD_MS → 显示 BackgroundHint
backgroundSignal 触发用户点击后台化或
autoBackgroundMs 超时
转入后台
async_launched继续后台运行
enqueueAgentNotification
循环结束 → finalizeAgentTool()提取文本 + 统计 toolUseCount + durationMs
classifyHandoffIfNeededL1010 — 交接警告检测(Transcript Classifier)
cleanupWorktreeIfNeeded()L644 — 检测 worktree 变更 → 保留或删除
路由设计要点:AgentTool.call() 的路由决策是级联式的——team_name 优先级最高(coordinator 模式),然后是 remote isolation(CCR 远程执行),最后是 Fork/Built-in/Custom 三选一。每一级都有递归守卫:Fork 子 agent 不能再 fork、In-process teammate 不能创建后台 agent、子 agent 不继承父的 setAppState 权限。这些约束通过 isInForkChild()isInProcessTeammate() 等 guard 函数在运行时强制执行。

核心处理流程详解

Agent 系统的核心是一个从用户请求到最终输出的完整处理链路。入口是 AgentTool.call()(AgentTool.tsx:239),它负责路由决策、资源准备、生命周期管理,最终将子 agent 的结果返回给主对话。以下是每一步的详细处理过程:

1. 路由决策与类型解析
call() 首先解析 subagent_typeteam_namename 等输入参数。如果 team_name + name 同时存在,走 Teammate 路径(调用 spawnTeammate())。否则根据 subagent_type 判断走 Fork 路径还是标准 Agent 路径。递归 Fork 防护通过 querySource(压缩安全)和消息扫描双保险实现 — AgentTool.tsx:239-340
2. Agent 定义查找与权限过滤
agentDefinitions.activeAgents 中查找匹配的 AgentDefinition。通过 filterDeniedAgents() 过滤被权限规则拒绝的 agent,并通过 getDenyRuleForAgent() 生成精确的错误提示(告知用户哪条规则阻止了哪个 agent)— AgentTool.tsx:340-400
3. MCP 依赖等待与验证
如果 Agent 声明了 requiredMcpServers,系统会轮询等待尚未完成连接的 MCP 服务器(最多 30 秒)。等待完成后,从已连接工具列表中提取服务器名,验证所需的 MCP 工具确实可用。不可用则抛出明确错误引导用户运行 /mcp — AgentTool.tsx:400-470
4. System Prompt 构建与消息准备
这是缓存命中率的关键步骤。Fork 路径复用父进程的 system prompt(通过 buildEffectiveSystemPrompt())以实现 cache-identical 前缀;标准路径调用 getAgentSystemPrompt()(runAgent.ts:906)构建独立 prompt。Fork 路径还通过 buildForkedMessages()(forkSubagent.ts:107)克隆父消息并注入子指令 — AgentTool.tsx:470-560
5. 工具池组装与隔离设置
通过 assembleToolPool() 独立组装 worker 的工具池,使用 worker 自己的权限模式(默认 acceptEdits),不受父进程工具限制。如果请求了 worktree 隔离,调用 createAgentWorktree() 创建独立 git 工作树。Fork 路径额外注入 worktree 路径转换通知 — AgentTool.tsx:560-640
6. 同步/异步分发
根据 shouldRunAsync 决定执行模式。异步路径通过 registerAsyncAgent() 注册后台任务,使用 void runAsyncAgentLifecycle() 火花运行;同步路径注册为前台任务(registerAgentForeground()),支持超时自动转后台(通过 backgroundPromise 竞速)— AgentTool.tsx:640-770
7. runAgent() 执行引擎
这是核心执行循环。初始化 agent 专属 MCP 服务器(initializeAgentMcpServers(),runAgent.ts:95),合并工具集,构建 agentToolUseContext,执行 SubagentStart hooks,预加载 frontmatter 中的 skills,然后进入 query() 异步迭代循环。每条消息实时记录到 sidechain transcript(runAgent.ts:735-805)— runAgent.ts:248-810
8. 结果收集与清理
同步 agent 的消息通过 finalizeAgentTool() 聚合为最终结果。如果启用了 transcript classifier,运行 classifyHandoffIfNeeded() 检测交接风险。最后执行 worktree 清理(有变更保留、无变更删除)、MCP 连接释放、前台任务注销 — AgentTool.tsx:770-1263
关键处理逻辑:整个流程最精妙的设计是同步 Agent 的"可后台化"机制。前台 Agent 注册时会创建一个 backgroundSignal Promise,在迭代循环中通过 Promise.race([nextMessage, backgroundPromise]) 竞速。当超时(autoBackgroundMs)或用户手动后台化时,signal 触发,当前迭代器被清理,新的 runAgent() 在后台启动并从已有消息继续。这实现了从同步到异步的无缝转换,用户无需重新发起请求。

设计精华

1. Fork 路径的 Cache-Identical 前缀优化

Fork 子 agent 复用父进程的完整 system prompt 和工具定义数组(useExactTools: true),确保 API 请求的字节前缀完全一致,从而命中 prompt cache。这是性能优化的极致体现——不是"相似",而是"字节级一致"。代价是 Fork 子 agent 继承了父进程的 thinking 配置和交互模式,但这正是设计意图:用最少的 cache_creation tokens 获得最大的上下文共享。

Fork 工具池继承(AgentTool.tsx:590-600)
Fork 路径传递父进程的工具列表和 system prompt,而非重新构建
availableTools: isForkPath ? toolUseContext.options.tools : workerTools,
// useExactTools 让 runAgent 跳过 resolveAgentTools(),直接使用传入的工具
// 同时继承父进程的 thinkingConfig 和 isNonInteractiveSession
...(isForkPath && { useExactTools: true }),
设计洞察:通过 buildForkedMessages()(forkSubagent.ts:107)克隆父 assistant 消息的所有 tool_use 块,并为每个 Fork 子 agent 注入占位符 tool_result + 独立指令,实现了在单一 API 前缀下并行派生多个工作单元。

2. 递归 Fork 双重防护

Fork 子 agent 保留了 Agent 工具(用于 cache 前缀一致),但必须防止递归 Fork。系统使用两级防护:主防护是 context.options.querySource(设为 'agent:builtin:fork'),这个值存在于 options 对象上而非消息中,因此能抵抗 autocompact 的消息重写。备用防护是 isInForkChild()(forkSubagent.ts:78),扫描消息中是否存在 Fork 标记——当 querySource 因某种原因未传递时兜底。

递归 Fork 检测(AgentTool.tsx:340-355)
主防护检查 options 上的 querySource,备用防护扫描消息历史
if (toolUseContext.options.querySource === `agent:builtin:${FORK_AGENT.agentType}`
    || isInForkChild(toolUseContext.messages)) {
  throw new Error('Fork is not available inside a forked worker.')
}
设计洞察:为什么不用简单的布尔标记?因为 autocompact 会重写消息,删除旧的 Fork boilerplate。把标记放在 options 对象上,options 在整个 agent 生命周期内保持不变,不受压缩影响。这种"元数据与消息分离"的模式在多个地方使用。

3. Worktree 隔离的智能清理

Agent 可以在独立 git worktree 中运行(isolation: 'worktree'),实现文件系统级别的沙箱。清理逻辑尤为精妙:cleanupWorktreeIfNeeded()(AgentTool.tsx:644)比较 worktree 创建时的 HEAD commit 和当前状态——有变更则保留 worktree,无变更则自动删除。Hook-based worktree 永远保留(因为无法检测 VCS 变更)。

设计洞察:这种"创建快照-执行-比较差异-条件清理"的模式是资源管理的最佳实践。它避免了"无变更也保留"的空间浪费,也避免了"有变更也删除"的数据丢失。清理结果还会写入 agent metadata 并传递给通知,让 resume 路径知道 worktree 的最终状态。

4. 消息过滤保证 API 一致性

filterIncompleteToolCalls()(runAgent.ts:866)在多个关键路径上确保消息序列符合 API 规范:每个 tool_use 必须有对应的 tool_result。当 Fork 子 agent 的父消息包含多个 tool_use 但只需处理其中一部分时,该函数为未配对的 tool_use 补充 placeholder result,防止 API 拒绝请求。同样在 agent 终止时清理未完成的工具调用。

不完整工具调用过滤(runAgent.ts:866-904)
遍历消息,收集所有 tool_use ID,为缺失的 tool_result 补充空结果
export function filterIncompleteToolCalls(messages: Message[]): Message[] {
  // 收集所有 tool_use ID 和已匹配的 tool_result ID
  // 对于未匹配的 tool_use,在其后的 assistant 消息前
  // 插入带空结果的 user 消息
}

5. 模块化 Task 类型系统

Task 类型(Task.ts:6-76)定义了 6 种 TaskType,每种对应不同的执行模型:local-agent(本地同步/异步)、local-shell(后台命令)、in-process-teammate(进程内持久化队友)、remote-agent(远程执行)等。getTaskByType() 工厂函数根据类型分发不同的 Task handler,每种 handler 只实现自己关心的生命周期方法(kill、spawn、render),实现了开放-封闭原则。

设计洞察:从 LocalAgentTaskInProcessTeammateTask 再到 RemoteAgentTask 的演进路径展示了"先具体后抽象"的架构演进模式。每种新 Task 类型都是增量添加,不修改已有类型的逻辑,通过统一的 Task 接口保持兼容性。

Agent 实践借鉴 — 客服 Agent 多 Agent 协作设计

场景映射:客服 agent 在协作上遇到的真实问题

在客服场景中,多 agent 协作是刚需而非锦上添花。典型痛点包括:

借鉴 CC + 客服改造

1. 客服 agent 的任务类型定义(CC 5 种 → 客服 3 种)

CC 定义了 7 种 TaskType(local_agent/local_bash/in_process_teammate/remote_agent/local_workflow/monitor_mcp/dream),但客服场景只需要 3 种核心模式:

// CC 的 5 种运行模式 → 客服场景精简为 3 种
type ServiceTaskType =
  | 'sync_query'      // 同步处理:查订单、查物流、回答FAQ
  | 'async_background' // 异步后台:发短信通知、同步CRM记录
  | 'escalation'      // 升级转交:技术支持、主管审批

type ServiceTaskStatus =
  | 'pending' | 'handling' | 'waiting_approval'
  | 'completed' | 'failed' | 'timeout'

// 统一任务基类——借鉴 CC 的 TaskStateBase
interface ServiceTask {
  taskId: string
  type: ServiceTaskType
  status: ServiceTaskStatus
  customerPhone: string
  startTime: number
  endTime?: number
  // 输出持久化到磁盘,避免内存溢出
  outputFilePath: string
  kill(): Promise<void>
}

// 优先级路由:借鉴 CC AgentTool.call() 的级联路由
function dispatchServiceTask(params: ServiceTaskParams): ServiceTaskResult {
  // 优先级 1: 升级转交(金额超限/技术问题/VIP专属)
  if (needsEscalation(params)) {
    return escalateToSpecialist(params)
  }
  // 优先级 2: 异步后台(通知/日志/数据同步)
  if (isBackgroundTask(params)) {
    return launchBackgroundTask(params)  // fire-and-forget
  }
  // 默认: 同步处理(一线 agent 直接处理)
  return handleSyncQuery(params)
}

2. agent 间上下文传递协议(借鉴 CC SendMessageTool)

CC 的 SendMessageTool 使用 pendingUserMessages 队列 + onIdleCallbacks 实现邮箱式通信。客服场景改造为"带摘要的上下文传递"——不是传递完整对话(太长),而是传递关键信息摘要:

// 借鉴 CC 的 MessageRouting → 客服场景的上下文传递协议
interface HandoffContext {
  fromAgent: string          // 来源 agent(如 "一线坐席-A03")
  toAgent: string            // 目标 agent(如 "技术支持-B07")
  customerProfile: {
    phone: string
    vipLevel: 'normal' | 'silver' | 'gold' | 'platinum'
    tags: string[]           // 如 ["高频投诉", "退款偏好"]
  }
  issueSummary: string       // 问题摘要(不是完整对话!)
  actionsTaken: string[]     // 已执行的操作(如 ["已查订单 ORD-20240101", "已查物流 显示签收"])
  recommendation?: string    // 操作建议(如 "建议同意退款,物流显示破损")
  urgency: 'low' | 'medium' | 'high' | 'critical'
}

// 上下文传递——借鉴 CC 的 handleMessage + pendingUserMessages
function handoffToSpecialist(context: HandoffContext): void {
  const targetAgent = findAvailableAgent(context.toAgent)
  // 摘要注入 target agent 的消息队列
  targetAgent.pendingMessages.push(formatHandoffPrompt(context))
  // 借鉴 CC 的 onIdleCallbacks:如果目标 agent 空闲,立即唤醒
  if (targetAgent.isIdle) {
    targetAgent.onIdleCallbacks.forEach(cb => cb())
  }
}

// 格式化转交提示——关键信息在前,不是原始对话堆砌
function formatHandoffPrompt(ctx: HandoffContext): string {
  return `[客户转交] 来自 ${ctx.fromAgent}
客户: ${ctx.customerProfile.phone} (${ctx.customerProfile.vipLevel})
问题: ${ctx.issueSummary}
已处理: ${ctx.actionsTaken.join('; ')}
建议: ${ctx.recommendation || '无'}
紧急度: ${ctx.urgency}`
}

3. 并行查询 + 结果合并(借鉴 CC Fork cache-identical)

CC 的 Fork 模式通过共享 system prompt 实现 cache-identical 前缀。客服场景借鉴其"共享上下文、独立执行"的思想,做并行查询:

// 借鉴 CC Fork 的"共享上下文、独立执行" → 客服并行查询
async function parallelQuery(customerId: string, issues: string[]) {
  // 共享上下文:客户基本信息(避免每个 agent 重复查)
  const sharedContext = {
    customerId,
    customerProfile: await getCustomerProfile(customerId),
  }

  // 并行派生多个查询任务——类似 CC 的 Fork 子 agent
  const tasks = issues.map(issue => ({
    agent: selectAgentForIssue(issue),
    context: { ...sharedContext, query: issue },
  }))

  // Promise.allSettled——不因单个查询失败而放弃全部
  const results = await Promise.allSettled(
    tasks.map(t => t.agent.query(t.context))
  )

  // 合并结果——每个查询只返回摘要,不是原始数据
  return results.map((r, i) => ({
    issue: issues[i],
    status: r.status,
    summary: r.status === 'fulfilled' ? r.value.summary : '查询失败',
  }))
}

// 使用示例:大促期间同时查订单 + 物流
const queryResults = await parallelQuery('CUS-12345', [
  '查询订单 ORD-20240101 的状态',
  '查询订单 ORD-20240101 的物流轨迹',
])
// → [{ issue: '订单状态', summary: '已发货,预计明天到达' },
//    { issue: '物流轨迹', summary: '最新节点: 广州中转站,今天14:00' }]

4. 升级审批流程(借鉴 CC 计划审批机制)

CC 的 plan_mode_required teammate 需要提交计划等待 leader 审批。客服场景改造为"一线 agent 提交操作建议 → 主管审批":

// 借鉴 CC 的 plan_approval/plan_rejection → 客服升级审批
interface EscalationRequest {
  requestId: string
  fromAgent: string
  customerPhone: string
  issueType: 'refund' | 'compensation' | 'technical' | 'complaint'
  amount?: number            // 退单金额
  recommendation: string     // 一线 agent 的建议
  evidence: string[]         // 支撑材料(订单截图、物流证据等)
}

// 一线 agent 提交审批
async function submitApproval(req: EscalationRequest): Promise<void> {
  const supervisor = await findAvailableSupervisor(req.issueType)
  // 借鉴 CC 的 pendingUserMessages 队列
  supervisor.pendingApprovals.push(req)
  // 通知主管(类似 CC 的 onIdleCallbacks)
  notifySupervisor(supervisor.id, `新的审批请求: ${req.issueType}`)
}

// 主管审批——借鉴 CC 的 handlePlanApproval / handlePlanRejection
async function handleApproval(
  requestId: string,
  decision: 'approved' | 'rejected',
  feedback?: string
): Promise<void> {
  const req = findEscalationRequest(requestId)
  if (decision === 'approved') {
    // 自动执行一线 agent 的建议(如发起退款)
    await executeRecommendation(req.recommendation)
  }
  // 回传审批结果给一线 agent
  notifyAgent(req.fromAgent, {
    requestId,
    decision,
    feedback,  // 如 "同意退款,但下次先核实物流再提交"
  })
}

落地清单

必须抄的:
1. 统一任务类型——所有 agent 任务共享同一个 ServiceTask 接口,新增任务类型不改下游代码。
2. agent 间消息协议——传递摘要而非完整对话,带操作建议和紧急度。
3. 上下文共享——并行查询前共享客户基本信息,避免每个 agent 重复查 CRM。
4. 审批流程——一线 agent 不能直接执行超额操作,必须经过主管 agent 审批。
不需要抄的:
1. 5 种运行模式——客服场景 3 种够用(同步/异步/升级),不需要 Fork cache 优化和 Dream agent。
2. Fork cache-identical 优化——客服对话短(平均 5-10 轮),不需要 prompt cache 共享来节省 token。
3. Remote agent——客服 agent 都在内网运行,不需要远程执行能力。
4. Dream agent——后台自动思考在客服场景没有意义。
常见坑: 1. 转交时丢失上下文——最常见的问题。一线 agent 转交时只传了"客户要退款",没传订单号、退款原因、已处理步骤,导致技术支持/主管 agent 重复询问客户,体验极差。必须在 HandoffContext 中强制包含 actionsTaken 和 recommendation 字段。 2. 并行查询没有超时控制——一个查询卡住(如物流系统响应慢),整个并行任务都卡住。每个并行查询必须设独立超时,超时的返回默认值而非阻塞。 3. 主管审批变成瓶颈——所有升级请求都走同一个主管队列,大促期间主管处理不过来,客户等待超时。需要按问题类型分配多个主管,并设超时自动升级机制。

代码索引

文件行数说明
Task.ts~126Task 类型定义:TaskType, TaskStatus, TaskStateBase, Task 接口, ID 生成
tasks.ts~40任务注册表:getAllTasks(), getTaskByType()
tools/AgentTool/AgentTool.tsx~1398AgentTool 入口:call() 路由逻辑、5 种运行模式分发
tools/AgentTool/runAgent.ts~974Agent 执行引擎:MCP 初始化、query() 循环、消息过滤、system prompt 构建
tools/AgentTool/forkSubagent.ts~211Fork 子 agent:消息构建、worktree 通知、递归防护
tools/AgentTool/loadAgentsDir.ts~文件Agent 定义加载:目录扫描、frontmatter 解析
tools/AgentTool/builtInAgents.ts~文件内置 agent 类型定义
tools/AgentTool/agentMemory.ts~文件Agent 记忆快照管理
tools/SendMessageTool/SendMessageTool.ts~918多 agent 通信:handleMessage, handleBroadcast, 关闭协商, 计划审批
tools/TeamCreateTool/目录团队创建工具(Swarm 模式)
tools/TeamDeleteTool/目录团队删除工具
tasks/LocalAgentTask/LocalAgentTask.tsx~683本地 agent 任务:注册、进度追踪、后台化、完成/失败处理
tasks/LocalShellTask/LocalShellTask.tsx~523Shell 命令任务:spawn、后台化、stall 检测、通知
tasks/InProcessTeammateTask/InProcessTeammateTask.tsx~126In-process teammate:kill、消息注入、shutdown 协商
tasks/InProcessTeammateTask/types.ts~122Teammate 状态类型定义:TeammateIdentity, 消息上限
tasks/RemoteAgentTask/RemoteAgentTask.tsx~856远程 agent:session 管理、轮询、review 提取、ultraplan 处理
tasks/DreamTask/DreamTask.ts~158Dream agent:自动启动、turn 追踪、consolidation lock 回滚
tools/TaskOutputTool/目录任务输出查询工具
tools/TaskStopTool/目录任务终止工具
tools/TaskCreateTool/~TaskListTool/目录TodoV2 任务管理工具集