深入浅出 LangGraph —— 第12章:多Agent系统架构

📖 本章学习目标

  • ✅ 理解多 Agent 系统相比单 Agent 的核心优势
  • ✅ 掌握监督者-工作者(Supervisor-Worker)架构模式
  • ✅ 学会使用 createReactAgent 快速创建工作者 Agent
  • ✅ 理解 Agent 间的通信与任务传递机制
  • ✅ 能够设计并实现一个协同工作的多 Agent 团队
  • ✅ 避免常见的多Agent设计陷阱

一、为什么需要多 Agent

1、单 Agent 的瓶颈

当任务越来越复杂,单个 Agent 会遇到以下瓶颈:

  • 上下文窗口有限:单个 Agent 处理长任务时历史消息超限
  • 工具太多:绑定几十个工具后,LLM 调用准确率下降
  • 专业化不足:一个 Agent 什么都做,什么都做得不精
  • 并行能力弱:单 Agent 只能串行处理任务
  • 维护困难:单一Agent逻辑复杂,难以调试和维护

多Agent就是处理以上问题的解决方案。
多Agent团队
用户请求
监督者Agent

任务分解
搜索Agent
分析Agent
写作Agent
结果汇总
高质量完成

2、多 Agent 的优势

搜索任务
分析任务
写作任务
🧑‍💼 监督者 Agent

任务规划与分配
🔍 搜索 Agent

专注信息检索
📊 分析 Agent

专注数据分析
✍️ 写作 Agent

专注内容生成
📋 最终结果

维度 单 Agent 多 Agent
专业性 通才,样样略懂 专家,各司其职
并行能力 串行执行 并行分工
上下文管理 单一上下文 各 Agent 独立上下文
可扩展性 难以扩展 按需增加专家 Agent
可靠性 单点故障 容错性强
维护性 复杂难维护 模块化易维护

实际应用场景:

  • 📰 新闻生成:搜索→分析→写作→审核
  • 💻 代码开发:需求分析→架构设计→编码→测试
  • 🔬 学术研究:文献检索→数据分析→论文撰写
  • 🏥 医疗诊断:症状分析→检查建议→治疗方案

二、监督者-工作者架构

1、架构设计

最经典的多 Agent 模式:一个监督者(Supervisor) 负责规划和任务分配,多个工作者(Worker)Agent 各负责专门的任务。

工作流程:

  1. 监督者接收用户请求
  2. 监督者分析任务,决定下一步
  3. 路由到对应的工作者Agent
  4. 工作者执行任务,返回结果
  5. 回到监督者,继续决策
  6. 直到任务完成(FINISH)

2、使用 createReactAgent 创建工作者

LangGraph 提供了 createReactAgent 预构建函数,快速创建 ReAct 工作者 Agent:

步骤1:导入依赖
typescript 复制代码
import * as dotenv from 'dotenv';
dotenv.config();

import { createReactAgent } from '@langchain/langgraph/prebuilt';
import { ChatOpenAI } from '@langchain/openai';
import { tool } from '@langchain/core/tools';
import { z } from 'zod';
import { HumanMessage, SystemMessage } from '@langchain/core/messages';

const model = new ChatOpenAI({ model: 'gpt-4o-mini' });
步骤2:创建搜索Agent
typescript 复制代码
// 搜索工作者的工具
const webSearchTool = tool(
  async ({ query }) => `搜索"${query}":找到了相关结果...`,
  { 
    name: 'web_search', 
    description: '搜索互联网信息', 
    schema: z.object({ query: z.string() }) 
  }
);

// 创建搜索 Agent
const searchAgent = createReactAgent({
  llm: model,
  tools: [webSearchTool],
  stateModifier: new SystemMessage(
    '你是专业的信息检索助手,擅长搜索并整理网络信息。请返回详细的搜索结果。'
  ),
});
步骤3:创建分析Agent
typescript 复制代码
// 分析 Agent
const codeAnalysisTool = tool(
  async ({ code }) => `代码分析结果:发现3个潜在问题...`,
  { 
    name: 'analyze_code', 
    description: '分析代码质量和潜在问题', 
    schema: z.object({ code: z.string() }) 
  }
);

const analysisAgent = createReactAgent({
  llm: model,
  tools: [codeAnalysisTool],
  stateModifier: new SystemMessage('你是专业的代码审查助手,擅长发现代码问题和提供改进建议。'),
});

每个工作者有专门的工具和角色定义,在设计工作者时,通常遵循以下原则:

  1. 单一职责:每个Agent只做一件事
  2. 专业化工具:只绑定相关的工具
  3. 明确角色:SystemMessage清晰定义职责

3、实现监督者

定义路由Schema
typescript 复制代码
import { 
  Annotation, StateGraph, MessagesAnnotation, 
  END, START 
} from '@langchain/langgraph';
import { AIMessage, BaseMessage } from '@langchain/core/messages';
import { z } from 'zod';

// 工作者列表
const workers = ['search_agent', 'analysis_agent', 'writer_agent'] as const;
type Worker = typeof workers[number];

// 监督者的路由决策 Schema
const SupervisorDecision = z.object({
  next: z.enum([...workers, 'FINISH']).describe('下一个要执行的工作者,FINISH 表示任务完成'),
  reason: z.string().describe('选择原因'),
  instructions: z.string().describe('给工作者的具体指令'),
});
  • 代码解读:
  • workers:定义所有可用的工作者名称
  • SupervisorDecision:约束监督者的输出格式
  • next:下一步路由目标(工作者或FINISH)
  • reason:决策原因,便于调试
  • instructions:给工作者的具体指令
实现监督者节点
typescript 复制代码
// 监督者节点:决定下一步派谁去做
async function supervisorNode(state: typeof MessagesAnnotation.State) {
  const supervisorModel = model.withStructuredOutput(SupervisorDecision);
  
  const decision = await supervisorModel.invoke([
    new SystemMessage(
      `你是团队监督者,负责将任务分配给以下工作者:\n` +
      `- search_agent:负责信息搜索\n` +
      `- analysis_agent:负责数据分析\n` +
      `- writer_agent:负责内容写作\n` +
      `根据对话历史决定下一步,任务完成时回复 FINISH。`
    ),
    ...state.messages,
  ]);
  
  return {
    messages: [
      new AIMessage({
        content: `[监督者] → ${decision.next}: ${decision.instructions}`,
      }),
    ],
    next: decision.next,
  };
}

代码解读:

  • withStructuredOutput:约束监督者只能返回合法的工作者名称
  • 监督者消息包含**"给工作者的指令"**,工作者会看到这条消息
  • next 字段用于路由到对应的工作者或结束

监督者的职责:

  • 理解用户需求
  • 分解任务步骤
  • 分配合适的工作者
  • 判断任务是否完成

提示词技巧:

  • 明确列出所有工作者及其职责
  • 说明终止条件(FINISH)
  • 要求给出决策原因

4、组装多 Agent 图

扩展State
typescript 复制代码
import { messagesStateReducer } from '@langchain/langgraph';

// 扩展 State 添加路由字段
const MultiAgentState = Annotation.Root({
  messages: Annotation({
    reducer: messagesStateReducer,
    default: () => [],
  }),
  next: Annotation<Worker | 'FINISH'>(),
});
创建工作者节点包装器
typescript 复制代码
import { CompiledStateGraph } from '@langchain/langgraph';

// 工作者节点:调用对应的 Agent,将结果加入消息历史
async function makeWorkerNode(agentGraph: CompiledStateGraph, agentName: string) {
  return async (state: typeof MultiAgentState.State) => {
    const result = await agentGraph.invoke({ messages: state.messages });
    const lastMsg = result.messages[result.messages.length - 1];
    return {
      messages: [
        new AIMessage({ content: `[${agentName}] ${lastMsg.content}` })
      ],
    };
  };
}

makeWorkerNode是工厂函数,用于创建工作者节点。

  • agentGraph:编译好的工作者Agent(createReactAgent返回)
  • agentName:工作者名称,用于标识消息来源
  • 调用工作者Agent,获取结果
  • 将结果包装后添加到messages

工作流程:

  1. 接收当前messages
  2. 调用工作者Agent处理
  3. 获取工作者的最后一条消息
  4. 添加前缀标识(如[搜索助手])
  5. 返回更新后的messages
组装完整图
typescript 复制代码
const multiAgentGraph = new StateGraph(MultiAgentState)
  .addNode('supervisor', supervisorNode)
  .addNode('search_agent', await makeWorkerNode(searchAgent, '搜索助手'))
  .addNode('analysis_agent', await makeWorkerNode(analysisAgent, '分析助手'))
  .addEdge('__start__', 'supervisor')
  // 监督者根据 next 字段路由
  .addConditionalEdges('supervisor', (state) => state.next, {
    search_agent: 'search_agent',
    analysis_agent: 'analysis_agent',
    writer_agent: 'writer_agent',
    FINISH: '__end__',
  })
  // 所有工作者执行后都回到监督者
  .addEdge('search_agent', 'supervisor')
  .addEdge('analysis_agent', 'supervisor')
  .compile();

每个工作者完成后都回到 supervisor,让监督者决定下一步,这形成了**"监督者→工作者→监督者→..."** 的循环,直到 FINISH。state.next 是监督者设置的路由目标,条件边据此分发。

关键点:

  • 监督者是中心节点
  • 工作者之间不直接通信
  • 所有决策由监督者做出
  • 通过next字段控制路由

多Agent协作流程图:
search_agent
analysis_agent
writer_agent
FINISH
start
监督者节点

决策下一步
next字段?
搜索Agent

执行搜索
分析Agent

执行分析
写作Agent

生成内容
end


三、运行多 Agent 系统

typescript 复制代码
async function runMultiAgentSystem() {
  const result = await multiAgentGraph.invoke({
    messages: [
      new HumanMessage(
        '请帮我:1.搜索LangGraph的最新版本信息,2.分析其主要特性,3.写一篇介绍文章'
      ),
    ],
    next: 'supervisor', // 初始路由到监督者
  });
  
  // 打印所有消息(展示协作过程)
  for (const msg of result.messages) {
    if (msg instanceof AIMessage) {
      console.log(msg.content);
      console.log('---');
    }
  }
}

await runMultiAgentSystem();
// 输出示例:
// [监督者] → search_agent: 请先搜索LangGraph最新版本信息
// ---
// [搜索助手] LangGraph最新版本是0.2.0,主要更新包括...
// ---
// [监督者] → analysis_agent: 请分析这些特性的价值
// ---
// [分析助手] 这些特性提升了开发效率,主要体现在...
// ---
// [监督者] → writer_agent: 请基于以上信息写介绍文章
// ---
// [写作助手] LangGraph是一个强大的Agent框架...
// ---
// [监督者] → FINISH: 任务已完成
// ---

invoke时传入初始消息和next字段,next:'supervisor'表示从监督者开始。整个过程全自动,监督者智能分配任务。 最终result.messages包含完整的协作历史。

调试技巧:

  • 打印所有messages查看协作过程
  • 使用streamEvents观察每一步
  • 检查next字段的决策是否正确

四、对等协作架构(Peer-to-Peer)

1、适用场景

当 Agent 之间需要双向通信时(如辩论、互相审阅),使用对等架构:
反馈
修订
批准
Agent A

提出方案
Agent B

审阅方案
完成

典型应用:

  • 🗣️ 辩论系统:正反方交替发言
  • 👀 代码审阅:开发者与审阅者交互
  • ✍️ 内容创作:作者与编辑协作
  • 🎯 方案设计:提案者与评审者迭代

2、实现辩论Agent

typescript 复制代码
// 提案 Agent
async function proposerNode(state: typeof MessagesAnnotation.State) {
  const response = await model.invoke([
    new SystemMessage('你是方案提出者,根据需求给出具体解决方案,简洁有力'),
    ...state.messages,
  ]);
  return { messages: [response] };
}

// 审阅 Agent
async function reviewerNode(state: typeof MessagesAnnotation.State) {
  const response = await model.invoke([
    new SystemMessage('你是严格的方案审阅者,指出问题和改进点,如果方案足够好回复"APPROVED"'),
    ...state.messages,
  ]);
  return { messages: [response] };
}

// 路由:审阅结果决定继续还是结束
function reviewRouter(state: typeof MessagesAnnotation.State): string {
  const lastMsg = state.messages[state.messages.length - 1];
  return (lastMsg.content as string).includes('APPROVED') ? '__end__' : 'proposer';
}

const collaborativeGraph = new StateGraph(MessagesAnnotation)
  .addNode('proposer', proposerNode)
  .addNode('reviewer', reviewerNode)
  .addEdge('__start__', 'proposer')
  .addEdge('proposer', 'reviewer')
  .addConditionalEdges('reviewer', reviewRouter)
  .compile({
    recursionLimit: 10
  });

执行流程:

  1. proposer提出方案
  2. reviewer审阅
  3. 如果不满意,回到proposer修改
  4. 如果满意(APPROVED),结束

注意事项:

  • 必须设置recursionLimit防止无限循环
  • APPROVED关键词要明确

对比两种架构:

特性 Supervisor-Worker Peer-to-Peer
控制方式 集中式(监督者) 分布式(平等)
通信模式 星型拓扑 网状拓扑
适用场景 任务分解与分配 双向协作与迭代
复杂度 中等 简单
扩展性 好(易添加工作者) 一般

五、最佳实践和踩坑指南

💡 实践 1:防止无限循环

typescript 复制代码
// 添加最大循环次数限制
const MAX_ITERATIONS = 10;

const safeMultiAgentGraph = new StateGraph(MultiAgentState)
  // ... nodes and edges ...
  .compile({
    recursionLimit: MAX_ITERATIONS, // 超过限制自动停止
  });

原因:多Agent系统容易陷入无限循环,必须设置安全限制。

💡 实践 2:监督者的提示词要明确

typescript 复制代码
// ✅ 明确的终止条件
const goodSupervisorPrompt = `
任务完成标准:
- 搜索结果已获取 AND
- 内容已撰写 AND
- 用户问题已完整回答
满足以上所有条件时,回复 FINISH。
`;

// ❌ 模糊的终止条件
const badSupervisorPrompt = `
你觉得差不多了就结束吧。
`;

原因:模糊的终止条件会导致监督者无法判断何时结束。

💡 实践 3:工作者上下文管理

typescript 复制代码
// ✅ 只传相关消息给工作者
async function smartWorkerNode(agentGraph: CompiledStateGraph, agentName: string) {
  return async (state: typeof MultiAgentState.State) => {
    // 只传最近5条消息,避免Token超限
    const relevantMessages = state.messages.slice(-5);
    const result = await agentGraph.invoke({ messages: relevantMessages });
    // ...
  };
}

// ❌ 传递全部历史
const badWorkerNode = async (state) => {
  const result = await agentGraph.invoke({ messages: state.messages }); // 可能超限
};

原因:工作者不需要完整历史,只传相关内容可节省Token。

⚠️ 常见陷阱

问题 现象 解决方案
监督者无限循环 图永远不返回 FINISH 设置 recursionLimit,优化终止条件提示词
工作者上下文太长 Token 超限报错 传给工作者的 messages 只传相关的,不传全部历史
Agent 输出格式不一致 监督者无法解析工作者结果 为每个工作者定义明确的输出格式规范
并行工作者写入同一字段 状态合并冲突 为工作者的输出设计追加 Reducer
工作者之间直接通信 绕过监督者,逻辑混乱 所有通信经过监督者协调
忘记初始化next字段 第一次路由失败 invoke时必须传入next:'supervisor'

📝 本章小结

核心知识点回顾

知识点 关键要点 应用场景
createReactAgent 快速创建 ReAct 工作者 工作者 Agent 的快速搭建
Supervisor 模式 中央调度 + 专家分工 复杂多步骤任务
Peer-to-Peer 模式 Agent 间双向协作 辩论、审阅、协商
recursionLimit 防止无限循环 所有多 Agent 系统
状态转换 工作者结果汇入messages 多Agent通信
路由控制 next字段决定下一步 Supervisor决策

🎯 动手练习

练习 1:研究团队

  • 目标:构建"规划者+搜索者+写作者"三 Agent 团队
  • 要求 :
    1. 监督者分配任务
    2. 结果汇总后由写作者输出最终报告
    3. 支持多轮迭代优化
  • 验收标准 :
    • 给定研究主题,自动生成完整的研究报告
    • 报告结构清晰,内容准确
    • 协作过程可追溯

练习 2:辩论 Agent

  • 目标:两个 Agent 对一个观点进行正反方辩论(3轮)
  • 要求 :
    1. 双方各持立场
    2. 每轮针对对方观点反驳
    3. 最后由第三个 Agent 裁判得出结论
  • 验收标准 :
    • 3轮辩论后输出裁判结论
    • 辩论逻辑清晰,有理有据
    • 不超过最大轮数限制

练习 3:代码审查团队

  • 目标:4个 Agent 分别负责安全审查、性能审查、可读性审查、最终汇总
  • 要求 :
    1. 前三个并行执行
    2. 最后汇总输出综合评分
    3. 每个Agent有专门的检查清单
  • 验收标准 :
    • 给定代码,输出四个维度的审查报告
    • 每个维度有具体问题和建议
    • 综合评分客观公正

练习 4:动态工作者注册

  • 目标:实现工作者动态注册和注销
  • 要求 :
    1. 监督者能感知可用工作者列表
    2. 运行时可以添加新工作者
    3. 工作者可以主动退出
  • 验收标准 :
    • 新增工作者无需修改监督者代码
    • 工作者列表动态更新
    • 系统稳定运行

📚 延伸阅读


下一章:第13章 ------ Functional API:函数式工作流

相关推荐
Web3VentureView3 小时前
SYNBO走进以太坊中国高校行复旦大学专场:链接Web3下一代开发者
人工智能·web3·区块链·加密货币·synbo
狐狐生风3 小时前
LangChain实现简易版-----PDF 文档问答机器人
人工智能·langchain·机器人·pdf·prompt
一水鉴天3 小时前
从“AI内在机制探询”到“三重三九格人本主权智能体架构”的演进 之2 20260503 (腾讯元宝)
人工智能·架构
guslegend3 小时前
第4节:应用架构与代码组织
人工智能·大模型·ai编程
一水鉴天3 小时前
现今/现在/现代——系统设计“现”层架构 20260503 (腾讯元宝)
人工智能·架构
格林威3 小时前
工业视觉检测:两大主流异常检测开源框架深度对比(PatchCore vs SPADE)
开发语言·人工智能·深度学习·数码相机·计算机视觉·视觉检测·工业相机
天诚智能门锁3 小时前
天诚cat.1人脸公租房智能锁及管控平台助力三门县公租房管理
大数据·人工智能·物联网·智慧城市·公租房
threelab3 小时前
Three.js 3D 饼图效果 | 三维可视化 / AI 提示词
javascript·人工智能·3d
小何code3 小时前
人工智能【第11篇】K近邻算法KNN:简单有效的分类方法(长文+代码实现)
人工智能·机器学习·knn