基于LangChain的多智能体协同框架设计与实践

发布时间:2026/10/21 14:25:12
基于LangChain的多智能体协同框架设计与实践 做了这么久的大模型应用我相信很多人都会遇到同一个瓶颈单个Agent单打独斗在一两个特定任务上表现不错可一旦任务链路拉长、涉及的领域变多就开始力不从心。我去年在做某个自动化分析工具时也撞上了这堵墙——一个Agent要同时兼顾数据获取、清洗、分析、出报告结果提示词越写越臃肿工具列表越来越长上下文越塞越满最终产出质量反而下降。后来我把系统重构为多智能体协同框架基于LangChain做了一层轻量级编排层才真正把任务拆开、角色分开、上下文隔离每个Agent只干自己最擅长的事。这篇文章就把这套框架的设计思路和实现过程完整整理一遍内容包括协同模式选型、整体架构搭法、核心模块实现、四种主流模式对比以及我在实际运行中踩过的坑。不管你是刚接触Agent开发、想从单Agent往多Agent演进还是已经做过一版但觉得调度混乱、上下文串味儿这篇文章都值得你花十五分钟读完。1. 先想清楚多智能体协同到底要解决什么问题1.1 单Agent的天花板在哪里我放弃单Agent的最直接原因是上下文熵增。单Agent把所有工具、历史、任务都塞进同一个上下文窗口无关信息互相干扰指令遵循能力明显退化。我之前做过一个实验让一个Agent内置8个工具分别处理网页抓取、数据库查询、文档解析、图表绘制等简单任务没问题但任务一复杂工具选择的准确率就明显下降模型经常在一个用不着的工具上反复尝试调用token消耗很大却没有进展。还有一个问题是任务拆分的粒度。人在做复杂项目时会把工作分给不同角色大模型Agent其实也是这样。一个人既做信息收集又做数据质检又做结论输出提示词之间是互相打架的。质检角色要求严格收集角色要求广撒网这两个目标放在同一个上下文里模型会两头摇摆结果就是“既没有收集全面也没有质检严格”。1.2 多Agent不是把模型多跑几遍我接触过不少人对多Agent的第一反应是把一个大任务写成多个Prompt分别调用几次大模型不就行了这是一个典型误区。多智能体协同框架的核心不是“多个模型实例”而是“角色化的执行单元 明确的协作机制 可控的信息流转”。如果你只是顺序调用几次模型那跟一个Agent分几步执行没有本质区别反而增加了代码复杂度。真正的多智能体协同至少要包含几件事每个Agent有自己的身份定义、能力范围、上下文边界Agent之间通过某种协议交换信息系统有一个调度层决定谁在什么时候做什么全局状态被集中管理而不是散落在各个Prompt里。这套框架就是围绕这几点构建的。1.3 先定义好你的协同模式在写任何代码之前建议先想清楚一个关键问题你的场景需要哪种协同模式我后来总结出四类常见模式团队模式、监督者-工作者模式、层级模式和流水线模式。团队模式适合头脑风暴、方案比对监督者模式适合任务分解与质量把控层级模式适合跨领域的复杂系统流水线模式适合步骤强依赖的数据处理链路。这个选择特别重要因为模式直接决定了编排代码怎么写。如果一开始不做这个决策很容易把框架设计得又重又死。我自己就走过这条弯路一开始想做一个通用的编排引擎结果快两周还没跑通一个最小示例后来逼自己先固定监督者模式把流程跑通再逐步抽象速度反而快很多。2. 框架整体设计与技术选型2.1 为什么选LangChain生态必须承认多智能体框架现在的选择很多市面上有不少专门的Agent框架。但我最终选了基于LangChain来搭理由有三个。第一是生态兼容性LangChain的Agent、Tool、Memory抽象非常成熟团队之前的代码资产都基于它迁移成本最低。第二是可控性强LangChain没有强行规定你的编排模式它给的是组件而不是体系我可以按自己的需求搭建调度逻辑。第三是社区活跃遇到问题几乎都能找到参考。LangChain本身也不是银弹它的抽象层比较重文档更新快版本兼容性偶尔让人头疼。如果你的团队都是大模型应用新手我更建议直接用LangChain LangGraph的组合用状态图来定义Agent间的流转要省心得多。我的框架是在这两者之上做的二次封装对外暴露配置化接口。2.2 系统分层架构我设计的框架整体分成四层。最外层是接入层负责接收用户请求并做初步意图识别第二层是编排层负责Agent调度、协作流程控制、上下文路由第三层是执行层由若干独立Agent组成每个Agent内部有自己的提示词模板、工具集和短时记忆最底层是基础设施层包含模型服务、向量库、工具注册中心、共享状态存储。这样的分层有一个明显的好处每层都可以独立替换和扩展。比如想把某个Agent底层的模型从A换成B只需改Agent工厂里的模型配置想加一个Agent角色只需新增一个角色定义文件想优化调度策略只动编排层。这个设计思路类似后端开发里的分层架构各层只依赖接口不依赖具体实现。2.3 通信与状态设计要点多智能体调度的本质是状态流转问题。我的设计将全局状态放在一个统一存储中各Agent执行后把结果写回调度层根据全局状态决定下一步给谁派发任务。这里有一个关键点Agent之间不建议直接用自然语言互相对话而是通过结构化的消息对象来传递。如果让Agent A阅读Agent B的输出再生成回复不仅浪费token还容易造成理解漂移。实际实现中我定义了一种简单的“任务消息”结构包含消息ID、发送方、接收方、任务类型、载荷和状态字段。调度层只认这个结构不关心Agent内部怎么推理。这样做的另一个好处是便于追踪每次消息传递都会记录日志出了问题可以直接回放整个协作过程排查问题时能节省大量时间。3. 核心模块实现从零搭一个最小可跑的多智能体框架这一章是全文的重头戏按我实际开发的先后顺序来讲每个模块都给出可参考的核心代码片段。基础环境是Python 3.10以上安装LangChain及所需依赖。3.1 角色注册与Agent工厂先定义一个AgentConfig数据类用来描述一个Agent的基本信息角色名称、职责描述、使用的模型、绑定的工具列表、最大步数阈值等。然后写一个AgentFactory工厂作用是根据配置创建对应的Agent实例。为什么要做工厂模式因为项目里Agent数量会增长如果每个Agent都在业务代码里手动实例化代码会非常散乱。下面给出核心代码。注意这里的工具列表是通过字符串名称引用的实际实例在ToolRegistry里统一管理from dataclasses import dataclass, field from typing import List, Dict, Any from langchain.agents import AgentExecutor, create_openai_functions_agent from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from langchain_openai import ChatOpenAI from langchain.tools import BaseTool dataclass class AgentConfig: name: str description: str prompt: str model: str gpt-4o-mini temperature: float 0.2 tools: List[str] field(default_factorylist) max_iterations: int 10 verbose: bool True class AgentFactory: def __init__(self, tool_registry: Dict[str, BaseTool]): self.tool_registry tool_registry def create_agent(self, cfg: AgentConfig) - AgentExecutor: llm ChatOpenAI(modelcfg.model, temperaturecfg.temperature) prompt ChatPromptTemplate.from_messages([ (system, cfg.prompt), MessagesPlaceholder(variable_namechat_history), (human, {input}), MessagesPlaceholder(variable_nameagent_scratchpad) ]) agent create_openai_functions_agent(llm, [self.tool_registry[t] for t in cfg.tools], prompt) executor AgentExecutor( agentagent, tools[self.tool_registry[t] for t in cfg.tools], max_iterationscfg.max_iterations, verbosecfg.verbose, handle_parsing_errorsTrue ) return executor这里需要注意两点。第一每个Agent的system prompt要尽可能写清楚能力边界比如“你是数据分析Agent你只能处理结构化数据不负责撰写最终报告”这对防止越权行为很有用。第二max_iterations务必设置否则模型在复杂任务里很容易陷入无限循环工具调用token消耗会很夸张。3.2 工具注册表与统一调用协议多智能体框架里的工具管理和单Agent有一个很大不同工具不是被所有Agent共享而是按角色做显式绑定。比如检索Agent只暴露搜索和网页解析工具质检Agent只暴露校验工具。这么做的好处是缩小每个Agent的决策空间让它在自己的职责范围内做工具选择准确率会明显提升。为了管理方便我写了一个简单的ToolRegistry负责注册、查询和按配置绑定工具class ToolRegistry: def __init__(self): self._tools: Dict[str, BaseTool] {} def register(self, tool: BaseTool): name getattr(tool, name, None) or tool.__class__.__name__ if name in self._tools: raise ValueError(ftool name duplicated: {name}) self._tools[name] tool def get(self, name: str) - BaseTool: return self._tools[name] def bind_by_config(self, cfg: AgentConfig) - List[BaseTool]: return [self._tools[name] for name in cfg.tools]注册机制的核心价值在于统一管理工具的元数据、参数校验与调用日志。每个工具在注册时我会要求开发者提供完整的参数schema说明这样大模型在选择工具时能准确地生成参数。还有一个实践技巧给每个工具加一层包装记录调用次数和耗时。这组数据在后面的成本分析和问题排查里非常有用能直观看到哪个工具被反复调用、哪个工具经常出错。3.3 任务分发与规划器实现有了Agent和工具之后核心问题变成任务怎么拆、怎么发。我的最早版本里用一个“规划Agent”来做任务编排它接收用户请求将请求拆成若干子任务每个子任务包含目标、接收者角色、输入参数范围然后把子任务加入全局队列由调度循环逐个派发给对应的执行Agent。规划Agent本身不执行任何具体工具操作它只做决策。有一个经验很值得分享规划Agent的prompt里一定要强调“不要替执行者做具体结论”否则它容易把最终答案都猜好了执行者只是走个过场。后来我在规划Agent的prompt里加了约束“你只负责任务分解和派发不生成最终结论当子任务结果返回后请综合各结果做出判断。”效果好了很多子任务质量和最终报告的完整性都有提升。3.4 共享记忆与全局状态管理这一块是整个框架里最容易被忽略、但恰恰最重要的一环。多智能体协同里最常见的失败模式就是上下文串味儿Agent B读了Agent A的全部历史结果把自己的角色都带偏了。所以我强烈建议每个Agent维护独立的短时记忆只接收与自己任务相关的上下文不要一股脑把全局状态全部塞给它。全局状态我放在一个中心化的StateStore里用字典或任意存储中间件保存。每个Agent执行完后把产出结构化地写回StateStore调度层决策时需要引用某个中间结果通过键读取并拼装给下一个Agent。这样做的好处是各Agent的上下文开销可控而且系统状态可观测。一个简化版的实现如下class StateStore: def __init__(self): self._store: Dict[str, Any] {} def set(self, key: str, value: Any): self._store[key] value def get(self, key: str) - Any: return self._store.get(key) def append(self, key: str, item: Any): self._store.setdefault(key, []).append(item)这里的设计要点是“谁负责写哪个键”必须明确。我在项目里维护了一张角色与键的映射表例如调研Agent只写research_*前缀的键审阅Agent只读不写。这个约定写在每个Agent的prompt开头同时也体现在代码注释里。一旦某个Agent试图写入不属于它的键日志系统会直接标记警告。3.5 协作协议的代码骨架最后是沉淀出来的编排核心逻辑。调度循环大致如下读取用户请求、调用规划Agent生成子任务清单、按顺序派发子任务、收集执行结果并写入StateStore、如果存在质检Agent则先送审再决定是否进入下一轮最后汇总各子任务的产出生成结果。class Orchestrator: def __init__(self, planner, executor_map, state_store, reviewerNone): self.planner planner self.executor_map executor_map self.state_store state_store self.reviewer reviewer def run(self, request: str) - Dict[str, Any]: tasks self.planner.plan(request) for task in tasks: agent self.executor_map.get(task[agent]) result agent.invoke({input: task[instruction]}) self.state_store.set(task[result_key], result[output]) if self.reviewer: review self.reviewer.review(task[result_key]) if not review[passed]: agent.invoke({input: f请根据反馈修改{review[feedback]}}) return {final_output: self.state_store.get(final_output)}这只是一个最小的骨架真实实现里还要处理并发、重试、失败传播等。但多智能体框架设计里最难的不是这些异常处理而是把职责边界和消息流转定义清楚。代码反而是其次的。我见过很多项目在异常处理上堆了大量代码但角色边界模糊、消息结构混乱最终整个系统还是跑不起来。4. 四种主流协同模式与选型对比4.1 团队模式多角色自由协作团队模式指多个Agent彼此平级像小组开会一样讨论同一个问题最后汇总结论或者投票决定。优点是思路发散性强适合创意类、方案类任务缺点是token消耗大、讨论容易发散、收敛困难。使用团队模式时一定要设置最大轮次限制并在每一轮讨论后让主持人Agent做一轮总结否则很容易陷入“你说得对我也同意”式的无效对话。我之前测试过一组团队Agent做技术选型讨论不加限制的情况下它们讨论了七轮还在围绕同一个方案的优缺点绕圈。4.2 监督者-工作者模式最稳妥的起步选择和我个人实际体验里最能落地的是监督者-工作者模式。有一个管理者Agent负责整体任务的分解与分配若干工作者Agent负责执行管理者最后汇总审核。这个模式实现简单、行为可控、扩展性强。它本质上是把“规划”和“执行”分离了规划信息集中在一个Agent手里执行Agent不关心全局只负责把自己的活干好。如果要加质检Agent本质上就是再加一个监督者的变体改动成本很小。新手起步我强烈推荐先从这个模式开始。4.3 层级模式适合复杂跨域任务当任务跨度较大比如既要处理文本、又要查询数据库、还要生成图表单层监督者模式会让监督者的上下文变得很重。这时候可以引入层级顶层监督者负责整体任务把子任务分给中层领域主管中层再分给基层执行Agent。层级模式的优点是上下文隔离到不同层级各层只关注自己的领域缺点是延迟变高、链路变长、调试也更复杂。我的建议是能不用就不用只有任务复杂度确实超过单层能力再上。层级模式一旦链路里某个环节出问题定位问题的成本会成倍增加。4.4 流水线模式步骤强依赖时的自然选择流水线模式适合有明显先后顺序的流程比如数据采集、清洗、分析、生成可视化、写报告每个Agent只处理前一个Agent的产出。它实现最简单最可控但缺点是不可回退一旦前面某个环节出现漏数据后面全错。为了缓解这个问题我一般会在每个环节输出里附带一个数据校验字段下游Agent执行前先检查不满足条件就直接报错回到上游重跑。4.5 模式对比速查表模式适用场景优点风险点团队模式头脑风暴、方案设计发散性强视角多元收敛困难token消耗大监督者-工作者通用任务分解与执行可控性好实现简单监督者上下文压力大层级模式跨领域复杂任务上下文隔离清晰链路长、调试复杂流水线模式步骤强依赖的处理实现简单、流程清晰错误传播、不可回退这四种模式的本质都是“状态流转”的变体区别在于谁拥有决策权和信息如何流动。实际项目中我用的最多的是监督者模式其他模式更多是某些具体模块内部的实现细节。不需要在一个系统里只选一种完全可以把监督者模式做总调度内部某个环节再用流水线模式处理子任务。5. 用一个实际案例验证框架模拟项目X的智能调研报告生成5.1 任务定义与角色分配为了验证框架我搭建了一个模拟项目X用户给出一个技术主题系统自动生成一份结构完整的调研报告包含背景、技术方案对比、社区热度分析、落地建议。在这个Demo中我把角色分为三类规划者、调研员、审阅者。规划者负责把用户主题拆成调研子项调研员按子项去检索和归纳客观信息注意我限制了它不能做主观推荐审阅者最后检查报告的完整性、数据来源、逻辑一致性并给出修改意见。为了让Demo在一个合理的成本内跑通我限制了总轮数不超过5轮模型使用整体成本较低的规格。5.2 完整工作流与配置示例整个流程是这样的。第一步规划者收到用户主题后输出三个子任务行业背景与市场数据接收者调研员、主流技术方案对比接收者调研员、社区活跃度与趋势接收者调研员。第二步三个子任务并行派发给三个调研员每个调研员独立调用搜索、网页文档解析等工具把结果写入StateStore的不同键第三步汇总Agent把三块内容拼装成完整报告第四步审阅者读取报告草稿按预先定义的质量清单检查如果有问题则返回给对应模块修改最多循环两轮。为了让角色配置更清晰我把Agent的prompt外置成了JSON文件。这里截取调研员角色的配置片段{ name: researcher, description: 负责客观信息检索与归纳不做主观推荐, model: gpt-4o-mini, temperature: 0.1, tools: [web_search, web_fetch, doc_parser], prompt: 你是一名调研员。你的任务是根据指定主题检索最新、最相关的客观信息并以结构化列表输出。你只陈述事实和数据必须标注信息来源。禁止给出主观建议或倾向性结论。, max_iterations: 8 }配置外置的好处很明显调prompt、换模型、增删工具都不需要改代码。业务同学也能看懂这个文件在需要调整Agent行为时可以自己改。我把每个Agent的“不做什么”也写进了描述里这比只写“要做什么”更能减少越权行为。比如调研员被明确禁止写结论审阅者被明确禁止新增外部信息。5.3 运行效果与产出分析实测下来这个Demo在正常情况下的产出质量明显高于单Agent版本。最直观的区别是报告里“信息检索”和“主观分析”的混杂感消失了调研员输出的是陈述性语句审阅者给出的修改意见是基于清单的而不是凭感觉。作为对比之前单Agent版本生成的报告经常会出现“根据我的经验建议选择……”这类没有任何数据支撑的句子。当然代价是调用次数变多了。同一个主题单Agent大概要调用模型8次左右多智能体版大约要20到25次。但因为每个Agent的上下文更短、模型规格可以部分降低总的token数和成本并没有线性增长那么多。具体数值这里不保证毕竟模型和工具版本不一样但方向是明确的多智能体用更多的调用次数换取了更好的模块化和可维护性在需要长期迭代的场景里这笔账是划算的。5.4 工程化扩展方向Demo跑通后我开始往工程化方向扩展。主要做了三件事。第一把Agent配置外部化用JSON文件描述每个角色的prompt和工具绑定业务同学也能改配置而不用碰代码。第二把整个编排流程接入日志和可视化追踪每轮协作都记录状态变化方便回放排查。第三增加“人工介入”的接口某些关键环节允许人工修改中间结果再放回流程。这些扩展的代码量不算大但对系统进入真实业务场景价值很高。6. 踩坑实录多智能体在生产落地中的常见问题6.1 上下文越滚越长怎么办多智能体框架跑一段时间后最容易出现的问题是某些Agent的上下文无限膨胀。尤其当Agent把历史消息全保留时对话轮次增加会让输入长度线性上升最终突破模型窗口。我的解法有三层。第一控制单Agent的会话历史长度只保留最近几轮关键消息。第二把Agent之间的通信从自然语言对话改为结构化消息让Agent只接收任务指令和所需数据不接收其他Agent的完整闲聊。第三如果确实需要长文档信息通过摘要Agent定期把历史内容压缩成要点再入上下文。6.2 工具调用失败与幻觉工具调用失败是多Agent场景里最常见的问题。单Agent时失败最多就是重试一次多Agent时一个工具失败的结果可能被下游Agent当成事实继续使用错误就会沿着链路传播放大。我强烈建议在每个工具调用外包一层异常捕获并设置“失败状态”字段下游Agent在读取数据时要先检查状态。同时要提醒你多智能体协同并不会天然降低幻觉反而因为上下文经过了多次转述信息失真可能更大。所以每个Agent的system prompt里都要强调“只陈述工具返回中的事实不确定的明确标注”。6.3 并发与死锁当我把派发逻辑从顺序改成并发后踩了一个典型的坑多个Agent同时写入StateStore的同一个键互相覆盖数据导致最终结果拼装时内容不完整。后来我把StateStore的写入操作加上了key级别的锁并明确约定每个Agent只写自己负责的键。还有一个更隐蔽的问题是死锁Agent A等Agent B的结果Agent B又等Agent A的结果形成环状依赖。规避方式是在规划阶段做依赖检查拒绝环形任务依赖。这些逻辑看起来是基础的并发问题但在Agent场景里很容易被忽略因为大家习惯性认为Agent是按顺序跑的。6.4 评测与回归多智能体系统更容易“隐性崩溃”多智能体系统比单Agent难测得多原因在于输出空间更大同样的输入可能因为模型采样的随机性产生完全不同的流程。我后来做了一套轻量回归方案准备一组固定的评测用例每次修改Agent配置后跑一遍人工记录关键指标的通过与失败情况。指标包括子任务是否全部完成、每个环节的耗时时长、返回结果里是否包含指定字段、是否出现越权行为——也就是某个Agent干了不属于它的事。这套方法成本不高但能拦住大部分回归问题。6.5 避坑清单速查问题现象解决方案上下文串味儿Agent输出偏离角色隔离上下文只传任务相关数据工具调用失败被传播下游基于错误数据继续处理工具结果带失败状态下游校验并发写同一键结果互相覆盖key级别锁明确写入责任方环状依赖调度卡住无响应规划阶段做依赖检测无限循环调用工具token快速消耗限制max_iterations设置轮次上限质量无法回归版本升级后行为飘忽固定评测用例记录关键指标说实话多智能体协同这个方向在大模型应用里已经不算新鲜了但框架层面的稳定性、可观测性和成本控制仍然有大量工程细节值得打磨。我自己的体会是不要一开始就想着把框架做得多通用一定要先用一个具体场景跑通最小闭环再逐步抽象成可复用的组件。在这个过程中核心不是代码量的多少而是对角色边界、状态流转、信息隔离这三件事的理解。最后再分享一个小技巧在配置Agent时把“你不需要做什么”也写进它的职责描述里这比只写“你要做什么”更能显著减少越权行为。希望这篇基于LangChain的多智能体协同框架实践记录能让你少走一些我走过的弯路。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询