Agents 201:多智能体编排实战指南
一、概述
1. 简介
A. 是什么
多智能体系统是指由多个专门化的 AI 智能体协同工作,共同完成复杂任务的系统架构。每个智能体专注于特定领域,通过编排模式实现高效协作。
B. 为什么学
单智能体系统存在明显限制:上下文窗口有限、决策混乱、调试困难。多智能体系统通过专业化分工解决这些问题,类似于组建一个高效团队。
C. 学完能做什么
- 设计并实现多智能体协作系统
- 选择合适的编排模式和通信策略
- 优化生产环境中的性能和成本
- 避免常见的反模式陷阱
2. 前置知识
A. 必备技能
- 了解单智能体的基本概念和实现
- 熟悉异步编程和并发处理
- 掌握基本的系统设计原则
B. 推荐知识
- 了解 LLM 的 token 消耗机制
- 熟悉事件驱动架构
- 具备生产环境部署经验
二、为什么需要多智能体
1. 单智能体的局限性
单智能体系统很快会遇到瓶颈:上下文窗口填满、决策变得混乱、调试变得不可能。这些问题随着任务复杂度增加而放大。
2. 多智能体的优势
A. 专业化
每个智能体专精一个领域,而不是在所有事情上都平庸。例如,一个智能体专注代码分析,另一个专注文档生成。
B. 并行处理
多个智能体可以同时在独立的子任务上工作。这种并行性显著提升系统效率。
C. 可维护性
当系统出现故障时,可以准确定位需要修复的智能体。问题范围被明确隔离。
D. 可扩展性
通过添加新的智能体来增加新功能,而不需要重写整个系统。
3. 权衡考量
协调开销是主要代价。智能体需要通信、共享状态、避免相互干扰。如果处理不当,只会构建一个更昂贵的失败模式。
三、三种编排模式
1. 监督者模式(集中控制)
A. 模式描述
一个监督者智能体协调整个工作。它接收任务、分解为子任务、路由到工作智能体、验证输出、综合最终响应。
B. 适用场景
- 任务可以清晰分解为子任务
- 需要可审计性和推理透明度
- 质量控制比速度更重要
- 管理 3-8 个工作智能体
C. 架构示意
graph TD
User[用户请求] --> Supervisor[监督者智能体]
Supervisor -->|分解| Decompose[任务分解]
Supervisor -->|路由| Route[任务路由]
Supervisor -->|监控| Monitor[进度监控]
Supervisor -->|验证| Validate[输出验证]
Supervisor -->|综合| Synthesize[结果综合]
Supervisor --> Worker1[工作智能体 1]
Supervisor --> Worker2[工作智能体 2]
Supervisor --> Worker3[工作智能体 3]D. 实现示例
AI Hedge Fund 示例使用这种模式。四个专门的分析师(基本面、投资组合、风险、技术分析)并行运行,监督者负责协调。
// 监督者协调并行分析
const analyses = await Promise.all([
fundamentalAgent.analyze(ticker),
portfolioAgent.analyze(ticker),
riskAgent.analyze(ticker),
technicalAgent.analyze(ticker)
]);
// 监督者综合结果
const report = await supervisorAgent.synthesize(analyses);E. 潜在问题
监督者成为瓶颈。每个决策都通过一个智能体,这意味着协调步骤需要串行处理,即使工作可以并行进行。token 成本随协调层级增加。
2. 群体模式(点对点)
A. 模式描述
没有中央控制器。智能体直接通信、交换信息、围绕任务自组织。类似于蚁群而不是组织架构图。
B. 适用场景
- 任务需要多个视角
- 没有清晰的串行步骤分解
- 实时响应性很重要
- 智能体需要相互反应
C. 架构示意
graph LR
A[智能体 A] <--> B[智能体 B]
A <--> C[智能体 C]
B <--> C
B <--> D[智能体 D]
C <--> DD. 实现示例
SmartTravel 多智能体示例展示了点对点协调。六个智能体(目的地探索、航班搜索、酒店搜索、餐饮、行程、预算)通过共享状态交换信息。
// 每个智能体读取和写入共享状态
await destinationAgent.explore(state);
await flightAgent.search(state); // 使用前一个智能体的目的地
await hotelAgent.search(state); // 使用目的地和日期
// 智能体更新共享状态
class TravelState {
destination: string;
flightOptions: Flight[];
hotelOptions: Hotel[];
// ...跨所有智能体共享
}E. 潜在问题
突发行为难以预测。没有协调者,智能体可能重复工作、创建无限循环或收敛到次优解。调试非常困难,因为要追踪信息在网格中的流动,而不是树中。
3. 层级模式(多级控制)
A. 模式描述
监督者模式的递归版本。顶层智能体管理中层智能体,中层智能体管理工作智能体。三层或更多层级。
B. 适用场景
- 任务太复杂不适合扁平监督
- 不同领域需要不同的管理策略
- 协调 10+ 个智能体
- 需要战略和战术控制
C. 架构示意
graph TD
Top[顶层监督者] --> MidA[中层 A]
Top --> MidB[中层 B]
MidA --> W1[工作智能体 1-3]
MidB --> W2[工作智能体 4-6]D. 实现示例
NVIDIA 文档生成器示例使用层级分解:
// 顶层:文档编排器
const topLevel = {
analyze: async (repo) => {
// 委托给分析团队
const analysis = await analysisTeam.execute(repo);
// 委托给文档团队
const docs = await docsTeam.execute(analysis);
// 委托给验证团队
return await validationTeam.execute(docs);
}
};
// 中层:分析团队监督特定分析器
const analysisTeam = {
codeAnalyzer: new Agent(),
archDiagrammer: new Agent(),
testGenerator: new Agent()
};E. 潜在问题
token 成本激增。每一层都增加协调开销。三层层级、每层 5 个智能体,协调成本可能轻松超过 50K tokens。只有当扁平模式真正无法处理复杂度时才值得。
四、智能体通信策略
1. 共享状态(最常用)
A. 策略描述
所有智能体从共享状态对象读取和写入。更改对所有人可见。
B. 实现方式
interface SharedState {
task: string;
results: Map<string, any>;
currentStep: string;
}
// 智能体 A 写入状态
state.results.set('analysis', analysisResult);
// 智能体 B 读取状态
const analysis = state.results.get('analysis');C. 优势
- 实现简单
- 易于调试(只需检查状态)
- 无消息传递复杂性
D. 劣势
- 智能体同时写入时可能出现竞态条件
- 智能体上下文之间无隔离
- 状态无限制增长,需要定期清理
E. 使用建议
从这里开始。大多数智能体系统应该使用共享状态,直到遇到它无法解决的具体问题。
2. 消息传递(事件驱动)
A. 策略描述
智能体相互发送消息。没有直接状态共享。
B. 实现方式
// 智能体 A 发布事件
eventBus.publish('analysis.complete', {
ticker: 'AAPL',
analysis: result
});
// 智能体 B 订阅事件
eventBus.subscribe('analysis.complete', async (event) => {
await portfolioAgent.process(event.analysis);
});C. 优势
- 智能体之间松耦合
- 自然适合异步工作
- 易于添加新智能体而不改变现有智能体
D. 劣势
- 更难调试(需要追踪消息流)
- 可能出现消息循环
- 需要基础设施(事件总线、队列)
E. 使用建议
当智能体真正独立且不应该相互了解时使用。或者需要在服务间进行异步处理时。
3. 移交机制(显式控制转移)
A. 策略描述
一个智能体显式地将控制权移交给另一个智能体,通常携带上下文。
B. 实现方式
class Agent {
async handoff(targetAgent: Agent, context: Context) {
// 准备移交上下文
const handoffContext = {
previousAgent: this.name,
taskContext: context,
timestamp: Date.now()
};
// 转移控制权
return await targetAgent.execute(handoffContext);
}
}C. 优势
- 清晰的控制流
- 易于审计谁做了什么
- 跨智能体保持上下文
D. 劣势
- 智能体之间紧密耦合
- 默认串行处理
- 每次转换都有移交开销
E. 使用建议
当任务必须按特定顺序发生且上下文必须流过链时使用。
五、多智能体系统的内存架构
1. 会话内存
A. 模式描述
每个智能体交互都是一个会话。会话有隔离的状态,在完成时合并回共享内存。
B. 实现方式
class MemoryManager {
async createSession(agentId: string): Session {
return {
id: generateId(),
agentId,
localState: {},
sharedSnapshot: this.getSnapshot()
};
}
async commitSession(session: Session) {
// 将本地更改合并回共享状态
this.merge(session.localState);
}
}C. 使用场景
需要读取共享上下文但进行隔离更改的并行智能体。常见于工作智能体独立运行的监督者模式。
2. 窗口内存(对话上下文)
A. 模式描述
保留所有智能体最近交换的滑动窗口。最旧的条目被压缩或丢弃。
B. 实现方式
class WindowMemory {
private window: Message[] = [];
private maxSize = 50;
add(message: Message) {
this.window.push(message);
if (this.window.length > this.maxSize) {
// 压缩最旧的三分之一
this.compressOldest();
}
}
compressOldest() {
const toCompress = this.window.slice(0, this.maxSize / 3);
const summary = await this.summarize(toCompress);
this.window = [summary, ...this.window.slice(this.maxSize / 3)];
}
}C. 使用场景
上下文重要但不能保留所有内容的长运行智能体对话。RAG 应用使用这种模式。
3. 情景内存(跨智能体学习)
A. 模式描述
存储特定智能体之间的交互历史。使智能体能够从过去的协调中学习。
B. 实现方式
interface Episode {
agentA: string;
agentB: string;
interaction: Interaction;
outcome: 'success' | 'failure';
learnings: string[];
}
// 智能体在协调前查询过去的交互
const pastEpisodes = await memory.query({
agents: ['supervisor', 'riskAnalyst'],
outcome: 'success'
});C. 使用场景
频繁协作且可以从过去有效的方法中学习的智能体。
六、生产环境考虑
1. Token 经济学
A. 成本挑战
多智能体系统快速消耗 token。四个智能体协调任务,成本可能比单个智能体高 10 倍。
B. 典型监督系统的成本分解
- 监督者分解:1K tokens
- 4 个工作智能体:每个 3K tokens(总计 12K)
- 监督者综合:2K tokens
- 总计:每个任务 15K tokens
相比之下,单个智能体完成相同任务只需 4K tokens。你在为协调付费。
C. 优化策略
- 缓存监督者指令:不要每次都重新生成任务分解
- 压缩工作智能体输出:工作智能体不需要返回散文,结构化数据即可
- 并行执行:4 个智能体串行运行的成本与并行相同,但时间长 4 倍
- 延迟智能体激活:只在需要输出时才调用智能体
2. 延迟管理
A. 延迟挑战
多个智能体意味着多个 LLM 调用。每次调用增加 2-5 秒。串行处理会破坏用户体验。
B. 延迟计算
- 1 个智能体:3 秒
- 4 个智能体(串行):12 秒
- 4 个智能体(并行):3-4 秒
C. 优化建议
始终并行化独立工作。AI Hedge Fund 示例通过并行运行四个分析师而不是串行,节省了 9 秒。
3. 错误传播
A. 失败模式
- 毒药丸:一个智能体返回垃圾数据,破坏下游智能体
- 死锁:智能体在循环依赖中相互等待
- 资源耗尽:并行智能体都尝试使用相同的速率限制 API
- 级联故障:监督者失败,所有工作智能体成为孤儿
B. 防御策略
- 每层超时:智能体必须在有界时间内完成
- 熔断器:N 次失败后停止调用有问题的智能体
- 优雅降级:系统应该能在部分智能体的情况下工作
- 隔离状态:工作智能体失败不应破坏共享状态
4. 监控和可观察性
A. 必需指标
- 每个智能体的成功率:哪些智能体失败?
- 协调开销:多少时间用于协调 vs 实际工作?
- 按智能体的 token 消耗:成本从哪里来?
- 智能体交互模式:哪些智能体与哪些智能体通信?
B. 示例实现
class ObservableAgent {
async execute(task: Task): Result {
const span = tracer.startSpan('agent.execute', {
agentId: this.id,
taskType: task.type
});
try {
const result = await this.process(task);
span.setStatus({ code: SpanStatusCode.OK });
return result;
} catch (error) {
span.setStatus({
code: SpanStatusCode.ERROR,
message: error.message
});
throw error;
} finally {
span.end();
}
}
}七、常见反模式
1. 过度协调
不要让智能体在不需要时协调。如果智能体在独立任务上工作,让它们独立运行。
2. 万能智能体
不要让一个智能体做所有事情。多智能体的全部意义是专业化。
3. 全部同步
不要在必须时阻塞等待智能体。大多数协调可以是异步的。
4. 忽略成本
不要在不跟踪 token 使用的情况下部署多智能体系统。你会收到惊喜账单。
5. 无备用方案
不要假设所有智能体都能工作。构建降级模式。
八、模式选择指南
1. 使用监督者模式当
- 需要可审计性
- 任务清晰分解
- 3-8 个专门智能体
- 质量 > 速度
2. 使用群体模式当
- 需要多个视角
- 没有清晰的任务分解
- 实时响应性关键
- 智能体可以自组织
3. 使用层级模式当
- 管理 10+ 个智能体
- 需要多层抽象
- 需要战略和战术控制
- token 成本可接受
4. 使用单智能体当
- 任务足够简单
- 一个专业领域足够
- 最小化成本很重要
- 还不确定
九、入门建议
1. 从简单开始
选择可能工作的最简单模式。大多数团队应该从监督者模式开始:
- 构建一个有能力的智能体
- 识别它在哪里挣扎(通常是专业化或并行工作)
- 将其提取到第二个智能体
- 添加监督者来协调
- 迭代
2. 循序渐进
不要从第一天就构建复杂的多智能体系统。构建一个智能体,看看它在哪里失效,添加另一个智能体。重复。
3. 实践建议
在构建十个智能体的系统之前,先构建一个可靠地使用两个智能体的系统。