核心摘要
当单个 AI Agent 面对复杂任务时,上下文窗口限制、工具过载、缺乏专业化分工等问题会显著降低效果。多智能体系统通过角色专业化、并行处理和协作涌现,突破单一 Agent 的能力天花板。本文深入解析 Eino 框架支持的三种核心协作模式——Router(意图路由)、Supervisor(管理者)和 Swarm(对等协作),并通过一个多 Agent 代码审查系统展示实战落地方案。
目录
- 核心要点
- 为什么需要多 Agent
- Router 模式:意图路由
- Supervisor 模式:管理者协调
- Swarm 模式:对等协作
- Agent 作为 Tool:层级组合
- 状态共享与隔离
- 三种模式对比
- 实战:多 Agent 代码审查系统
- 最佳实践
- 常见问题
- 总结
- 相关资源
核心要点
- Router 模式:一个路由 Agent 对用户意图分类,将请求分发到领域专家 Agent,延迟低、结构清晰
- Supervisor 模式:管理者 Agent 负责规划、派发、汇总,Worker Agent 执行具体子任务并汇报结果
- Swarm 模式:无中心协调器,Agent 之间对等通信、自主移交,适合开放式协作
- Agent as Tool:任何编译后的 Graph 或 Agent 都可以暴露为 Tool,实现层级化的 Agent 架构
- 状态策略:共享事实(via context)、隔离推理(独立对话历史),平衡一致性与自主性
为什么需要多 Agent
单个 Agent 在面对真实世界的复杂任务时存在明确的能力天花板:
| 限制因素 | 表现 | 多 Agent 解决方案 |
|---|---|---|
| 上下文窗口 | 信息超载导致遗忘关键细节 | 每个 Agent 只处理相关子集 |
| 工具过载 | 工具过多时选择准确率下降 | 每个 Agent 只绑定必要工具 |
| 缺乏专业化 | 通才表现不如领域专家 | 角色专业化的 System Prompt |
| 串行执行 | 复杂任务耗时过长 | 子任务并行处理 |
| 单点失败 | 一次错误影响全局 | 独立推理、局部失败不扩散 |
这些限制在 Eino 框架中通过 Graph 编排 + Agent 组合得到系统性解决。在 前一篇文章 中我们构建了单 Agent 应用,现在让我们进入多 Agent 的世界。
Router 模式:意图路由
Router 模式是最简单的多 Agent 协作——一个路由器根据用户输入的意图分类,将请求转发到对应的专家 Agent。
架构图
核心实现
package main
import (
"context"
"github.com/cloudwego/eino/compose"
"github.com/cloudwego/eino/schema"
)
func buildRouterGraph(ctx context.Context) (*compose.Runnable[string, *schema.Message], error) {
graph := compose.NewGraph[string, *schema.Message]()
// 添加路由节点:对意图进行分类
graph.AddLambdaNode("router", compose.InvokableLambda(func(ctx context.Context, input string) (string, error) {
// 调用轻量模型快速分类意图
classification, err := classifyIntent(ctx, input)
if err != nil {
return "general", nil // fallback
}
return classification, nil
}))
// 添加专家 Agent 节点
graph.AddChatModelNode("code_agent", codeModel, &compose.ChatModelNodeConfig{
SystemPrompt: "你是一位资深 Go 开发专家,专注于代码编写、调试和优化。",
})
graph.AddChatModelNode("data_agent", dataModel, &compose.ChatModelNodeConfig{
SystemPrompt: "你是一位数据分析专家,擅长 SQL、数据可视化和统计分析。",
})
graph.AddChatModelNode("general_agent", generalModel, &compose.ChatModelNodeConfig{
SystemPrompt: "你是一位通用助手,擅长回答日常问题。",
})
// 设置边和分支
graph.AddEdge(compose.START, "router")
graph.AddBranch("router", compose.NewBranch(func(ctx context.Context, intent string) (string, error) {
switch intent {
case "code":
return "code_agent", nil
case "data":
return "data_agent", nil
default:
return "general_agent", nil
}
}))
graph.AddEdge("code_agent", compose.END)
graph.AddEdge("data_agent", compose.END)
graph.AddEdge("general_agent", compose.END)
return graph.Compile(ctx)
}
适用场景
- 客服系统:根据问题类型路由到售前/售后/技术支持
- IDE 助手:区分代码生成、文档查询、项目配置等请求
- 数据平台:分流 SQL 查询、报表生成、异常分析等任务
Supervisor 模式:管理者协调
Supervisor 模式引入一个"管理者" Agent,负责理解任务全局、制定计划、分配子任务给 Worker Agent,并汇总最终结果。
架构图
核心实现
package main
import (
"context"
"fmt"
"github.com/cloudwego/eino-ext/devops/adk"
"github.com/cloudwego/eino/components/tool"
"github.com/cloudwego/eino/schema"
)
// workerAsTool 将一个 Agent 包装为 Tool,供 Supervisor 调用
func workerAsTool(name, description string, agent *adk.ChatModelAgent) tool.BaseTool {
return tool.NewTool(
name,
description,
func(ctx context.Context, input string) (string, error) {
messages := []*schema.Message{
schema.UserMessage(input),
}
result, err := agent.Generate(ctx, messages)
if err != nil {
return "", fmt.Errorf("worker %s failed: %w", name, err)
}
return result.Content, nil
},
)
}
func buildSupervisorAgent(ctx context.Context) (*adk.ChatModelAgent, error) {
// 创建 Worker Agent
researcher, _ := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
Model: researchModel,
SystemPrompt: "你是一位技术研究员,负责收集和整理技术资料。输出结构化的调研报告。",
})
writer, _ := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
Model: writerModel,
SystemPrompt: "你是一位技术写作专家,根据调研资料撰写高质量技术文章。",
})
reviewer, _ := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
Model: reviewModel,
SystemPrompt: "你是一位严格的技术审稿人,检查文章的准确性、完整性和可读性。",
})
// 创建 Supervisor Agent,将 Worker 作为 Tool
supervisor, err := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
Model: supervisorModel,
Tools: []tool.BaseTool{
workerAsTool("researcher", "调用研究员收集技术资料,输入为研究主题", researcher),
workerAsTool("writer", "调用写作专家撰写文章,输入为写作要求和参考资料", writer),
workerAsTool("reviewer", "调用审稿人审核文章,输入为待审核文章内容", reviewer),
},
SystemPrompt: `你是一位项目经理,负责协调团队完成技术内容生产任务。
工作流程:
1. 分析用户需求,拆解为子任务
2. 先调用 researcher 收集资料
3. 将资料交给 writer 撰写初稿
4. 让 reviewer 审核初稿
5. 如有问题,让 writer 修改
6. 汇总最终结果返回`,
MaxSteps: 10,
})
return supervisor, err
}
适用场景
- 内容生产:调研 → 写作 → 审核 → 定稿的完整流水线
- 代码审查:分析 → 审查 → 修复的迭代循环
- 项目规划:需求分析 → 方案设计 → 风险评估的多维度评审
Swarm 模式:对等协作
Swarm 模式(灵感来源于 OpenAI Swarm 概念)中,Agent 之间是对等关系,没有中心协调器。每个 Agent 拥有自主决策权,可以将对话控制权移交(handoff)给另一个 Agent。
核心概念
- 无中心化:没有固定的"管理者",任何 Agent 都可以接管
- Handoff 机制:当前 Agent 判断某个问题超出自己能力范围时,主动移交给更合适的 Agent
- 上下文传递:移交时携带必要的对话上下文
核心实现
package main
import (
"context"
"github.com/cloudwego/eino/components/tool"
"github.com/cloudwego/eino-ext/devops/adk"
)
// HandoffResult 表示一次移交操作的结果
type HandoffResult struct {
TargetAgent string
Context string
}
// buildSwarmAgents 构建对等协作的 Agent 集合
func buildSwarmAgents(ctx context.Context) (map[string]*adk.ChatModelAgent, error) {
agents := make(map[string]*adk.ChatModelAgent)
// 销售 Agent
salesAgent, _ := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
Model: model,
SystemPrompt: `你是销售顾问。处理产品咨询和购买相关问题。
如果用户问技术问题,调用 handoff_to_tech 移交给技术支持。
如果用户要退款,调用 handoff_to_refund 移交给退款专员。`,
Tools: []tool.BaseTool{
makeHandoffTool("handoff_to_tech", "移交给技术支持", "tech"),
makeHandoffTool("handoff_to_refund", "移交给退款专员", "refund"),
},
})
// 技术支持 Agent
techAgent, _ := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
Model: model,
SystemPrompt: `你是技术支持工程师。解决技术问题和 bug 报告。
如果用户想购买或升级,调用 handoff_to_sales 移交给销售。`,
Tools: []tool.BaseTool{
makeHandoffTool("handoff_to_sales", "移交给销售顾问", "sales"),
},
})
// 退款 Agent
refundAgent, _ := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
Model: model,
SystemPrompt: "你是退款专员。处理退款申请和订单问题。",
Tools: []tool.BaseTool{
makeHandoffTool("handoff_to_sales", "移交给销售顾问", "sales"),
},
})
agents["sales"] = salesAgent
agents["tech"] = techAgent
agents["refund"] = refundAgent
return agents, nil
}
// runSwarm 运行 Swarm 对话循环
func runSwarm(ctx context.Context, agents map[string]*adk.ChatModelAgent, input string) (string, error) {
currentAgent := "sales" // 默认入口
currentInput := input
for i := 0; i < 5; i++ { // 最多 5 次 handoff
agent := agents[currentAgent]
result, err := agent.Generate(ctx, []*schema.Message{
schema.UserMessage(currentInput),
})
if err != nil {
return "", err
}
// 检查是否发生 handoff
if handoff := extractHandoff(result); handoff != nil {
currentAgent = handoff.TargetAgent
currentInput = handoff.Context
continue
}
return result.Content, nil
}
return "", fmt.Errorf("exceeded max handoff limit")
}
适用场景
- 客服系统:不同技能的客服代表之间灵活转接
- 多角色对话:模拟多个角色的讨论和辩论
- 工作流不确定的场景:无法预先定义执行路径
Agent 作为 Tool:层级组合
Eino 中,任何编译后的 Graph 或 Agent 都可以暴露为 Tool,这是构建层级化多 Agent 架构的关键模式。
// 将一个完整的 Agent 系统封装为 Tool
func agentAsTool(name, desc string, runnable *compose.Runnable[string, string]) tool.BaseTool {
return tool.NewTool(name, desc, func(ctx context.Context, input string) (string, error) {
return runnable.Invoke(ctx, input)
})
}
// 构建层级结构:顶层 Agent 调用子系统
func buildHierarchicalSystem(ctx context.Context) (*adk.ChatModelAgent, error) {
// 子系统 1:代码分析 Agent Graph
codeAnalysisGraph := buildCodeAnalysisGraph(ctx)
codeAnalysisTool := agentAsTool(
"code_analysis",
"分析代码质量、复杂度和潜在问题,输入为代码片段",
codeAnalysisGraph,
)
// 子系统 2:文档生成 Agent Graph
docGenGraph := buildDocGenGraph(ctx)
docGenTool := agentAsTool(
"doc_generation",
"为代码生成技术文档,输入为代码和上下文描述",
docGenGraph,
)
// 顶层协调 Agent
coordinator, err := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
Model: model,
Tools: []tool.BaseTool{codeAnalysisTool, docGenTool},
SystemPrompt: "你是开发助手,可以调用代码分析和文档生成子系统来帮助用户。",
})
return coordinator, err
}
层级组合的优势:
- 子系统可以独立开发、测试和迭代
- 顶层 Agent 的 prompt 保持简洁,只需要理解 Tool 的接口
- 支持按需加载,不用的子系统不占用资源
状态共享与隔离
多 Agent 协作中,状态管理是核心挑战。Eino 提供灵活的策略:
| 策略 | 实现方式 | 适用场景 | 优缺点 |
|---|---|---|---|
| Context 传递 | context.WithValue |
只读共享事实 | 简单直接,但只支持不可变数据 |
| 外部存储 | Redis / 数据库 | 可变共享状态 | 支持并发读写,但引入外部依赖 |
| 消息传递 | Tool 调用的输入输出 | Agent 间通信 | 解耦好,但有 token 开销 |
| 独立历史 | 每个 Agent 独立维护 | 对话记忆 | 推理不干扰,但无法共享经验 |
最佳实践:共享事实,隔离推理
// 通过 Context 共享只读的任务上下文
type TaskContext struct {
TaskID string
UserID string
Constraints []string
}
func withTaskContext(ctx context.Context, tc *TaskContext) context.Context {
return context.WithValue(ctx, taskContextKey, tc)
}
// 每个 Agent 独立维护自己的对话历史
type AgentState struct {
History []*schema.Message
// 仅存储该 Agent 的推理过程
}
三种模式对比
| 维度 | Router | Supervisor | Swarm |
|---|---|---|---|
| 拓扑结构 | 星形(一对多) | 层级(管理者-工人) | 网状(对等) |
| 协调方式 | 静态分类 | 动态规划 | 自主移交 |
| 延迟 | 低(一次路由) | 中高(多轮交互) | 不确定 |
| 适用复杂度 | 低-中 | 中-高 | 高 |
| 容错性 | 单子 Agent 失败可 fallback | Supervisor 可重新分配 | 天然隔离 |
| 实现难度 | 简单 | 中等 | 较高 |
| 典型场景 | 意图分发、客服路由 | 项目管理、内容生产 | 角色扮演、灵活协商 |
实战:多 Agent 代码审查系统
结合以上模式,构建一个包含 Planner(规划者)、Reviewer(审查者)和 Fixer(修复者)的代码审查系统。
package main
import (
"context"
"fmt"
"github.com/cloudwego/eino-ext/devops/adk"
"github.com/cloudwego/eino/components/tool"
)
func buildCodeReviewSystem(ctx context.Context) (*adk.ChatModelAgent, error) {
// Reviewer Agent:专注于代码质量审查
reviewer, _ := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
Model: reviewModel,
SystemPrompt: `你是代码审查专家。分析以下维度:
- 逻辑正确性
- 性能隐患
- 安全漏洞
- 代码规范
输出格式:[severity] file:line - description`,
})
// Fixer Agent:根据审查意见生成修复代码
fixer, _ := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
Model: fixerModel,
SystemPrompt: `你是代码修复专家。根据审查意见生成修复补丁。
输出标准的 unified diff 格式。确保修复不引入新问题。`,
})
// Planner (Supervisor):协调整个审查流程
planner, err := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
Model: plannerModel,
Tools: []tool.BaseTool{
workerAsTool("reviewer", "对代码进行质量审查,输入为待审代码", reviewer),
workerAsTool("fixer", "根据审查意见修复代码,输入为审查意见和原始代码", fixer),
},
SystemPrompt: `你是代码审查项目的协调者。工作流程:
1. 接收用户提交的代码变更
2. 调用 reviewer 进行审查
3. 如果发现问题,调用 fixer 生成修复
4. 再次调用 reviewer 验证修复
5. 输出最终的审查报告和修复建议
如果 reviewer 连续两次都没有发现问题,直接输出通过。`,
MaxSteps: 8,
})
return planner, err
}
// 使用示例
func main() {
ctx := context.Background()
system, err := buildCodeReviewSystem(ctx)
if err != nil {
panic(err)
}
codeChange := `
func processOrder(order *Order) error {
db.Save(order)
sendEmail(order.UserEmail, "Order confirmed")
chargePayment(order.Amount)
return nil
}
`
result, _ := system.Generate(ctx, []*schema.Message{
schema.UserMessage(fmt.Sprintf("请审查以下代码变更:\n%s", codeChange)),
})
fmt.Println(result.Content)
}
这个系统体现了 Supervisor 模式的核心特征:Planner 负责流程控制,Reviewer 和 Fixer 作为专业 Worker 执行具体任务。通过 MaxSteps 限制避免无限循环。
开发调试时,可以使用 JSON 格式化工具 来检查 Agent 间传递的结构化数据,或使用 JSON to Go 快速生成数据结构定义。
最佳实践
1. 从单 Agent 开始,按需拆分
不要过早引入多 Agent。先用单 Agent 验证核心逻辑,当观察到明确的性能瓶颈或能力限制时再拆分。
2. 控制嵌套深度
Agent as Tool 的嵌套不宜超过 3 层。每增加一层,token 消耗和延迟都会倍增。
3. 为每个 Agent 设定清晰边界
每个 Agent 的 System Prompt 应明确定义:职责范围、输入/输出格式、何时移交。
4. 实现优雅降级
// Router 中设置 fallback
if confidence < 0.6 {
return "general_agent", nil // 不确定时走通用 Agent
}
5. 利用 Callback 做全链路观测
agent.WithCallbacks(
callbacks.OnStart(func(ctx context.Context, info *callbacks.RunInfo) {
log.Printf("[%s] started with input: %s", info.Name, info.Input)
}),
callbacks.OnEnd(func(ctx context.Context, info *callbacks.RunInfo) {
log.Printf("[%s] completed in %v", info.Name, info.Duration)
}),
)
常见问题
Q: Router、Supervisor 和 Swarm 三种模式应该如何选择?
Router 适合意图明确、可分类的请求分发场景;Supervisor 适合需要规划、分配、汇总的复杂任务;Swarm 适合需要灵活协商、无法预定义流程的开放式协作。选择依据是任务是否可预先分类、是否需要中心协调。
Q: Agent as Tool 模式有什么限制?
主要限制:1)Tool 调用是同步阻塞的,子 Agent 执行耗时会阻塞父 Agent;2)返回值是字符串,复杂结构需序列化;3)嵌套过深导致 token 消耗激增。建议嵌套不超过 3 层。
Q: 多 Agent 之间的状态如何共享?
推荐策略:通过 context.Context 传递只读的共享事实,每个 Agent 维护独立的对话历史。需要持久化的中间结果可使用外部存储。核心原则:共享事实,隔离推理。
Q: Eino 的多 Agent 系统支持流式输出吗?
支持。Supervisor 的最终汇总节点可流式输出;Router 模式中被路由到的子 Agent 可以 Stream 模式返回。Graph 编排引擎自动处理 Stream 传递。
Q: 多 Agent 系统如何调试和观测?
Eino 内置 Callback 机制,为每个 Agent 设置唯一 RunInfo.Name,配合 OpenTelemetry 实现分布式追踪,可在可观测平台上看到完整的多 Agent 调用链。
总结
多智能体协作是突破单 Agent 能力限制的核心路径。Eino 通过 Graph 编排、Agent as Tool 和灵活的状态管理机制,原生支持三种协作模式:
- Router:低延迟的意图分发,适合明确分类的场景
- Supervisor:有序的任务规划与执行,适合复杂多步骤任务
- Swarm:灵活的对等协作,适合开放式、不确定性高的场景
选择模式时,从最简单的 Router 开始评估,当任务需要多轮规划时升级到 Supervisor,当流程无法预定义时考虑 Swarm。在 Eino 系列第一篇 中,我们介绍了框架全貌;本文进一步展示了如何用这些编排能力构建生产级的多 Agent 系统。