ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

多人多AI协同架构设计:从消息总线到冲突消解实践

多人多AI协同架构设计:从消息总线到冲突消解实践 “AI代理”这个词最近快被各方说烂了但绝大多数讨论还停留在让单个代理帮你写周报、查资料。我过去几个月一直在折腾一个更麻烦的问题当多个AI代理分别代表不同角色还要和真实的人类成员一起推进同一件事时到底该怎么设计底层架构。这套“多人多AI协同”系统我不只是画过图也真跑过一版简单的参考实现期间踩了通讯混乱、状态冲突、权限失控等不少坑。这篇文章就是我对整套架构的复盘研究不是某个现成框架的使用教程更适合正在设计多代理平台的架构师、后端工程师以及那些想搞清楚代理之间如何“代为交互”的产品和技术负责人。1. 从孤岛式AI助手到多人多AI协同问题从哪来1.1 别再混淆几个概念代理、代为交互和协同很多讨论把术语混在一起用导致一开始设计就歪了。我这里给三个词先定边界AI代理一个具备感知、规划、行动能力的软件实体能调用外部工具、访问数据并基于大模型或规则做决策。它不等同于“聊天机器人”更多是一个能独立承担子任务的执行单元。代为交互代理以某个用户或组织的名义向另一个主体传递意图、读取数据、做出承诺或执行操作。这里的重点是“授权”和“责任”不是简单替人发一句话。多人多AI协同多个自然人和多个代理在一个共享目标下分工互动通过消息交换、任务流转、结果合并共同推进工作。理解这三点之后你再回头看那些“聊天机器人接入钉钉群”的方案就会明白那只是协同的极简雏形离真正可治理的多代理系统还差得很远。1.2 单代理范式撑不住多人场景的四个原因为什么不能继续用“一个超级代理处理所有请求”的架构我在实际验证中总结了四个直接原因。第一上下文预算扛不住。单个大模型上下文窗口是有限的。在一个超过10个人的项目里同时存在多条业务线、几十轮讨论和若干份共享文档把所有历史都塞给一个代理要么超长截断要么费用高到不切实际。第二专业边界无法收敛。让同一个代理既做财务分析又做代码审查它的行为会变得不可预期。相反拆成“财务代理”和“代码审查代理”每个代理的职责、权限、prompt和工具集都能独立控制出问题时也容易定位。第三并行是刚需。多人协作天然希望不同任务同时推进。单代理是串行的一个任务卡在模型响应上后续所有事情都等着。多代理架构至少能让部分子任务并行处理。第四责任与权限必须隔离。不同参与者能够看到的数据范围不同。例如普通成员不应当看到薪资信息外部协作代理不应该访问内部代码库。单一超级代理很难做细粒度隔离一旦失手就波及全局。我甚至遇到过更尴尬的情况两个代理在没有明确终止条件时互相“捧场”A说“你说得对”B也说“你说得对”最后在死循环里消耗Token。这种问题在单代理体系里几乎不会出现但一旦引入多人多AI就必须从架构层面处理。2. 系统架构的顶层决策谁在交互谁在协调2.1 代理、人、任务的三元素关系我设计这套系统时最先画的不是流程图而是一张关系模型参与者、任务、交互。参与者包括自然人和AI代理。两者在通信层面被抽象成同一种“主体”Actor都有唯一ID、角色、权限和通信地址。任务是系统推进的最小工作单元包含目标、状态、前置条件和产出物。状态机从“待分配”走到“进行中”再到“待仲裁”或“已完成”。交互是一条发生在参与者之间的消息或调用承载意图和负载。交互不只是文字也可能是工具调用、审批请求、状态更新事件。把人和Agent都抽象成Actor是我认为最关键的一步。只有统一抽象后面的路由、权限、审计才能共用同一套机制。很多多代理框架没想清楚这一点导致“人类用户”和“AI Worker”被写成两套完全不同的子系统后期改造成本很高。2.2 分层交互层、编排层、资源层顶层架构我拆成三层每层只解决一类问题。交互层负责所有接入通道的统一转换。无论是WebSocket、HTTP回调还是邮件Webhook进到这里都变成标准化的内部事件。同时这一层也承担协议适配你发过来的文本要变成带schema的消息代理输出的Markdown要转成结构化字段才能继续向后流转。编排层是大脑负责任务分解、路由、调度、状态跟踪和冲突仲裁。这一层不直接调用模型也不直接操作数据库它只回答几个问题当前任务应该由谁处理消息应该投递给哪些订阅者两个代理的改动有冲突时按什么规则裁决资源层做的是“脏活”模型网关、工具注册中心、数据存储、外部服务适配。模型网关很值得多说一句——不是所有请求都应该丢给云端模型。按照事务性质和数据敏感级别可以让请求走本地模型或远程模型。这种做法用现在的流行话讲是“ai代理助手加本地模型”混合部署本质上是在成本、延迟和隐私之间做动态取舍。划分三层的理由很实际交互层经常需要加新渠道资源层经常要换模型商但编排逻辑一旦写死就会牵一发动全身。保持层与层之间的接口稳定是系统能持续演进的基础。2.3 集中式编排与分布式自治的取舍这是多代理架构最容易被架空的决策点。一端是全部走集中协调器另一端是代理之间点对点直接通信。集中式的优点特别明显全局状态一致、仲裁方便、审计日志完整。但风险也清楚——单点瓶颈。所有消息都经过中心节点代理数量一多中心节点既是吞吐瓶颈又是一个高价值攻击目标。完备的点对点网络理论上扩展性更好却容易陷入“多协调者”的混乱两个代理同时认为自己有权决定下一步用户就会收到两套互相矛盾的结论。我的实践做法是“逻辑集中、物理分散”。全局状态机和仲裁逻辑放在一个独立服务里但消息的传输和任务的执行分散在各节点。这有点类似分布式交换机系统架构的思路控制平面集中维护配置和路由策略数据平面负责按规则快速转发。代理之间不直接修改共享状态只向事件流广播变更状态投影服务消费事件流生成可供查询的当前状态。这样既保住了集中决策的优势又尽量避免把每一条消息都压在同一个进程里。3. 核心组件如何落地身份、消息、记忆与工具调用3.1 代理身份、授权链和权限边界系统里每个代理都要有一个完整的身份生命周期注册、启用、停用、吊销。我初期偷懒直接让代理共享一个API Key结果排查问题时分不清到底是哪个代理调用了哪个服务后来老老实实补了身份模块。具体做法是三层绑定给每个代理生成独立的公私钥对和ID代理之间通信时必须携带签名。代理要代表某个用户做事必须先由用户签发一个短时授权令牌令牌上写明允许访问的资源和有效期。代理调用工具时请求经过API网关网关解析令牌校验权限范围再决定放行或拒绝。这里有一个常见的反模式把用户的所有API Key直接塞进代理prompt让代理“按需取用”。一旦prompt被注入或者日志泄露钥匙等于全丢。正确思路是用门禁代理来控制密钥的可见性代理只得到一个临时凭证用完就失效。3.2 强类型消息总线与事件溯源多人多AI系统的血液是消息。我一开始用的是“格式自由”的WebSocket消息后来维护成本直线上升。每个代理输出的格式都不一样一个说“完成”一个说“I’ve finished”程序根本没法稳定判断。现在我把消息分为三类Command指定接收者期待执行某项操作比如“生成验收报告”。Event广播事实比如“任务状态已从待仲裁变为已完成”。Query请求数据比如“当前共享工作空间的最新版本号是多少”。每种消息都写成强类型schema至少有trace_id、sender_id、target_id、msg_type、payload_version这几个公共字段。尤其是trace_id没有它你就无法把“A代理的输入”和“B代理的输出”串成一条链路也无法回答“这个结论是怎么来的”。配合消息是事件溯源。系统不直接更新数据库里的行记录而是把所有状态变更都作为不可变事件追加写进事件流需要知道当前状态时从事件流里做投影。好处有两个一是能回放历史排查问题就像“时光倒流”二是不会因为两个人同时写一条记录而静默覆盖。3.3 工作区内存与长期记忆多代理协同里的“记忆”远比单代理对话复杂。单代理只需要管理自己的上下文多代理系统里记忆既分私有和共享又要防止串味。我采用的模型包含三层代理私有缓存只属于当前代理的推理上下文存放正在处理的任务细节其他人和代理不可见。相当于每个人的草稿纸。共享工作空间当前协作项目的实时状态包括文档、决议、待办。任何有权限的参与者都可以写入但每次写入必须广播事件。长期档案具有持久价值的决策记录、用户偏好、历史指标。这类数据放进向量库并建立知识图谱连接关系。在写共享工作空间时每条记录都必须带上source和confidence字段。比如“评估结果是该项目存在风险 —— source质量代理confidence0.85”。如果代理读了共享记忆又不保留出处就会把别人可能错误的结论当成事实再用一次导致错误层层放大。这个问题在多人多AI环境里比想象中常见。3.4 工具注册、门控和人工审批AI代理离不开工具调用但多代理场景下工具调用会成为事故高发区。我在资源层设计了一个工具注册中心用统一schema描述每个工具的名称和功能描述入参格式和返回格式访问权限要求速率限制和配额副作用级别只读、写数据、发通知、执行付款等代理要调用工具必须走“注册中心校验权限 — 门控执行 — 事后审计”三步。副作用级别高的操作比如给客户发邮件、删除资源、确认订单必须转人工审批。这里的“人工”可以是真正的人也可以是用户在后台设定好的审批代理但最终确认权必须保留在人类手里。我见过一个失败案例某次测试里一个代理因为prompt理解偏差把一条原本应该发给内部测试组的消息误转给了外部供应商。原因是系统没有对“外部接收者”做特殊标记。所以代理代你发言之前务必让“发送到外部”成为高成本操作。4. 状态同步与冲突消解多人多AI最容易翻车的点4.1 我遇到的三类状态不一致多代理系统只要开始并行状态不一致就是大概率事件。我在测试中遇到最多的是下面三类并发写同一份文档代理A和代理B同时基于旧版本修改需求文档分别生成新版本后写的把先写的覆盖了双方看起来都成功实际上丢了内容。消息乱序代理A先发出“我已完成”的事件但网络原因导致后发代理B先接收了后续的“开始下一步”再收到“已完成”上下文整个错乱。外部世界与内部状态脱节会议室已经被管理员取消了但代理没有同步外部变更仍然按旧日程向用户发出提醒。这本质上是缺少对不依赖于事件流的“外部状态”的主动刷新机制。第二个坑尤其隐蔽。如果消息总线不保证按序投递而代理之间的依赖关系隐含在消息顺序里那么在异步网络环境下出错只是时间问题。4.2 从版本向量到自动合并策略真正解决并行冲突不能靠“最后写入覆盖”。我采用了一套基于版本向量的冲突检测。每个参与者在修改共享对象时都维护一个版本向量一个以参与者ID为索引的计数器列表。每次写入自己的计数器加一并带上自己见过的其他参与者最新计数器值。当两个写入产生时系统比较两个版本向量一个版本向量的所有计数器都小于等于另一个版本说明前者是后者的因果关系可以直接合并。双方各有一些比对方更大的计数器说明这两次写入是并发冲突不能被安全覆盖。检测到并发冲突后具体合并策略我按数据种类分三种无冲突字段直接取并集或保留双方内容。可计算字段比如数字型累加用冲突合并规则重新计算。文本类字段标记为“冲突草案”进入仲裁队列而不是盲目合并。实际实现时不需要每个人都手写版本向量算法但理解这个判断过程很重要。否则遇到冲突就一股脑丢给仲裁代理仲裁逻辑会越来越胖最后变成一个无法解释的新模型。4.3 仲裁代理的角色避免二次放大冲突必然存在谁来拍板我在系统里设计了一个“仲裁代理”的抽象但它不是传统意义上生成内容的代理更像一个裁决器。仲裁代理可以基于规则也可以让一个只读上下文的AI模型参与。关键是它的职责不是“创作新内容”而是在候选版本里选一个、合并两个、或者决定转人工。如果仲裁代理也跑去生成新方案就会出现“第三个新版本”的问题——它基于两个有冲突的版本重新推理生成的内容既不是A版本也不是B版本还引入了新的幻觉风险。所以仲裁流程我固定为检测到冲突事件进入仲裁队列。仲裁代理分析候选版本和原始冲突描述选择“采纳A”“采纳B”“自动合并”或“请求人工介入”之一。自动合并结果要附带合并说明写明基于什么规则。如果仲裁超过预设超时或置信度低于阈值立刻转给真实用户。仲裁代理自身也不能成为新的单点。仲裁规则要可插拔、可回放同一个冲突事件重新跑一遍仲裁流程结果应该是稳定的。这个稳定性一旦做不到说明仲裁逻辑本身还有问题。5. 在真实项目中搭建参考实现架构验证与性能观察5.1 我最终的选型与理由纸上谈兵没有意义我花了两周做了一个可运行的最小参考实现。技术栈不算豪华但每一样都是基于实际运维成本选的。组件选择理由接入层FastAPI WebSocket生态成熟Python写起来快类型提示友好消息中间件NATS JetStream轻量、支持持久化流比Kafka复杂度和运维成本低模型网关远程模型 本地模型双路按数据敏感级别路由隐私数据走本地低敏感高理解任务走远程本地模型部署vLLM有分页管理吞吐比原生Transformers好很多向量库SQLite加向量扩展最小原型阶段不想额外维护服务规模上来再迁移Milvus状态存储事件流 PostgreSQL投影事件溯源和关系查询都覆盖模型网关是这里比较特别的一环。我的原则是涉及用户个人数据或内部代码的内容一律走本地模型而通用总结、发散讨论这类不敏感任务可以走远程模型。这样既符合“ai代理助手加本地模型”的混合思路也不会被单一模型API的限流卡死。5.2 一个任务协作场景的完整走通我设计了一个测试场景模拟一个小型团队的产品迭代评审。参与者有真实用户Mary、一个产品代理、一个技术架构代理、一个质量风险代理。流程启动后做了这几件事创建workspace初始化所有参与者身份并注册“读取需求模板”“查询架构约束”“生成风险清单”等工具。Mary在配置面板写下规则“技术架构代理可以提出异议但没有最终决策权如果它拒绝某个方案先转给我人工确认。”产品代理提出需求草案并写入共享工作空间触发事件广播。技术架构代理收到事件后调用工具查询当前架构约束判断草案不可行标记为“阻塞”并写明原因。质量风险代理并行执行风险检查把结果写入共享工作空间。仲裁代理检测到“技术架构代理反对”和“Mary设置的规则”匹配自动生成一个人工审批待办推送到Mary的终端。Mary确认后技术代理才进入重写方案状态。这个流程里代理之间没有任何一条消息是直接点对点改数据的。所有状态变更都通过事件流广播所以Mary在移动端App上能看到完整动作链“谁在什么时间基于什么版本提出了什么结论”。这就是“AI代理代为交互”的正确打开方式——它替你参与协作但每一步都留有痕迹。5.3 实测遇到的问题与调优跑通只是第一步我在压测和日常使用中又遇到了几个必须解决的工程问题。无限循环回复。两个代理就一个观点反复“讨论”每条消息都会触发对方回复形成自激循环。我的解决方案是在消息路由层加“主题轮次上限”同一主题下任何代理最多连续响应N次超过上限就自动转为“需要人工接入”。这个不解决Token消耗会指数级上升。上下文窗口溢出。本地模型对长上下文的支持不如远程模型稳定。处理方式是分层记忆大段历史先做摘要摘要最近事件作为模型输入共享工作空间里只保留当前任务的必要细节别贪多。消息颠三倒四。即使NATS支持按主题有序代理之间的因果依赖依然可能乱序。我增加了每轮决策必须显式引用parent_event_id的规则如果代理发现引用的父事件不在本地缓存就先阻塞或向事件查询接口拉取不允许闷头处理。本地模型偶发OOM。vLLM在并发高时有概率显存溢出。我调小了实例的并发数把任务调度改成单代理排队执行牺牲了一点吞吐换来稳定性。代理数量超过8个之后建议考虑把编排服务和状态投影拆开部署避免互相挤占资源。6. 个人经验与后续演进方向6.1 三个被低估的隐性成本这套系统跑下来让我最头疼的往往不是模型能力而是工程治理带来的隐性成本。第一个是代理对齐成本。每个代理的prompt风格、输出参数、错误处理习惯都不一样。如果一开始没有统一协议和输出schema最后你会花一半时间写解析各代理输出格式的胶水代码。我的经验是提前定义好“代理能力描述”和“消息协议版本”并强制所有代理通过同一个SDK接入。第二个是可观测性成本。多代理链路的排错比单线程难得多。没有了trace_id你几乎不可能回答“哪个代理用了哪份数据、产生了什么结论”。现在我的系统从消息网关开始就打印结构化日志哪里断链立刻能看出来。第三个是权限治理成本。多人多AI系统会放大任何一个权限小漏洞。本地模型、远程模型、工具调用、共享记忆每一层都可能是数据泄露的出口。权限规则不能等出事之后再补而是在建第一个代理时就要考虑。6.2 从协同系统到代理社会下一步怎么做这个架构再往前延伸其实就是“有治理的人机混合组织”。代理不再只是工具而是一个具备身份、行为记录、信用数据的参与者。我们可以把代理的每一次发言、投票、审批都做成可验证的记录这样协作结果可以审计责任可以被追溯。如果你也想动手做类似方向我的建议非常朴素先从两个代理协作解决一个真实问题开始别急着搞几十个代理的大联盟。把消息总线、状态同步、权限门禁这三样基础服务打好后面加代理其实就是注册一个新的Actor加一个prompt和一组工具而已。这个领域还很年轻留给工程架构师的空间比留给调参工程师的空间要大得多。就我个人体会而言多人多AI协同架构最有趣的地方在于大模型决定了每个代理的“智商上限”而架构师的每一层设计决定了整个系统的“协作下限”。
返回列表