第四章:tRPC-Agent-Go Team 多 Agent 协作
本章目标:深入理解 Coordinator 和 Swarm 两种多 Agent 协作模式,搞清楚它们各自的适用场景和实现机制。
4.1 为什么需要多 Agent?
一个 Agent 能做的事是有限的。就像一个人——即使是全栈工程师,同时又精通机器学习、法律合规、UI 设计也不现实。
多 Agent 的核心动机:
- 专业分工:每个 Agent 专注一个领域,配备该领域的专用工具和知识
- Token 效率:一个 Agent 加载 100 个工具的描述会占满 context window;10 个 Agent 各加载 10 个工具更高效
- 并行加速:多个独立子任务可以分给不同 Agent 同时执行
- 容错隔离:一个 Agent 出错不会影响其他 Agent 的执行
日常类比:公司为什么要分部门?因为一个人不可能什么都擅长。市场部做推广、研发部做产品、财务部管钱——各司其职,通过组织架构协作。
4.2 tRPC-Agent 的两种协作模式
tRPC-Agent-Go 提供两种多 Agent 协作模式,对应两种不同的组织形态:
type Mode int
const (
ModeCoordinator Mode = iota // 有中心调度者
ModeSwarm // 去中心化
)
Coordinator 模式 —— “经理分活”
┌──────────────┐
│ Coordinator │ ← 看全局,决定谁做什么
│ Agent │
└──┬───┬───┬───┘
│ │ │
┌───────┘ │ └───────┐
↓ ↓ ↓
┌────────┐ ┌────────┐ ┌────────┐
│Research│ │ Writer │ │Reviewer│ ← 各干各的
│ Agent │ │ Agent │ │ Agent │
└────────┘ └────────┘ └────────┘
Swarm 模式 —— “同事间直接交接”
┌────────┐ handoff ┌────────┐ handoff ┌────────┐
│Research│ ─────────→ │ Writer │ ─────────→ │Reviewer│
│ Agent │ │ Agent │ │ Agent │
└────────┘ └────────┘ └────────┘
↑ │
└──────────── handoff(返工)──────────────┘
4.3 Coordinator 模式详解
核心机制:把 Agent 变成工具
Coordinator 模式的实现非常巧妙:它把每个 member Agent 包装成一个”工具”,注入到 Coordinator Agent 的工具列表中。
func New(coordinator Agent, members []Agent, opts ...Option) *Team {
team := &Team{
coordinator: coordinator,
members: members,
mode: ModeCoordinator,
}
// 关键操作:把每个 member 包装为 AgentTool
agentTools := make([]tool.Tool, len(members))
for i, member := range members {
agentTools[i] = NewAgentTool(member)
}
// 把 AgentTools 注入 Coordinator 的工具列表
coordinator.AddTools(agentTools...)
return team
}
这意味着什么? Coordinator Agent 在执行 ReAct 循环时,LLM 看到的”工具列表”里不只有搜索、代码执行这些工具——还有”调用研究员 Agent”“调用写手 Agent”这些”Agent 工具”。LLM 可以像调工具一样调其他 Agent。
日常类比:经理的”工具”不只是 Excel 和 PPT——还有”指派小王去调研”“让小李写报告”。在 Coordinator 模式下,其他 Agent 就是 Coordinator 的”人力工具”。
执行流程
1. 用户任务到达 Team
2. Team 把任务交给 Coordinator Agent
3. Coordinator 进入 ReAct 循环:
- Think: "这个任务需要先调研,再写报告"
- Act: 调用 AgentTool("research_agent", "调研 AI 趋势")
→ Research Agent 执行完成,返回调研结果
- Observe: 收到调研结果
- Think: "调研结果不错,交给写手写报告"
- Act: 调用 AgentTool("writer_agent", "基于以下调研写报告: ...")
→ Writer Agent 执行完成,返回报告
- Observe: 收到报告
- Final Answer: 返回报告给用户
适用场景
- 任务分解需要全局视野(Coordinator 能看到所有 member 的能力描述)
- 子任务之间有依赖关系(先调研再写作)
- 需要结果汇总(Coordinator 最后整合多个 member 的输出)
代价
- 多一层 LLM 调用开销(Coordinator 自身也需要调 LLM 做决策)
- Coordinator 成为单点瓶颈(所有决策都经过它)
- Coordinator 的 system prompt 需要精心设计(要让它知道什么时候该委派、委派给谁)
4.3.5 Coordinator 的 Prompt Engineering
Coordinator 的 system prompt 质量直接决定了整个 Team 的表现。一个差的 prompt 会导致 Coordinator “独揽大权”(什么都自己做,不委派)或”乱派活”(把任务交给不合适的 Agent)。
System Prompt 设计模板
你是一个任务协调器。你的唯一职责是分析任务并委派给合适的团队成员。
## 你的团队成员
- **researcher**: 互联网信息研究员。能搜索最新信息、整理资料、验证来源。
适用:需要最新数据的调研、事实核查。不适用:写作、代码。
- **writer**: 专业写手。能写报告、文章、邮件。
适用:需要产出文字内容。不适用:搜索、数据分析。
- **coder**: 软件工程师。能写代码、调试、做技术方案。
适用:编程任务。不适用:非技术类写作。
## 工作原则
1. 你自己不执行任何具体任务。你只做分解和委派。
2. 每次委派时,给出清晰的子任务描述和期望输出格式。
3. 收到成员输出后,判断质量是否达标。不达标可要求重做。
4. 所有子任务完成后,整合输出给用户。
## 禁止
- 禁止自己搜索、写代码、写文章(你没有这些能力)
- 禁止跳过成员直接给最终答案
- 禁止一次给多个成员派活(除非确定任务完全独立)
Member 描述写法的好坏对比
// 差的描述 → Coordinator 无法准确判断该派谁
badAgent := llmagent.New(
llmagent.WithName("agent1"),
llmagent.WithDescription("一个助手"), // 毫无区分度
)
// 好的描述 → 五要素:身份/能力/适用/不适用/格式
goodAgent := llmagent.New(
llmagent.WithName("security_reviewer"),
llmagent.WithDescription(`安全审查专家。
能力:检测SQL注入、XSS、CSRF等安全漏洞,审查认证和授权逻辑。
适用:代码安全审查、安全方案评审。
不适用:性能优化、代码风格、业务逻辑审查。
输入:代码片段或PR diff。输出:漏洞清单+修复建议。`),
)
防止 Coordinator 独揽大权的三个技巧
// 技巧1:不给 Coordinator 任何普通工具
coordinator := llmagent.New(
llmagent.WithName("coordinator"),
llmagent.WithTools(), // 空工具列表!只有框架自动注入的 AgentTools
)
// 技巧2:prompt 中强约束
// "你没有搜索/编程/分析能力。试图自己做一定会出错。"
// 技巧3:低 MaxSteps 限制思考时间
coordinator := llmagent.New(
llmagent.WithMaxSteps(15), // 约5次委派机会
llmagent.WithTemperature(0.1), // 低温度 → 决策稳定
)
4.4 Swarm 模式详解
核心机制:Agent 间直接握手
Swarm 模式的设计灵感来自 OpenAI 的 Swarm 论文——没有中心调度者,Agent 自行决定”做完之后交给谁继续”。
func NewSwarm(entryName string, members []Agent, opts ...Option) *Team {
team := &Team{
entryName: entryName,
members: members,
mode: ModeSwarm,
}
// 关键操作:让每个 member 知道所有其他 members
wireSwarmRoster(team)
// wireSwarmRoster 做的事:
// 对每个 member,注入 transfer_to_agent 工具 + 所有同事信息
return team
}
每个 Agent 都获得了一个特殊工具 transfer_to_agent——当 Agent 判断”我这部分做完了,该交给别人了”,它调用这个工具指定下一个 Agent。
执行流程
1. 用户任务到达 Team
2. Team 从 entryName 指定的 Agent 开始执行
3. Research Agent 进入 ReAct 循环:
- Think: "用户要一篇报告,我先搜索资料"
- Act: 调用 search_tool("AI 趋势 2026")
- Observe: 搜索结果
- Think: "资料够了,该交给写手了"
- Act: 调用 transfer_to_agent("writer_agent", "基于以下资料写报告: ...")
→ 控制权转移给 Writer Agent
4. Writer Agent 进入 ReAct 循环:
- Think: "收到资料,开始写报告"
- ... 写完 ...
- Think: "报告写好了,需要审核"
- Act: 调用 transfer_to_agent("reviewer_agent", "请审核这份报告: ...")
→ 控制权转移给 Reviewer Agent
5. Reviewer Agent 执行:
- Think: "报告质量不错"
- Final Answer: "报告审核通过" → 整个 Swarm 结束
Swarm Runtime 的安全机制
Swarm 的去中心化特性带来了一些风险——如果 Agent 之间互相推诿怎么办?team/runtime.go(705 行)实现了多重安全机制:
type SwarmConfig struct {
MaxHandoffs int // 最大交接次数(防止无限循环)
NodeTimeout time.Duration // 单个 Agent 执行超时
RepetitiveHandoffWindow int // 重复交接检测窗口
}
| 安全机制 | 防范的风险 | 实现方式 |
|---|---|---|
| MaxHandoffs | Agent 互相推诿形成死循环 | 超过次数强制终止 |
| NodeTimeout | 某个 Agent 执行过久卡住 | 超时强制中断 |
| RepetitiveHandoffWindow | A→B→A→B 循环交接 | 检测短窗口内重复模式 |
| OnTransfer 回调 | 自定义交接策略 | 允许拦截/修改/拒绝交接 |
跨请求状态恢复
Swarm 模式有一个特殊需求:用户的下一条消息应该继续上次离开的那个 Agent。
// Swarm 在 session 中记录当前活跃的 Agent
const swarmActiveAgentKey = "swarm_active_agent:teamName"
// 新请求到达时,从 session 读取上次的活跃 Agent
func (t *Team) runSwarm(ctx, inv) {
activeAgent := inv.Session.Get(swarmActiveAgentKey)
if activeAgent == "" {
activeAgent = t.entryName // 首次请求从入口开始
}
// 从 activeAgent 继续执行
}
适用场景
- 工作流是线性或近线性的(A→B→C)
- 每个 Agent 能自行判断”该交给谁了”
- 不需要全局视野做决策
- 要求低延迟(省了 Coordinator 的一轮 LLM 调用)
代价
- 每个 Agent 需要”认识”所有同事(SubAgents 注入所有 member)
- 交接决策分散——如果某个 Agent 判断失误把活交错了人,没有全局仲裁者
- Debug 困难——执行路径是动态的,取决于运行时每个 Agent 的决策
4.4.5 Swarm 状态传递与上下文继承
Swarm 中 Agent 之间的 handoff 不仅是”控制权转移”——还涉及”上下文如何传递”。
Handoff 消息传递机制
// transfer_to_agent 工具的内部实现(简化)
func transferToAgent(ctx context.Context, params map[string]any) (string, error) {
targetName := params["agent_name"].(string)
message := params["message"].(string) // 交接说明
inv := GetInvocationFromContext(ctx)
inv.HandoffMessage = message
inv.HandoffTarget = targetName
// 当前 Agent 的对话历史默认传递给下一个 Agent
return "transfer_successful", nil
}
默认行为:完整上下文继承。Agent A 交接给 Agent B 时,B 能看到 A 的全部对话历史。
上下文膨胀问题与裁剪策略
完整继承会导致每次 handoff 上下文都增长:A 用 3000 tokens → B 继承 3000 + 自己 2000 = 5000 → C 继承 5000 + 自己 2000 = 7000。几轮之后接近 context window 上限。
// 四种裁剪策略
// 策略1:只传 handoff 消息(最激进)
team.WithContextInheritance(team.InheritNone)
// 下游只看到 transfer_to_agent 的 message 参数
// 策略2:滑动窗口(保留最近N条)
team.WithContextInheritance(team.InheritLastN(5))
// 策略3:LLM 摘要压缩
team.WithContextInheritance(team.InheritSummary)
// handoff 时自动调 LLM 压缩上下文,再传给下游
// 策略4:自定义裁剪
team.WithContextTransformer(func(msgs []*Message, from, to string) []*Message {
// 只保留 system + tool_result + 最后一条 assistant
var kept []*Message
for _, m := range msgs {
if m.Role == "system" || m.Role == "tool" {
kept = append(kept, m)
}
}
kept = append(kept, msgs[len(msgs)-1])
return kept
})
共享状态 vs 局部状态
// Team 级共享状态:所有 Agent 可读写
inv.State.Values["research_data"] = data // A 写,B 读
// Agent 局部状态:通过 Agent 内部字段
type WriterAgent struct {
draftCount int // 只有 Writer 自己用
}
// 设计建议:
// - 下游需要的数据 → 写入 State(共享)
// - 内部执行细节 → 保留在局部
// - handoff 消息 → 描述"期望什么",而非"dump所有数据"
4.5 Coordinator vs Swarm:选择指南
| 维度 | Coordinator | Swarm |
|---|---|---|
| 控制方式 | 中心化(经理决策) | 去中心化(同事自行交接) |
| 全局视野 | 有(Coordinator 看到所有 member 描述) | 无(每个 Agent 只看到自己的上下文) |
| LLM 调用开销 | 多一层(Coordinator 本身调 LLM) | 省一层 |
| 延迟 | 较高 | 较低 |
| 适合的任务类型 | 复杂分解(不确定谁该做什么) | 明确流程(知道顺序就是 A→B→C) |
| Debug 友好度 | 高(看 Coordinator 的决策记录) | 低(要追踪多次 handoff) |
| 容错 | Coordinator 是单点 | 任一 Agent 出错只影响当前步 |
| 典型场景 | 客服系统(根据问题类型分配专员) | 代码审查流水线(写→review→merge) |
选择口诀:
- 不确定谁该做什么 → Coordinator(让 LLM 帮你决定)
- 明确知道流程顺序 → Swarm(省去决策开销)
- 需要结果汇总 → Coordinator(它天然是汇总者)
- 要求低延迟 → Swarm(少一轮 LLM 调用)
4.6 双引擎混用:Team + StateGraph
tRPC-Agent-Go 独有的一个能力:Team 和 StateGraph 可以混用。
方式一:Team 作为 StateGraph 的一个节点
// 定义一个多 Agent Team
researchTeam := team.New(coordinator, []*Agent{searcher, analyzer})
// 把 Team 作为图的一个节点
graph := NewStateGraph(schema)
graph.AddNode("collect_requirements", requirementsFn)
graph.AddNode("research", researchTeam.AsNode()) // Team 当节点用
graph.AddNode("generate_report", reportFn)
graph.AddEdge("collect_requirements", "research")
graph.AddEdge("research", "generate_report")
方式二:StateGraph 作为某个 Agent 的内部实现
// GraphAgent 内部用 StateGraph 实现复杂逻辑
type ComplexResearchAgent struct {
graph *StateGraph
}
func (a *ComplexResearchAgent) Run(ctx, inv) (<-chan *Event, error) {
return a.graph.Execute(ctx, inv.State)
}
// 然后把这个 Agent 作为 Team 的一个 member
team := team.NewSwarm("complex_research", []Agent{complexResearchAgent, writerAgent})
这种灵活性在其他框架中看不到:LangGraph 只有图、CrewAI 只有角色、LangChain 只有链。tRPC-Agent 允许你在同一个系统中混合使用图编排和多 Agent 协作——根据不同层级的复杂度选择最合适的工具。
4.7 与其他框架的多 Agent 对比
| 框架 | 中心调度 | 去中心化 | Agent 间通信 | 动态 Agent |
|---|---|---|---|---|
| tRPC-Agent | Coordinator | Swarm(handoff) | RPC + 事件流 | ✓ |
| LangGraph | 父图路由子图 | ✗ | Channel State | ✗ |
| CrewAI | Hierarchical Manager | ✗ | Task 输出传递 | ✗ |
| Agno | Team coordinate | Team route/broadcast | 函数调用 | ✓ |
| AutoGen | ✓ | 对话轮转 | 消息传递 | ✓ |
tRPC-Agent 的 Swarm 是独有的。LangGraph 和 CrewAI 都没有”Agent 自行决定交给谁”的去中心化模式。AutoGen 有对话轮转,但那是”大家轮流说话”,不是”做完自己的部分后精确交接给特定人”。
4.7.5 多 Agent 调试与可观测性
多 Agent 系统最大的工程挑战不是”让它跑起来”——而是”出了问题时能快速定位原因”。
链路追踪
tRPC-Agent 自动为 Team 执行生成嵌套的 trace span:
[Team.Run] ─── 总 span (trace_id: abc123)
├── [Coordinator.Think] ─── 第1步思考
│ span: {duration: 2.1s, tokens: 450}
├── [Coordinator.ToolCall: research_agent] ─── 委派
│ └── [ResearchAgent.Run] ─── 子 Agent span
│ ├── [LLM.Call] ─── {model: gpt-4o, tokens_in: 800, tokens_out: 200}
│ ├── [Tool: web_search] ─── {duration: 1.5s, result_size: 2KB}
│ └── [LLM.Call] ─── 第2轮
├── [Coordinator.Think] ─── 再次思考
└── [Coordinator.ToolCall: writer_agent] ─── 委派写手
└── [WriterAgent.Run]
└── [LLM.Call] ─── {model: gpt-4o, tokens_in: 1200, tokens_out: 800}
通过 Jaeger 或 Grafana Tempo 查看这个 trace,你可以立刻看到:哪个 Agent 最慢?哪步 token 消耗最多?哪个工具调用失败了?
Handoff 日志
Swarm 模式需要专门记录 handoff 链路,否则 debug 时无法还原执行路径:
// Swarm Runtime 自动记录 handoff 日志
type HandoffLog struct {
Timestamp time.Time
FromAgent string
ToAgent string
Message string // handoff 时传递的消息
Reason string // 为什么交接(从 LLM 思考中提取)
StepCount int // 当前 Agent 执行了几步后交接
TokensUsed int // 当前 Agent 消耗的 token
}
// 查看完整 handoff 链
// [14:30:01] triage_agent → security_reviewer: "检测到疑似SQL注入" (3步, 450 tokens)
// [14:30:08] security_reviewer → perf_reviewer: "安全问题已记录" (5步, 1200 tokens)
// [14:30:15] perf_reviewer → style_reviewer: "无性能问题" (2步, 300 tokens)
// [14:30:20] style_reviewer → END: "审查完成" (4步, 600 tokens)
性能瓶颈定位
多 Agent 系统的性能瓶颈通常在三个地方:
瓶颈1:Coordinator 决策过慢
症状:Coordinator 的 Think span 时间过长(>5秒)
原因:Coordinator prompt 太复杂 / member 太多 / 模型选错
修复:精简 prompt / 减少 member / 换更快模型
瓶颈2:某个 Member Agent 执行过慢
症状:某个 Agent 的 Run span 明显比其他 Agent 长
原因:工具调用慢 / LLM 响应慢 / 循环步数过多
修复:优化工具 / 降低 MaxSteps / 换模型
瓶颈3:Handoff 次数过多(Swarm)
症状:总 handoff 次数接近 MaxHandoffs
原因:Agent 职责划分不清 / handoff 消息写得不好
修复:重新设计 Agent 职责边界 / 改善 prompt
常见故障模式
| 故障 | 现象 | 根因 | 修复 |
|---|---|---|---|
| 死循环 | A→B→A→B 反复交接 | A 和 B 对任务理解矛盾 | 明确各自完成条件 |
| 独揽大权 | Coordinator 不委派,自己做 | Coordinator 有普通工具 | 去掉普通工具 |
| 乱派活 | 安全问题派给风格审查 | Member 描述不清晰 | 加”不适用”声明 |
| 信息丢失 | 下游 Agent 说”我不知道你在说什么” | 上下文裁剪过度 | 调整继承策略 |
| Token 爆炸 | 执行到一半报 context length exceeded | 完整继承 + 多次 handoff | 用摘要策略 |
4.8 实战示例:构建一个代码审查 Agent Team
假设你要构建一个自动代码审查系统,流程是:
- 接收 PR diff
- 安全审查(检查 SQL 注入、XSS 等)
- 性能审查(检查 N+1 查询、内存泄漏)
- 代码风格审查
- 汇总审查意见
方案一:Coordinator 模式
coordinator := NewLLMAgent("review_manager",
WithSystemPrompt("你是代码审查经理。分析 PR 内容,分配给合适的审查员。"),
)
securityReviewer := NewLLMAgent("security_reviewer",
WithTools(sqlInjectionChecker, xssScanner),
WithSystemPrompt("你是安全专家。只关注安全漏洞。"),
)
perfReviewer := NewLLMAgent("perf_reviewer",
WithTools(queryAnalyzer, memoryProfiler),
WithSystemPrompt("你是性能专家。只关注性能问题。"),
)
styleReviewer := NewLLMAgent("style_reviewer",
WithTools(linter, formatterCheck),
WithSystemPrompt("你是代码风格审查员。只关注规范。"),
)
team := team.New(coordinator, []Agent{securityReviewer, perfReviewer, styleReviewer})
方案二:Swarm 模式
securityReviewer := NewLLMAgent("security_reviewer",
WithTools(sqlInjectionChecker, xssScanner, transferTool),
WithSystemPrompt("你是安全专家。审查完安全问题后,转交给性能审查员。"),
)
perfReviewer := NewLLMAgent("perf_reviewer",
WithTools(queryAnalyzer, memoryProfiler, transferTool),
WithSystemPrompt("你是性能专家。审查完性能后,转交给风格审查员。"),
)
styleReviewer := NewLLMAgent("style_reviewer",
WithTools(linter, formatterCheck),
WithSystemPrompt("你是风格审查员。审查完后给出最终汇总意见。"),
)
team := team.NewSwarm("security_reviewer",
[]Agent{securityReviewer, perfReviewer, styleReviewer},
WithMaxHandoffs(5),
)
哪个更好? 这个场景下 Swarm 更合适——因为审查顺序是确定的(安全→性能→风格),不需要 Coordinator 做动态决策。Swarm 省去了 Coordinator 的 LLM 调用开销。
但如果需求变成”根据 PR 的内容决定是否需要安全审查”(有些 PR 只是改了文档,不需要安全审查),那 Coordinator 更合适——它能根据 PR 内容动态选择需要哪些审查员。
4.9 嵌套 Team 与递归协作
到目前为止我们看到的都是”一层” Team——一个 Coordinator/Swarm 管理一组 Member Agent。但真实的复杂系统往往需要多层嵌套:Team of Teams。
Team of Teams 的动机
日常类比:大公司不是”CEO 管 100 个人”,而是”CEO 管 5 个 VP,每个 VP 管 3 个总监,每个总监管 10 个员工”。Agent 系统也一样——当 member 超过 5-7 个时,单层 Coordinator 的决策质量会下降(工具列表太长,LLM 选错的概率增大)。解法:分层。
三级组织架构案例
假设你要构建一个”全栈软件开发 Team”:
// ===== 第三级:基础 Agent =====
frontendCoder := NewLLMAgent("frontend_coder", ...)
backendCoder := NewLLMAgent("backend_coder", ...)
dbDesigner := NewLLMAgent("db_designer", ...)
uiDesigner := NewLLMAgent("ui_designer", ...)
securityAuditor := NewLLMAgent("security_auditor", ...)
perfTester := NewLLMAgent("perf_tester", ...)
techWriter := NewLLMAgent("tech_writer", ...)
// ===== 第二级:子 Team(各自有 Coordinator)=====
devTeam := team.New(
NewLLMAgent("dev_lead", WithSystemPrompt("你是开发组长,管理前端后端和数据库")),
[]Agent{frontendCoder, backendCoder, dbDesigner},
)
qaTeam := team.New(
NewLLMAgent("qa_lead", WithSystemPrompt("你是QA组长,管理安全和性能测试")),
[]Agent{securityAuditor, perfTester},
)
designTeam := team.NewSwarm("ui_designer",
[]Agent{uiDesigner, techWriter}, // 设计→文档,线性流程用 Swarm
)
// ===== 第一级:顶层 Team =====
// 注意:子 Team 作为 Member 注入顶层 Coordinator
topTeam := team.New(
NewLLMAgent("project_manager", WithSystemPrompt(`
你是项目经理。你管理三个组:
- dev_team: 开发组(前端、后端、数据库)
- qa_team: 质量组(安全审查、性能测试)
- design_team: 设计组(UI设计、技术文档)
按项目需求委派给合适的组。
`)),
[]Agent{devTeam.AsAgent(), qaTeam.AsAgent(), designTeam.AsAgent()},
)
递归深度控制
嵌套 Team 有一个危险:递归深度失控。如果不限制,顶层 Coordinator 可能把任务层层下放,而每一层都消耗 LLM 调用。
// 递归深度限制
topTeam := team.New(coordinator, subTeams,
team.WithMaxDepth(3), // 最多3层嵌套
team.WithTotalMaxSteps(50), // 所有层级加起来最多50步
team.WithTotalTokenBudget(100000), // 总 token 预算
)
递归深度的经验法则:
| 层数 | 典型场景 | LLM 调用开销 |
|---|---|---|
| 1层 | 3-5个Agent的简单协作 | 1次 Coordinator + N次 Member |
| 2层 | 10-20个Agent的部门协作 | 1+3次 Coordinator + N次 Member |
| 3层 | 大型系统 | 不推荐超过3层(开销指数增长) |
事件流合并
嵌套 Team 的事件流如何向上汇报?每一层 Team 都产出事件,顶层需要合并所有子 Team 的事件流:
// 事件流的嵌套结构
// 顶层 Runner 收到的事件流:
//
// [team:top] thinking: "需要开发组先做"
// [team:top] tool_call: dev_team("实现用户注册功能")
// [team:dev] thinking: "需要后端和数据库"
// [team:dev] tool_call: backend_coder("写注册API")
// [agent:backend_coder] thinking: "用 REST 设计"
// [agent:backend_coder] tool_call: code_write(...)
// [agent:backend_coder] final_response: "API 实现完成"
// [team:dev] tool_call: db_designer("设计用户表")
// [agent:db_designer] final_response: "表结构设计完成"
// [team:dev] final_response: "开发完成"
// [team:top] tool_call: qa_team("测试注册功能")
// ...
// 事件过滤:用户通常只需要看顶层事件
topTeam := team.New(coordinator, subTeams,
team.WithEventFilter(func(ev *event.Event) bool {
return ev.Depth <= 1 // 只向上传播前两层的事件
}),
)
嵌套 Team 的设计原则
- 每层不超过 5-7 个 member:超过后 Coordinator 的选择准确率显著下降
- 同一层的 member 职责不重叠:重叠会导致 Coordinator 随机选择
- 子 Team 对外表现为单个 Agent:通过
AsAgent()方法封装,上层不需要知道内部结构 - 总 token 预算向下分配:顶层设总预算,每层按比例分配给子 Team
- 事件流向上汇聚时做过滤:用户只看高层事件,详细事件存到 trace 中供调试
思考题
Q1(模式选择):你要做一个”智能客服”系统,有售前、售后、技术支持、投诉处理四个 Agent。用户上来可能问任何类型的问题。你选 Coordinator 还是 Swarm?为什么?
Q2(安全机制):Swarm 的 MaxHandoffs 设为 5。如果一个真实场景确实需要 8 次交接才能完成任务,你怎么办?简单调大 MaxHandoffs 有什么风险?
Q3(设计扩展):当前 Swarm 的 transfer_to_agent 只能转交给一个 Agent。如果你需要”同时转交给两个 Agent 并行执行”呢?你会怎么扩展这个设计?
Q4(对比思考):CrewAI 的 Hierarchical 模式和 tRPC-Agent 的 Coordinator 模式看起来很像——都有一个 Manager/Coordinator 分配任务。但它们有一个关键区别。你能找出来吗?(提示:看 CrewAI 的 Manager 是怎么创建的)
Q5(实战判断):你的 Agent Team 有 3 个 member,用 Coordinator 模式。线上监控发现 Coordinator 经常把活分错人(比如把安全问题交给了风格审查员)。你觉得最可能的原因是什么?怎么修?
上一章:第三章 ReAct 循环与 LLM Flow 深度解析
返回目录:Agent 框架深度导读系列