尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
LangGraph多智能体网络架构实战:状态管理、动态路由与工程落地
1. 为什么有些任务天生适合“网”而不是“链”1.1 从协作形态看架构选型LangGraph里做多智能体协作最容易被带偏的思路就是“多就是堆”把几个Agent串成一条链或者统一挂在一个supervisor底下就觉得完事了。但有一类任务本质上就不该是流水线它是网状的。举个最直观的例子某个跨平台系统要评审一个需求设计产品、开发、测试、安全四个角色地位平等谁都可以先发现问题谁都可以把自己的结论抛给另一个角色意见来回碰撞好几轮才能收敛。这种“多智能体网络架构”的设计就是这次要聊的主题也是LangGraph多智能体设计模式的第四篇。先做一个最基本的判断架构要跟着任务的协作形态走不是跟着感觉走。我见过不少项目一开始用的是链式因为写起来最简单A干完给BB干完给C。对于完全固定的流水线这是最优解没有之一。但任务一旦涉及“评审”“协商”“迭代”这类互动链式就露馅了——它能表达单向传递却表达不了反馈回路。B发现A的产出有问题想打回去的时候你得额外写循环逻辑结果链就被改成了环环一多和网状也没区别了。并行模式适合可拆分的独立子任务比如一次翻译多篇文章。它的问题是每个子任务都是孤岛合并之前彼此不知道对方干了什么。层级模式supervisor适合上下级分工明确的场景顶层Agent负责任务分解和调度下层Agent只干活不互相沟通。那网络架构覆盖的是什么场景一句话协作双方地位平等信息的流动方向在运行时才能确定。回到开头的例子产品把需求讲给开发开发发现安全约束不满足于是直接把问题丢给安全安全补充意见后又回到产品。整个过程没有固定的先后顺序谁找谁取决于当时的上下文。我把常见的协作形态和对应模式整理成一个表任务形态典型例子建议模式固定顺序传递没有反馈订单审批、日志处理链式可拆分的独立子任务批量翻译、批量审核并行上下级分工、统一调度任务分发、流程编排层级多角色平等、动态协商设计评审、方案讨论网络这个表不是分类器更多是拿来自检当前任务属于哪个形态。很多真实任务往往是混合的主干是链局部环节是网络。这种混合结构在LangGraph里也很好表达因为图就是图节点和边随你组合。1.2 网络架构的两个直接收益与代价选网络架构最直接的收益有两点。第一是容错。链式架构里任何一环失败整条链路中断网络架构里一个节点失败其他节点仍然可以通过共享State里的已有消息继续讨论或者直接把失败节点的剩余工作分配出去。本质上是把对单点能力的依赖改成了对整体协作过程的依赖。第二是动态性。网络架构里的路由是由消息内容决定的也就是说只要Agent在消息里写明下一个应该处理的人选流程就可以走一条代码里从未写过的路径。这个特性对开放域任务很重要因为到底谁应该处理什么问题做设计的时候根本列不全。代价也要说清楚。第一状态管理复杂度明显上升多个人同时写共享State互相覆盖是家常便饭。第二消息数量会膨胀Token成本翻倍甚至翻几倍很正常。第三可能出现死循环两个Agent观点不一致会互相踢皮球大概率需要外部机制强制终止。这些不只是理论问题我后面会逐个讲实际操作时怎么处理。2. 网络架构在LangGraph里的落地方式2.1 StateGraph就是天然的“网络画布”把网络架构落到LangGraph核心就一句话把多个子Agent当作节点放进同一张StateGraph节点之间的边做成条件边条件读的是共享State里的消息。LangGraph里StateGraph表示一个有向状态机。节点可以是普通函数也可以是编译好的子图。节点执行完后返回一个dictLangGraph会把这个dict合并到共享State里。边有两种固定边用于严格顺序条件边用于动态跳转。网络架构几乎全部依赖条件边。如果你写的每个子Agent本身又很复杂可以把它们各自做成独立的StateGraph然后作为节点嵌入到外层Supergraph里。这种嵌套能力是LangGraph做多智能体比较顺手的原因——内层图负责单个Agent内部的思考与工具调用外层图负责Agent之间的协商与路由。先看一个最基础的结构两个Agent的网络雏形from typing import TypedDict, Annotated import operator from langgraph.graph import StateGraph, START, END class NetState(TypedDict): messages: Annotated[list, operator.add] def agent_a(state: NetState): # 处理完把结果和一个“目标”写进消息 return {messages: [{from: a, to: b, content: 轮到你处理了}]} def agent_b(state: NetState): return {messages: [{from: b, to: a, content: 我处理完了你看一下}]} def router(state: NetState): last state[messages][-1] return last[to] builder StateGraph(NetState) builder.add_node(a, agent_a) builder.add_node(b, agent_b) builder.add_edge(START, a) builder.add_conditional_edges(a, router, {b: b}) builder.add_conditional_edges(b, router, {a: a, END: END}) app builder.compile()这段代码把流程控制权完全交给了消息内容。router每次读最后一条消息里的to字段决定下一步进哪个Agent。只要你愿意改消息的to字段流程就能走到任意一个节点不需要改一行图的定义。这就是网络架构的底层控制逻辑。2.2 消息总线给共享状态定一套数据协议既然流程由消息驱动那消息设计就是整个架构的地基。建议每条消息至少包含这几个字段from发送方Agent名to接收方Agent名这是路由的依据content实际内容可以是文本也可以是结构化数据msg_id唯一消息ID用于去重防止同一个消息被处理两次type消息类型比如suggestion、question、approve、reject用生活化的比喻State就是办公区的公共白板每一条消息是有人贴上去的一张便签。所有便签都按时间顺序贴在同一块白板上谁都能看谁都能决定下一个自己贴什么。路由函数就是那个读便签决定下一个去找谁的人。在LangGraph里定义这样一个可追加的消息列表需要用到reducer。直接写普通list字段每次节点返回都会把旧值覆盖掉。要追加就必须在类型注解里用Annotated包一层messages: Annotated[list, operator.add]operator.add表示当节点返回新的消息时不是覆盖而是追加到列表末尾。这个细节写网络架构时几乎必用。等到了第4部分我会专门讲它一个容易踩的变体。另外消息里带不带结构化字段差别很大纯文本虽然对模型友好但路由函数无法稳定解析我的习惯是content里放自然语言同时用type字段存结构化意图路由优先读type和to解析成功率会高很多。3. 从零搭一个网络架构Demo四角色协同评审3.1 场景与拓扑模拟项目X的四角色评审我拿一个最近做的Demo当例子。场景是一个跨平台系统上线前做技术评审四个Agent参与pm产品、dev开发、qa测试、sec安全。每个Agent的能力不一样pm分析需求完整性判断一个需求是否值得推进dev评估实现成本、技术风险qa评估测试成本和质量风险sec评估安全合规风险流程规则是这样设计的pm先对需求提出一个初步评审结论然后通过消息明确下一个要参与的角色收到消息的Agent用自己的视角补充意见同样把自己认为重要的发现发给下一个角色任何一个Agent发现其他角色的意见有明显漏洞都可以直接把消息发回给对方。全部角色表态完毕且连续两轮没有新的异议评审收敛流程终止。这个规则看起来简单但它已经包含网络架构的核心要素没有固定的先后顺序没有中心调度器谁找谁完全由内容决定。3.2 节点实现每个Agent就是图上的一环按之前的思路先定义状态from typing import TypedDict, Annotated, List import operator from langgraph.graph import StateGraph, START, END from langgraph.checkpoint.memory import MemorySaver class ReviewState(TypedDict): task: str messages: Annotated[List[dict], operator.add] round: int converged: bool注意这里比朴素的NetState多加了两个字段round记录当前轮次converged记录是否收敛。它们是后面终止控制的依据。四个Agent按同样的模式写。以dev为例def dev_agent(state: ReviewState): last state[messages][-1] new_msg { from: dev, to: decide_next(state), content: analyze_from_dev_view(state[task], last[content]), msg_id: uuid4().hex, type: comment, } converged check_converged(state[messages] [new_msg]) return {messages: [new_msg], round: state[round] 1, converged: converged}decide_next和analyze_from_dev_view按具体场景实现。decision的核心逻辑是如果消息里藏着需要qa确认的风险就发给qa如果发现有安全约束没满足就发给sec如果觉得pm的需求描述有含糊就发回pm都没问题就返回END。这里我想强调一个设计习惯每个Agent内部先写好一个独立的函数处理领域逻辑再把函数包装成节点。这样便于单测Agent之间的通信协议也能独立验证。就算后面要换成更复杂的子图结构这个函数也能直接复用到子图内部。3.3 动态路由把流程逻辑交给消息内容然后是组装和路由。为了让图真正“网络化”我给每个节点都加了条件边路由函数统一读最后一条消息的to字段def router(state: ReviewState): if state[converged]: return __end__ last state[messages][-1] return last[to] builder StateGraph(ReviewState) builder.add_node(pm, pm_agent) builder.add_node(dev, dev_agent) builder.add_node(qa, qa_agent) builder.add_node(sec, sec_agent) builder.add_edge(START, pm) for node in [pm, dev, qa, sec]: builder.add_conditional_edges( node, router, {pm: pm, dev: dev, qa: qa, sec: sec, __end__: END}, ) app builder.compile(checkpointerMemorySaver())这段代码的核心是所有Agent节点的出边都经过同一个router而router只认converged和消息里的to字段。消息数据本身成了路由表图的拓扑结构退居到第二位。你甚至可以在运行时让pm把消息发给一个后来才加入的新节点只要路由映射里有这个名字流程就能过去。3.4 运行轨迹看一次真实的网络协作用一条典型需求跑一次消息流向是pm - sec - dev - qa - pm - dev - END。这条路径不是设计时写死的。第一次跑的时候pm起初是想把需求发给dev但dev的发言里发现安全风险后直接把消息抛给secsec确认后又把修改建议传回pmpm更新结论后再发给qa。整个顺序是Agent们在协作过程中自己协商出来的这就是网络架构和固定流程最大的区别。从工程上来讲真正有价值的不是最终结论而是这串消息序列——它记录了每一步是谁、在什么时候、因为什么触发了下一个动作。配合checkpointer你可以随时重放到任意一步这对调试和审计都是巨大的帮助。4. 网络架构的三块硬骨头状态、死循环、容错4.1 共享状态合并最容易互相覆盖的地方网络架构第一个坑就是共享State里的字段互相覆盖。Node函数的返回dict会被合并到顶层State如果State里某个字段没用reducer后面执行的节点就会直接覆盖前面节点的值。两个Agent各写各的结论常见做法是定义一个opinion字段。结果A写完B一执行opinion就只剩B的了A的结论完全丢失。解决思路有二。一是每个Agent使用独立的字段命名空间比如dev_opinion、qa_opinion、sec_opinion。二是把所有需要跨Agent传递的信息全部放进messages列表用reducer追加。我的习惯是尽量走第二条因为只有消息序列才能完整还原协作过程。这里还有个关于子图字段映射容易踩坑的地方。如果你把一个子图作为节点嵌入外层图子图的内部State字段和外层State字段往往对不上。最简单的处理是用一个包装函数做显式转换def dev_wrapper(state: ReviewState): sub_input {task: state[task], last_message: state[messages][-1]} sub_out dev_subgraph.invoke(sub_input) return {messages: [sub_out[summary]], round: state[round] 1}在包装函数里把子图的输出映射成外层State需要的字段格式比在LangGraph配置层面抠各种映射要省心得多实测下来稳定性也更高。4.2 死循环与消息风暴控制回合是硬功夫网络架构最经典的故障就是死循环。最常见的形式是两个Agent持续互相让步A说“你改一下我再确认”B说“你先把结论定了我再改”如此往复直到打满算力或Token配额。对付这个问题只能靠外部硬性终止。我在实际项目里用了三招第一招显式轮次上限。round字段每次节点执行都递增router里判断round超过上限就无条件进END。这比LangGraph的recursion_limit更直观因为它还能顺便输出一条“评审超时未收敛”的结论消息系统知道发生了什么而不是静默断掉。第二招消息去重。给每条消息一个msg_idAgent内部维护一个已经处理过的ID集合。如果router里发现最新消息的msg_id已经在列表中说明这条消息被重复投递直接跳过。这个做法能挡掉不少循环消息风暴。第三招语义收敛判断。当连续两轮没有任何新增观点、只有相同的复述时就认为讨论已经收敛。实际实现时我通常会让每个Agent在返回的消息里带上一个flag比如is_novelrouter统计最近N条消息里novel的数量为0就终止。就算用了这三招我仍然建议在编译时给个recursion_limit兜底result app.invoke(initial_state, config{recursion_limit: 40})兜底和业务逻辑的终止条件不冲突一层是安全网一层是正常出口。曾经有个项目就是没加兜底两个Agent在“你觉得呢/我等你确认”之间反复横跳了几十轮才发现问题加了轮次上限之后整个系统的稳定性完全不是一个量级。4.3 节点故障隔离网络架构的容错红利网络架构一个被低估的优势在于单个Agent不可用系统往往还能继续运转。前提是你得把每个Agent做成故障隔离的单元。具体做法是在包装函数里处理异常而不是让异常一路抛到图的外层def safe_agent(node_func): def wrapper(state): try: return node_func(state) except Exception as e: return { messages: [{ from: node_func.__name__, to: pm, content: fagent failed: {e}, msg_id: uuid4().hex, type: error, }], } return wrapper这样某个Agent因为模型超时、工具调用失败等原因挂掉图并不会整体崩溃。收到error消息的其他Agent可以决定是自己重试还是把任务转交给备用节点或者直接停止并报告。这种把故障变成消息、而不是异常的处理方式是网络架构下比较理想的做法。配合checkpointer还能做到更细粒度的恢复某个节点失败后人工修正它的输入再从失败节点继续执行而不是整个图重跑。在网络拓扑较大的场景里这个能力能省下大量Token重试成本。也要提醒一句图编译后如果某个节点的实现本身有逻辑bug比如返回了None导致router报错那是代码问题容错包装救不回来。网络架构的高容错指运行环境的容错不是逻辑错误的免责牌。5. 网络架构的适用边界与工程化建议5.1 哪些场景不该用网络架构必须先说反模式否则容易为了炫技把简单任务做复杂。固定流程别用网络架构。订单审核这种确定性的状态流转用链式哪怕用状态机就够网络架构只会让状态爆炸和调参难度拉满。层级模式能解决的也别硬换成网络强管控场景下supervisor的分配逻辑更清晰出问题也更好追责。高频率低延迟的调用别用网络架构。网络架构的每次消息传递都要经过大模型推理消息轮数不可控延迟和成本都很难预测。如果需要200毫秒级别的实时响应就别想多Agent网聊了。还有Token预算紧张的任务也别硬上。网络架构意味着同一个问题会被多个Agent从多个角度各回答一遍Token消耗是倍数增长的。在做技术预研时可以用并行模式试跑一次完整任务估一下Token量再决定是否值得。5.2 成本与Token为什么网络架构这么“贵”一个简单计算如果单次Agent调用的平均Token是4000一轮评审4个Agent参与跑3轮那就是大约48000 Token的消耗还没有算路由和状态叠加。用并行模式同样的任务可能只需要16000不到。贵是最少三倍起步。贵不一定代表错。如果你需要的是多角色视角带来的质量提升那这笔钱花得值。我建议把质量收益显性化比如在Demo里对比单Agent评审和网络评审的结果把问题检出数、评审耗时这些指标记录下来有理有据地决定预算。不要为了架构而架构项目负责人会感谢你。5.3 落地清单把网络架构工程化把网络架构从Demo变成稳定服务我总结了几条行为准则先小后大。先用两到三个Agent验证收敛逻辑再往上加角色。一上来就四五个Agent互相聊调试起来全是鬼故事。每个Agent做成可独立调用的子图或函数单独写测试。通信协议单独验证确保消息格式合法。全部消息进日志。不管是checkpointer还是普通文件日志都要能回放完整协作过程不然出了问题根本定位不了。路由逻辑集中管理。不要在每个节点里散落一段路由判断统一收敛到一个router模块改起来才安全。消息协议加版本号。Agent升级时旧版本消息字段可能解析不了带上version字段能省很多兼容性麻烦。预留人工介入入口。网络架构跑偏时最好能通过checkpointer从某一步手动修改消息后再继续而不是只能推倒重来。6. 实测踩坑记录与避坑速查表6.1 高频问题速查表我从实际项目里挑了几个反复出现的坑整理成表症状根因解法两个Agent反复互相发“请你先确认”整个图一直跑不停没有硬性轮次上限round字段路由统一判断到上限强制ENDAgent执行完别的Agent看不到它写的内容State字段间互相覆盖为每条信息使用消息列表追加或用独立命名空间字段路由函数返回了不在映射里的目标运行时报错Agent返回的to字段名写错路由映射加兜底default分支消息协议约束to字段的枚举值某一个Agent超时整个评审挂了异常直接抛到图外层safe_agent包装把异常转成error消息恢复断点后同一消息被重复处理没有msg_id去重维护seen集合重复ID直接跳过子图输出格式和外层State对不上字段映射缺失包装函数里显式转换字段6.2 一点小技巧最后分享一个小技巧。在调试网络架构时别直接上复杂业务先让每个Agent只做一件事把收到的消息原样返回并随机指定下一个目标。用这种“哑Agent”跑一遍图只看路由是否按预期跳转、消息是否无冲突、终止条件是否生效。链路通了再往里面填业务逻辑排查问题的成本能降一大截。另外关于观察网络状态我通常会在每次node执行后打印State里的消息摘要而不是打印全部内容。打印全部在消息多的时候根本没法看打印前三行内容加上msg_id足够看出问题在哪一环。做网络架构这段时间我最大的体会是这个模式的难点从来不在LangGraph API本身而在于约束——约束消息格式、约束状态边界、约束终止条件。谁先把这些约束想清楚谁就能让多个Agent真正像一支团队一样协作而不是各自发泄一通就散场。从长远看网络架构非常适合用来做那种“让AI们互相评审”的质量类任务比如代码评审、文档评审、方案评审。把这套思路吃透你可以很容易把任意一个单Agent系统升级成多角色协作系统这也是LangGraph多智能体设计模式里我觉得最值得花时间研究的一种。
RELATED

相关推荐

基于Python与Vue的企业员工培训系统开发实战

基于Python与Vue的企业员工培训系统开发实战

1. 项目定位与需求拆解1.1 企业员工培训系统到底在解决什么这几年我在做企业数字化项目时感触很深的一点是:培训管理系统听起来不如ERP、CRM那么“高大上”,但它恰恰是企业内部管理里最容易拖后腿、也最容易出乱子的环节。很多公司还停留在人事群里发Exc…

📅 2026/10/20 4:59:27
PyTorch实战避坑指南:从环境搭建到多卡训练

PyTorch实战避坑指南:从环境搭建到多卡训练

1. 从零上手PyTorch:一个老手的踩坑与实战笔记搞深度学习这几年,要说什么框架让我又爱又恨,PyTorch绝对排第一。爱的是它那种“写起来像Python,跑起来像闪电”的顺手感,恨的是早期版本各种API变动、显存泄漏、多卡训练…

📅 2026/10/20 4:59:27
Go Web 项目 XSS 防护实战:从 html/template 自动转义到 CSP 纵深防御

Go Web 项目 XSS 防护实战:从 html/template 自动转义到 CSP 纵深防御

做 Go 后端的人都知道,XSS 防护这件事,看起来无非是几个转义函数的事,真正到生产环境里踩一圈,才发现防线一层都不能少。Go 项目因为html/template自带自动转义,不少团队默认“挺安全”,直到某天线上收到一…

📅 2026/10/20 4:59:27
MORE NEWS

更多资讯

📰

2026年AI玩具十大榜单:从智能交互到系统化成长

2026年,随便点开一个电商平台,搜索“儿童机器人”“智能玩具”,结果能翻出几十页。每张详情页都在讲“AI大模型”“智能对话”“个性化成长”,可真正买回家,大多数产品第三天就变成了吃灰的塑料摆件。这份榜单的由来&a…

📰

经典ASP作业提交系统源码解析:环境搭建、核心模块与避坑指南

简介:这份资源是面向高校学生与Web开发初学者的ASP网上作业提交系统课程设计资料,围绕网络教育平台中作业提交与自适应学习导航的实际需求展开。内容以ASP结合ACCESS数据库为核心,涵盖模块导航、知识点检索导航、知识点关联导航与帮助导航等设…

📰

大模型系统实战:推理优化、服务化与评测监控

1. 学到这里,系统能力才是真正的分水岭如果你一路跟着这个系列学下来,能坚持到第14期这个位置,说明你已经不是刚碰LLM大模型的新手了。前面那些期我们花了大量篇幅把Transformer原理、训练策略、微调方法、RAG、Agent这些地基一块块垒起来&am…

📰

27B 单挑 2.4 万亿 Max:Qwen3.8 家族的「性价比之王」为什么是 27B

27B 单挑 2.4 万亿 Max:Qwen3.8 家族的「性价比之王」为什么是 27B 【免费下载链接】Qwen3.8-27B-GGUF 项目地址: https://ai.gitcode.com/hf_mirrors/unsloth/Qwen3.8-27B-GGUF 2026 年 8 月,阿里开源了 Qwen3.8 家族,舆论焦点几乎全…

📰

k-means图像分割从原理到实战:聚类算法详解与调参攻略

做计算机视觉的朋友应该都有个体会,图像分割这个方向看起来门槛很高,搜索引擎一搜全是U-Net、DeepLab、Mask R-CNN这类深度学习模型,动辄需要标注数据、GPU训练。但在深度学习真正普及之前,k-means这类经典聚类算法一直是图像分割…

📰

海明校验码详解:从奇偶校验到单比特纠错的原理与实现

第一次看到海明校验码的时候,我有个特别具体的疑问:奇偶校验只能告诉你“这一组里有奇数个1”,为什么海明码把几组奇偶校验叠在一起,就能反推出是哪一位错了?后来自己拿纸笔推了一遍完整的编码、传输出错、纠错流程&am…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬