当前位置: 首页 > article >正文

Multi-Agent 的共享状态问题:并发写 State 的三种冲突场景与解法一次讲透

很多同学在搭第一个 Multi-Agent 系统时脑子里的模型是这样的多个 Agent 各干各的然后把结果汇总到一起就行了。结果上线后发现某个 Agent 的更新消失了、messages 数组出现重复消息、某个字段被后来的 Agent 悄悄覆盖了排查半天找不到原因。这些问题的根源不是代码写错了是对 LangGraph 的状态合并机制理解不够深。01 Reducer 决定一切没有它并发写就是在碰运气LangGraph 的执行模型是超步superstep在同一个超步里并行运行的节点完成后统一把更新提交给 State由Reducer合并。没有 Reducer 的字段默认行为是覆盖Last Write Wins。三个 Agent 同时写同一个字段只有最后一个活下来——而「最后一个」取决于调度顺序几乎是随机的。Reducer 的签名是(existing: T, update: T) T。你来定义「两份更新怎么合并」LangGraph 负责在超步结束时调用它。importAnnotationStateGraphSendfromlangchain/langgraphimportAIMessagefromlangchain/core/messagesimportasfromuuid// ❌ 没有 Reducer多 Agent 并发写只有最后一个写入会保留constUnsafeStateAnnotationRootresultAnnotationstring// 无 Reducer → 覆盖语义并发写赌博// ✅ 有 Reducer每个 Agent 的写入都会被保留并合并constSafeMultiAgentStateAnnotationRoot// 收集所有 Agent 的结论不互相覆盖agentResultsAnnotationagentstringcontentstringreducer(existing, newItems) default() // 必须设置 default否则第一次调用时 existing undefined 会崩// 消息历史基于 id 去重后追加LangGraph 内置 messagesStateReducer 也是这个逻辑messagesAnnotationanyreducer(existing, newMsgs) constnewSetmap(m: any) idconstfilter(m: any) hasidreturndefault() // Supervisor 用 Send API 并行派发三个 AgentfunctionsupervisorNodestate: typeof SafeMultiAgentState.StatereturnnewSendresearchAgenttask搜集竞品信息newSendcodeAgenttask生成代码骨架newSendwriterAgenttask起草需求文档// 每个 Agent 节点显式设置消息 id避免 messagesStateReducer 去重时碰撞functioncodeAgentNodestate: anyconst代码骨架已生成示意returnagentResultsagentcodeAgentcontentmessagesnewAIMessageidcode-agent-${uuidv4()}content合并过程是串行的——LangGraph 先收集超步内所有节点的更新再依次通过 Reducer 处理。所以 Reducer 本身不用担心线程安全但必须满足结合律无论哪个节点的更新先被合并最终结果应该一样。02 场景一Fan-out 并发写与 messagesStateReducer 的去重陷阱messagesStateReducerLangGraph JS 里的MessagesAnnotation默认行为有一个很多人不知道的去重逻辑新消息的id在已有列表中存在→ 用新消息替换旧消息更新语义新消息的id在已有列表中不存在→ 追加到列表末尾新增语义设计初衷是支持 Human-in-the-Loop 里用户编辑历史消息。但在多 Agent 场景下如果两个 Agent 各自创建AIMessage却没有显式设置id某些运行环境下 id 会碰撞导致 B 的消息静默替换 A 的消息表面上没有报错消息却丢了。// 完整示例子图隔离 消息瘦身 显式 id三件套防御并发写问题constSubgraphStateAnnotationRoottaskAnnotationstringagentNameAnnotationstring// 子图内部消息对父图完全不可见防止中间步骤污染父图internalMessagesAnnotationanyreducer(a, b) concatdefault() constParentStateAnnotationRoottaskAnnotationstring// 父图只收子图的最终结论不收中间步骤subResultsAnnotationagentstringresultstringreducer(existing, newItems) default() // 子图 exit node「瘦身」输出只暴露最终结论给父图functionsubgraphExitNodestate: typeof SubgraphState.StateconstinternalMessagesat1return// 注意这里返回 subResults父图字段而不是 messages// 父图的 messages 完全不受子图内部过程影响subResultsagentagentNameresulttypeofcontentstringcontentJSONstringifycontent子图把 ReAct 的每一步思考都存在internalMessages里父图只拿最终结论。这样父图的 context window 不会随子图运行步数增长而膨胀。03 场景二Race Condition——基于旧快照计算导致增量丢失第三种场景更隐蔽两个 Agent 不是严格并行但都基于「同一个旧 State 快照」做增量计算。时序示例Race ConditionAgent A 读 Statecount 0→ 计算 count 1 → 写入 count 1Agent B 读 Statecount 0→ 计算 count 1 → 写入 count 1最终 count 1而不是预期的 2两人都基于旧值 0 计算A 的写入对 B 来说「不存在」解法是写「增量」而不是「绝对值」把累加逻辑交给 Reducer。// ❌ 直接写绝对值两个 Agent 都基于旧值 0 计算最终结果是 1 而非 2constBadCounterStateAnnotationRootcountAnnotationnumber// 无 Reducer覆盖语义 → race condition// ✅ 写增量每个 Agent 写 [1]Reducer 累积最终聚合时才得出绝对值constGoodCounterStateAnnotationRootcountDeltasAnnotationnumberreducer(existing, newDeltas) default() // Agent A 写 [1]Agent B 写 [1]Reducer 合并后是 [1, 1]// 读取时聚合结果是 2正确functiongetFinalCountstate: typeof GoodCounterState.StatenumberreturncountDeltasreduce(sum, delta) 0// 同理动态 fan-out 时结果数组用 Reducer 收集无论派多少个 worker 都正确functiondispatcherNodestate: typeof ParentState.StateconstparseTaskstask// 可能是 1~N 个returnmap(task, index) newSendworkerAgentagentNameworker-${index}// 只要 subResults 有 Reducer无论派 1 个还是 10 个 worker结果都完整收集04 私有 State vs 共享 State架构层面的根本取舍维度共享 State私有 State子图隔离数据共享方式所有 Agent 直接读写同一份 State子图内部隔离通过入参/出参传递数据冲突风险高需要精心设计 Reducer低冲突面局限在接口层调试难度容易一份 State 一目了然较难需要追踪子图内部状态Context Window 压力高所有 Agent 的消息汇入同一 messages低每个子图有独立 messages适合场景强协作、需要实时共享中间状态强隔离、各 Agent 独立性强选型建议Pipeline 流水线A 的输出是 B 的输入用共享 State简单直接Fan-out 并行多 Agent 各自独立处理最后汇总用子图隔离 结果汇总字段Swarm/网状协作Agent 之间需要互相感知彼此状态用共享 State 精心设计的 Reducer05 四条实践原则与常见坑速查原则一每个会被多个 Agent 写入的字段必须定义 Reducer。原则二Reducer 必须是纯函数且满足结合律。不在 Reducer 里做 API 调用。不写依赖合并顺序的逻辑如字符串拼接带分隔符。原则三子图输出要「瘦身」。exit node 只返回最终结论不把内部 messages 全部暴露给父图。原则四Multi-Agent 场景显式管理消息 id。用uuidv4()自己管不依赖框架自动生成避免messagesStateReducer静默去重。// 速查4 个最常见的坑 解法// 坑 1Reducer 不满足结合律 → 改为数组收集// ❌ reducer: (a, b) a ? ${a}|${b} : b // 顺序不同结果不同// ✅ reducer: (a, b) [...a, ...b] // 数组 concat 满足结合律// 坑 2忘记 default → 第一次调用 existingundefined → 崩溃// ❌ Annotationstring[]({ reducer: (a, b) [...a, ...b] })// ✅ Annotationstring[]({ reducer: (a, b) [...a, ...b], default: () [] })// 坑 3子图 messages 全量流入父图 → context window 膨胀// ❌ 子图 exit node 直接返回 { messages: state.internalMessages }// ✅ 子图 exit node 返回 { subResults: [{ agent, result: lastMsg.content }] }// 坑 4消息没有显式 id → messagesStateReducer 去重时碰撞 → 消息静默丢失// ❌ new AIMessage(结果内容)// ✅ new AIMessage({ id: agent-${uuidv4()}, content: 结果内容 })总结这篇我们把 Multi-Agent 共享状态的并发写入问题拆了个底朝天Reducer 是关键没有 Reducer 的字段在并发写入时行为未定义凡是多 Agent 会写的字段都必须配 Reducer且default不能省三种冲突场景各有解法fan-out 写入用 Reducer 汇总、子图 messages 膨胀用 exit node 瘦身、race condition 用写增量而非绝对值messagesStateReducer 有去重逻辑基于消息 id 决定追加还是替换Multi-Agent 场景必须显式管理消息 id静默去重是最难排查的 bug私有 State vs 共享 State 根据场景选强隔离用子图强协作用共享 State Reducer不要无脑共享Reducer 必须满足结合律合并顺序不可控写成「增量收集 最终聚合」是最稳健的模式学AI大模型的正确顺序千万不要搞错了2026年AI风口已来各行各业的AI渗透肉眼可见超多公司要么转型做AI相关产品要么高薪挖AI技术人才机遇直接摆在眼前有往AI方向发展或者本身有后端编程基础的朋友直接冲AI大模型应用开发转岗超合适就算暂时不打算转岗了解大模型、RAG、Prompt、Agent这些热门概念能上手做简单项目也绝对是求职加分王给大家整理了超全最新的AI大模型应用开发学习清单和资料手把手帮你快速入门学习路线:✅大模型基础认知—大模型核心原理、发展历程、主流模型GPT、文心一言等特点解析✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑✅开发基础能力—Python进阶、API接口调用、大模型开发框架LangChain等实操✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经以上6大模块看似清晰好上手实则每个部分都有扎实的核心内容需要吃透我把大模型的学习全流程已经整理好了抓住AI时代风口轻松解锁职业新可能希望大家都能把握机遇实现薪资/职业跃迁这份完整版的大模型 AI 学习资料已经上传CSDN朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】

相关文章:

Multi-Agent 的共享状态问题:并发写 State 的三种冲突场景与解法一次讲透

很多同学在搭第一个 Multi-Agent 系统时,脑子里的模型是这样的:多个 Agent 各干各的,然后把结果汇总到一起就行了。结果上线后发现:某个 Agent 的更新消失了、messages 数组出现重复消息、某个字段被后来的 Agent 悄悄覆盖了&…...

Data URL生成器:自动化资源内联与性能优化利器

1. 项目概述:一个被低估的Web开发利器如果你经常和前端开发打交道,尤其是处理图片、字体这类静态资源,那你一定对“Base64编码”和“Data URL”这两个词不陌生。乍一看,“Blobby-Boi/data-URL-Generator”这个项目标题&#xff0c…...

不用写代码!5分钟用TimeGPT API搞定你的销售数据预测(附Python完整示例)

零代码实战:5分钟用TimeGPT完成电商销量预测 每次大促前,运营团队最头疼的就是备货量预估——备多了怕滞销,备少了又错失爆单机会。去年双11,我们团队就因为预测偏差导致30%的SKU断货,损失超百万销售额。直到发现Time…...

蓝鲸CMDB配置项生命周期管理终极指南:从创建到归档的完整流程

蓝鲸CMDB配置项生命周期管理终极指南:从创建到归档的完整流程 【免费下载链接】bk-cmdb 蓝鲸智云配置平台(BlueKing CMDB) 项目地址: https://gitcode.com/gh_mirrors/bk/bk-cmdb 蓝鲸智云配置平台(BlueKing CMDB)是一款功能强大的配置管理工具,帮…...

基于Git与Markdown构建开发者知识库:从原理到实践

1. 项目概述:一个面向开发者的个人知识管理工具最近在整理自己过去几年的技术笔记和项目心得时,发现了一个非常普遍但又棘手的问题:信息太散了。代码片段在Gist里,项目总结在Notion里,临时想法在备忘录里,而…...

3步解密高效法线贴图制作:NormalMap-Online实战指南

3步解密高效法线贴图制作:NormalMap-Online实战指南 【免费下载链接】NormalMap-Online NormalMap Generator Online 项目地址: https://gitcode.com/gh_mirrors/no/NormalMap-Online NormalMap-Online是一款完全免费的在线法线贴图生成工具,让你…...

ServiceStack验证系统终极指南:Fluent Validation集成与自定义规则完整教程

ServiceStack验证系统终极指南:Fluent Validation集成与自定义规则完整教程 【免费下载链接】ServiceStack Thoughtfully architected, obscenely fast, thoroughly enjoyable web services for all 项目地址: https://gitcode.com/gh_mirrors/se/ServiceStack …...

中兴光猫工厂模式解锁技术深度解析:5步获取完整设备控制权

中兴光猫工厂模式解锁技术深度解析:5步获取完整设备控制权 【免费下载链接】zteOnu A tool that can open ZTE onu device factory mode 项目地址: https://gitcode.com/gh_mirrors/zt/zteOnu 中兴光猫工厂模式解锁技术是网络管理员和技术爱好者必备的专业技…...

如何快速掌握Sunday算法:字符串匹配的终极指南

如何快速掌握Sunday算法:字符串匹配的终极指南 【免费下载链接】algo 数据结构和算法必知必会的50个代码实现 项目地址: https://gitcode.com/gh_mirrors/alg/algo 在数据结构与算法的学习中,字符串匹配是一项基础且重要的技能。Sunday算法作为一…...

C++20终极指南:std::make_shared对数组的完整支持解析

C20终极指南:std::make_shared对数组的完整支持解析 【免费下载链接】modern-cpp-features A cheatsheet of modern C language and library features. 项目地址: https://gitcode.com/gh_mirrors/mo/modern-cpp-features C20标准为开发者带来了众多实用特性…...

如何使用C++20 std::midpoint:安全整数中点计算的终极指南

如何使用C20 std::midpoint:安全整数中点计算的终极指南 【免费下载链接】modern-cpp-features A cheatsheet of modern C language and library features. 项目地址: https://gitcode.com/gh_mirrors/mo/modern-cpp-features C20标准库引入的std::midpoint是…...

如何掌握现代C++ constexpr lambda:编译时表达式的终极指南

如何掌握现代C constexpr lambda:编译时表达式的终极指南 【免费下载链接】modern-cpp-features A cheatsheet of modern C language and library features. 项目地址: https://gitcode.com/gh_mirrors/mo/modern-cpp-features 现代C constexpr lambda是C17引…...

终极DDIA特征工程完整指南:数据预处理的核心技术与实践

终极DDIA特征工程完整指南:数据预处理的核心技术与实践 【免费下载链接】ddia 《Designing Data-Intensive Application》DDIA 第一版 / 第二版 中文翻译 项目地址: https://gitcode.com/gh_mirrors/dd/ddia 《Designing Data-Intensive Applications》&…...

ROPES:嵌入式系统开发的模型驱动方法论

1. ROPES:嵌入式系统开发的革命性方法论在嵌入式系统开发领域,我们常常面临一个核心矛盾:如何在高可靠性的硬实时要求与快速迭代的市场需求之间找到平衡?传统瀑布式开发周期长、反馈慢,而完全敏捷的方法又难以满足嵌入…...

React学习路径与实践指南

文章目录React 全栈进阶指南(从基础到架构)第一阶段:React 基础深入1.1 环境搭建和项目初始化1.2 JSX 深度解析编译原理1.3 组件深度解析函数组件 vs 类组件组件组合模式(Composition over Inheritance)1.4 Props 深入…...

本地向量记忆库实战:从原理到应用,打造私有AI记忆系统

1. 项目概述:一个本地优先的记忆管理工具最近在折腾个人知识管理和AI应用本地化部署时,我一直在寻找一个能让我完全掌控数据、又能灵活调用的记忆存储方案。市面上的在线笔记或知识库工具虽然方便,但数据隐私和网络依赖始终是个心结。直到我遇…...

Portable Spec Kit:用Markdown文件实现AI辅助开发的规格持久化框架

1. 项目概述:一个文件,改变你的AI编码方式 如果你和我一样,每天都要和Claude、Cursor、Copilot这些AI编码助手打交道,那你肯定也经历过这种痛苦:每次打开一个新项目,或者隔了几天再回来,都得从头…...

终极指南:如何使用Flow测试框架构建自动化测试套件

终极指南:如何使用Flow测试框架构建自动化测试套件 【免费下载链接】flow Adds static typing to JavaScript to improve developer productivity and code quality. 项目地址: https://gitcode.com/gh_mirrors/flow30/flow Flow是一个为JavaScript添加静态类…...

构建动态开发者仪表盘:Next.js与API集成实战

1. 项目概述:一个面向开发者的个人数字资产门户最近在逛GitHub的时候,偶然发现了一个挺有意思的项目,叫bigrack.dev。这个项目本身是一个个人网站,但它的定位和实现方式,让我这个老码农觉得很有嚼头。它不是一个简单的…...

Deep Searcher:解析混合搜索,打通向量检索的最后一公里

1. 项目概述:向量检索的“最后一公里”难题最近在折腾RAG(检索增强生成)应用,发现一个挺普遍的问题:向量数据库确实好用,把文本转成向量塞进去,靠相似度搜索能快速找到相关内容。但实际用起来&a…...

DesignPatternsPHP:遗留系统改造的10个终极模式指南

DesignPatternsPHP:遗留系统改造的10个终极模式指南 【免费下载链接】DesignPatternsPHP Sample code for several design patterns in PHP 8.x 项目地址: https://gitcode.com/gh_mirrors/de/DesignPatternsPHP DesignPatternsPHP是一个专注于PHP 8.x设计模…...

基于ChatGPT与FastAPI构建YouTube视频智能摘要系统

1. 项目概述:当ChatGPT遇上YouTube,我们能做什么?最近在GitHub上看到一个挺有意思的项目,叫AIAdvantage/chatgpt-api-youtube。光看名字,你大概就能猜到它的核心玩法:把ChatGPT的智能对话能力和YouTube这个…...

如何快速掌握高级机器学习:深度学习算法进阶的完整指南

如何快速掌握高级机器学习:深度学习算法进阶的完整指南 【免费下载链接】data-science 📊 Path to a free self-taught education in Data Science! 项目地址: https://gitcode.com/gh_mirrors/da/data-science GitHub 加速计划 / da / data-scie…...

OpenVision:模块化CV工具箱实战,从分类到检测的完整开发指南

1. 项目概述:一个开源的视觉智能工具箱最近在折腾一些计算机视觉相关的项目,从图像分类到目标检测,再到更复杂的视频分析,总感觉市面上的一些框架要么太“重”,要么太“散”。想快速验证一个想法,或者搭建一…...

PM2-VSCode集成方案:在IDE内实现Node.js进程可视化与一键管理

1. 项目概述:一个为开发者定制的PM2-VSCode集成方案 如果你和我一样,长期在Node.js生态里摸爬滚打,那你对PM2这个进程管理器一定不陌生。它几乎成了Node.js应用在生产环境部署的“标配”,守护进程、负载均衡、日志管理&#xff0…...

3步攻克魔兽争霸3兼容性难题:WarcraftHelper实战指南

3步攻克魔兽争霸3兼容性难题:WarcraftHelper实战指南 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper 还在为经典游戏魔兽争霸3在现代Windo…...

掌握Vue-Element-Admin事件处理的10个高级实践技巧:从基础到精通

掌握Vue-Element-Admin事件处理的10个高级实践技巧:从基础到精通 【免费下载链接】vue-element-admin :tada: A magical vue admin https://panjiachen.github.io/vue-element-admin 项目地址: https://gitcode.com/gh_mirrors/vu/vue-element-admin Vue-Ele…...

独立开发者如何利用Taotoken模型广场为小项目挑选合适模型

独立开发者如何利用Taotoken模型广场为小项目挑选合适模型 1. 模型选择面临的挑战 独立开发者在启动小型AI项目时,往往面临模型选择的困境。主流大模型厂商提供的选项众多,每个模型在性能、价格和适用场景上各有特点。传统方式需要开发者逐个查阅不同厂…...

Vue管理系统状态管理实践:Pinia在企业级项目中的终极应用指南

Vue管理系统状态管理实践:Pinia在企业级项目中的终极应用指南 【免费下载链接】vue-manage-system Vue3、Element Plus、typescript后台管理系统 项目地址: https://gitcode.com/gh_mirrors/vu/vue-manage-system Vue3、Element Plus、typescript后台管理系统…...

STM32H750驱动正点原子1.3寸屏,一个`IOSwap`参数没设对,屏幕就卡成PPT了?

STM32H750驱动1.3寸SPI屏幕:一个IOSwap参数引发的性能灾难 当我在STM32H750核心板上成功运行正点原子1.3寸屏幕的官方Demo时,那种成就感就像第一次点亮LED一样令人兴奋。然而这种喜悦很快被一个诡异现象打破——当我尝试显示自定义内容时,屏幕…...