Agent 架构
5 种任务类型、AgentTool 子 agent 调度、SendMessage 多 agent 通信——Claude Code 的多 agent 协作体系
职责概述
解决的问题:单个 AI 对话很难处理"重构整个微服务架构"这种大任务。需要一种机制把大任务拆成小任务,分配给多个 AI Agent 并行执行,再汇总结果。Agent 架构就是 CC 的"多 AI 协作"方案。
应用场景:① 用户说"把这个项目从 JS 迁移到 TS" → 主 Agent 拆分出多个子 Agent 分别处理不同模块 ② 后台 Agent 异步执行耗时任务(如全量测试),不阻塞主对话 ③ 代码审查 Agent 在完成后自动触发 review ④ 多个 Agent 组成团队,通过消息传递协调工作。
一句话理解:就像一个项目经理带着几个开发——经理拆任务、分配给组员、收集结果,组员各自独立干活,有事儿互相喊。
架构设计
任务类型层次
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() 路由流程
isolation='remote' → 远程 agent
Fork 启用 → forkSubagent
run_in_background → registerAsyncAgent
默认 → 同步 runAgent
async_launched 状态 + taskId。Teammate 返回 teammate_spawned + 邮箱信息。Agent 层次结构
REPL 主循环
同进程 query() 循环
阻塞主循环
可后台化
同进程独立运行
不阻塞主循环
TaskOutputTool 查询进度
持久化 agent
SendMessage 通信
独立权限模式
服务器端 session
轮询获取结果
脱机执行
独立对话上下文
从 assistant message 继承
Worktree 隔离
自动后台思考
consolidation lock
回滚支持
SendMessage 通信模式
pendingUserMessages 队列,teammate 在下一个 query 循环中消费。来源:SendMessageTool.ts:149关键类型与接口
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'
}
设计模式与亮点
TaskStateBase,通过 Task 接口的 kill() 方法统一管理生命周期。状态存储在 AppState.tasks Map 中,以 taskId 为 key。forkSubagent.ts 实现了一种独特的 agent 隔离:在同一进程内创建完全独立的对话上下文。通过 buildForkedMessages() 从当前 assistant message 构建子 agent 的初始消息,支持 worktree 隔离。pendingUserMessages 队列实现异步邮箱通信。Leader 通过 SendMessageTool 投递消息,teammate 在下一个 query 循环中消费。onIdleCallbacks 避免 leader 轮询。更多亮点
- 动态后台化:LocalAgentTask 和 LocalShellTask 都支持从同步模式动态转为后台模式。
backgroundAgentTask()将任务从 foreground 队列移到后台,释放主循环。用户可以在运行中按 Escape 触发后台化。 - 消息数量上限:
TEAMMATE_MESSAGES_UI_CAP = 50限制 teammate 的 UI 镜像消息数量,防止长时间运行的 teammate 消耗过多内存。完整对话保存在磁盘。 - 分布式关闭协议:SendMessageTool 实现了 request → approval/rejection 关闭协商。Teammate 不能被强制终止(除非 kill),必须通过协商优雅关闭。支持 reason 反馈。
- 计划审批流程:
plan_mode_required的 teammate 在执行前必须提交计划等待 leader 审批。Leader 通过handlePlanApproval/handlePlanRejection决定是否允许执行,支持 feedback。 - Worktree 隔离:AgentTool 支持
isolation: 'worktree'参数,为子 agent 创建独立的 git worktree。Fork 子 agent 自动检测 worktree 并注入通知。完成后自动清理。 - Task ID 前缀:每种任务类型有唯一前缀(a/b/r/t/w/m/d),便于在日志和 UI 中快速识别任务类型。8 位随机字符提供 2.8 万亿组合,抵抗暴力攻击。
- Agent 自定义 MCP:
initializeAgentMcpServers()(runAgent.ts:95)为每个 agent 初始化独立的 MCP 服务器实例,避免跨 agent 的 MCP 状态污染。 - 进度追踪:
ProgressTracker(LocalAgentTask.tsx:41-49)实时追踪 agent 的 token 使用量、工具调用次数和当前活动。支持 SDK 消费者通过tool_progress事件获取实时更新。
开发者实践指南
如何添加新的 Task 类型
Task.ts 的 TaskType 联合类型中添加新类型,在 TASK_ID_PREFIXES 中指定前缀。
tasks/ 下创建目录,实现 Task 接口(name, type, kill())。定义继承 TaskStateBase 的状态类型。
tasks.ts 的 getAllTasks() 中注册新任务。
如何使用 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 响应
注意事项
isTeammate() && teamName && name 会抛出异常)。Team roster 是扁平结构,只允许一层 teammate。
架构师决策指南
设计权衡
所有 agent 都在同一 Node.js 进程中运行(远程 agent 除外)。优势:零 IPC 开销,共享 MCP 连接,状态管理简单。代价:agent 共享事件循环,长时间运行的 agent 可能影响主循环响应性。通过
run_in_background 和 backgroundAgentTask() 缓解。
Teammate 通信采用邮箱队列(
pendingUserMessages)而非直接函数调用。优势:解耦 Leader 和 Teammate 的执行循环,支持异步消息传递和优雅关闭协商。代价:消息传递有延迟(一个 query 循环的延迟),不适合实时协作。
扩展性考量
- Agent 数量扩展:每个 In-process teammate 的 UI 镜像消息上限为 50 条(
TEAMMATE_MESSAGES_UI_CAP)。完整对话保存在磁盘。大型 swarm 场景(如 292 个 agent 的极端案例)需要关注内存。 - 新通信模式:SendMessageTool 的
action字段是可扩展的枚举。新增通信模式只需在call()中添加新的路由分支和对应的handle*函数。 - 新隔离模式:
isolation参数支持 'worktree' 和 'remote' 两种隔离。新增隔离模式(如 Docker 容器)需要修改 AgentTool.call() 的路由逻辑和对应的任务类型。
性能考量
- MCP 服务器开销:每个 agent 初始化独立的 MCP 服务器实例(
initializeAgentMcpServers())。大量并发 agent 可能导致 MCP 连接数激增。 - 内存控制:
TEAMMATE_MESSAGES_UI_CAP限制每个 teammate 的 AppState 内存占用。实际数据显示:500+ turn session 约 20MB RSS,292 agent swarm 峰值 36.8GB。消息上限从无限制改为 50 条后显著缓解。 - Task 输出持久化:所有任务输出写入磁盘文件(
getTaskOutputPath()),通过outputOffset增量读取。避免大输出占用内存。 - 过滤不完整工具调用:
filterIncompleteToolCalls()(runAgent.ts:866)清理子 agent 终止时的未完成工具调用,防止无效 tool_use block 污染主对话。
架构演进方向
LocalAgentTask 处理简单子 agent,后加入 LocalShellTask 处理后台命令,再引入 InProcessTeammateTask 实现持久化 teammate,最后加入 RemoteAgentTask 支持远程执行。每一步都是增量扩展,保留了向后兼容性。
◈ 可视化处理拓扑图
AgentTool.call() 是所有子 agent 请求的统一入口。它根据参数组合进行多级路由判断,最终将任务分发到 5 种执行路径之一。以下拓扑图展示完整的路由决策、执行引擎和结果回收流程。
返回 teammate_spawned
返回 remote_launched
继承父 prompt
内置 agent 定义
自定义 agent
Phase 2 — 系统提示注入与执行引擎
cache-identical 前缀
enhanceSystemPromptWithEnvDetails()
返回 async_launched
forward progress
Phase 3 — 同步 Agent 消息循环
① agentIterator.next() 获取下一条消息
② Promise.race([nextMessage, backgroundSignal]) 竞速
③ 消息推入 agentMessages[],更新 progress
④ result.done === true → 跳出循环
超时自动后台化:elapsed >= PROGRESS_THRESHOLD_MS → 显示 BackgroundHint
autoBackgroundMs 超时
enqueueAgentNotification
isInForkChild()、isInProcessTeammate() 等 guard 函数在运行时强制执行。⇉ 核心处理流程详解
Agent 系统的核心是一个从用户请求到最终输出的完整处理链路。入口是 AgentTool.call()(AgentTool.tsx:239),它负责路由决策、资源准备、生命周期管理,最终将子 agent 的结果返回给主对话。以下是每一步的详细处理过程:
call() 首先解析 subagent_type、team_name、name 等输入参数。如果 team_name + name 同时存在,走 Teammate 路径(调用 spawnTeammate())。否则根据 subagent_type 判断走 Fork 路径还是标准 Agent 路径。递归 Fork 防护通过 querySource(压缩安全)和消息扫描双保险实现 — AgentTool.tsx:239-340agentDefinitions.activeAgents 中查找匹配的 AgentDefinition。通过 filterDeniedAgents() 过滤被权限规则拒绝的 agent,并通过 getDenyRuleForAgent() 生成精确的错误提示(告知用户哪条规则阻止了哪个 agent)— AgentTool.tsx:340-400requiredMcpServers,系统会轮询等待尚未完成连接的 MCP 服务器(最多 30 秒)。等待完成后,从已连接工具列表中提取服务器名,验证所需的 MCP 工具确实可用。不可用则抛出明确错误引导用户运行 /mcp — AgentTool.tsx:400-470buildEffectiveSystemPrompt())以实现 cache-identical 前缀;标准路径调用 getAgentSystemPrompt()(runAgent.ts:906)构建独立 prompt。Fork 路径还通过 buildForkedMessages()(forkSubagent.ts:107)克隆父消息并注入子指令 — AgentTool.tsx:470-560assembleToolPool() 独立组装 worker 的工具池,使用 worker 自己的权限模式(默认 acceptEdits),不受父进程工具限制。如果请求了 worktree 隔离,调用 createAgentWorktree() 创建独立 git 工作树。Fork 路径额外注入 worktree 路径转换通知 — AgentTool.tsx:560-640shouldRunAsync 决定执行模式。异步路径通过 registerAsyncAgent() 注册后台任务,使用 void runAsyncAgentLifecycle() 火花运行;同步路径注册为前台任务(registerAgentForeground()),支持超时自动转后台(通过 backgroundPromise 竞速)— AgentTool.tsx:640-770initializeAgentMcpServers(),runAgent.ts:95),合并工具集,构建 agentToolUseContext,执行 SubagentStart hooks,预加载 frontmatter 中的 skills,然后进入 query() 异步迭代循环。每条消息实时记录到 sidechain transcript(runAgent.ts:735-805)— runAgent.ts:248-810finalizeAgentTool() 聚合为最终结果。如果启用了 transcript classifier,运行 classifyHandoffIfNeeded() 检测交接风险。最后执行 worktree 清理(有变更保留、无变更删除)、MCP 连接释放、前台任务注销 — AgentTool.tsx:770-1263backgroundSignal 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 获得最大的上下文共享。
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 因某种原因未传递时兜底。
if (toolUseContext.options.querySource === `agent:builtin:${FORK_AGENT.agentType}`
|| isInForkChild(toolUseContext.messages)) {
throw new Error('Fork is not available inside a forked worker.')
}
3. Worktree 隔离的智能清理
Agent 可以在独立 git worktree 中运行(isolation: 'worktree'),实现文件系统级别的沙箱。清理逻辑尤为精妙:cleanupWorktreeIfNeeded()(AgentTool.tsx:644)比较 worktree 创建时的 HEAD commit 和当前状态——有变更则保留 worktree,无变更则自动删除。Hook-based worktree 永远保留(因为无法检测 VCS 变更)。
4. 消息过滤保证 API 一致性
filterIncompleteToolCalls()(runAgent.ts:866)在多个关键路径上确保消息序列符合 API 规范:每个 tool_use 必须有对应的 tool_result。当 Fork 子 agent 的父消息包含多个 tool_use 但只需处理其中一部分时,该函数为未配对的 tool_use 补充 placeholder result,防止 API 拒绝请求。同样在 agent 终止时清理未完成的工具调用。
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),实现了开放-封闭原则。
LocalAgentTask 到 InProcessTeammateTask 再到 RemoteAgentTask 的演进路径展示了"先具体后抽象"的架构演进模式。每种新 Task 类型都是增量添加,不修改已有类型的逻辑,通过统一的 Task 接口保持兼容性。◈ Agent 实践借鉴 — 客服 Agent 多 Agent 协作设计
场景映射:客服 agent 在协作上遇到的真实问题
在客服场景中,多 agent 协作是刚需而非锦上添花。典型痛点包括:
- 技术问题升级:客户来电,一线 agent 处理不了的技术问题需要转给技术支持 agent,转交时上下文容易丢失,客户被迫重复描述问题。
- 退单审批流转:退单超过 5000 元需要主管 agent 审批,一线 agent 必须带上操作建议(如"建议同意退款,原因是物流破损")提交审批,主管审批后一线 agent 才能执行。
- 大促期间并行查询:一个 agent 查订单状态,另一个 agent 同时查物流轨迹,两个结果合并后才能给客户完整答复。串行查询太慢,客户等不及。
- VIP 专属权限:VIP 客户有专属 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——后台自动思考在客服场景没有意义。
代码索引
| 文件 | 行数 | 说明 |
|---|---|---|
Task.ts | ~126 | Task 类型定义:TaskType, TaskStatus, TaskStateBase, Task 接口, ID 生成 |
tasks.ts | ~40 | 任务注册表:getAllTasks(), getTaskByType() |
tools/AgentTool/AgentTool.tsx | ~1398 | AgentTool 入口:call() 路由逻辑、5 种运行模式分发 |
tools/AgentTool/runAgent.ts | ~974 | Agent 执行引擎:MCP 初始化、query() 循环、消息过滤、system prompt 构建 |
tools/AgentTool/forkSubagent.ts | ~211 | Fork 子 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 | ~523 | Shell 命令任务:spawn、后台化、stall 检测、通知 |
tasks/InProcessTeammateTask/InProcessTeammateTask.tsx | ~126 | In-process teammate:kill、消息注入、shutdown 协商 |
tasks/InProcessTeammateTask/types.ts | ~122 | Teammate 状态类型定义:TeammateIdentity, 消息上限 |
tasks/RemoteAgentTask/RemoteAgentTask.tsx | ~856 | 远程 agent:session 管理、轮询、review 提取、ultraplan 处理 |
tasks/DreamTask/DreamTask.ts | ~158 | Dream agent:自动启动、turn 追踪、consolidation lock 回滚 |
tools/TaskOutputTool/ | 目录 | 任务输出查询工具 |
tools/TaskStopTool/ | 目录 | 任务终止工具 |
tools/TaskCreateTool/~TaskListTool/ | 目录 | TodoV2 任务管理工具集 |