
多人多AI协同听起来像是把几个大模型接在一起就完事了但真正把“替人干活”这件事落进系统架构坑比我预想的多得多。这个项目最初源于一个很实际的痛点团队里有产品、研发、测试、运营四种角色日常要同时使用代码生成模型、文档模型、数据分析模型和内部知识库助手每人开几个窗口来回切换上下文全靠人肉搬运消息复制粘贴到变形。后来我们决定不搞“给AI加界面”这种浅层集成而是让每个成员拥有一个AI代理由代理替人去协调、调度、分发和汇总其他AI最终沉淀出一套“多人对多AI”的代理化协同架构。这篇就把这套架构从设计决策到落地细节完整拆开讲包括为什么代理化优于直连、多智能体协同的上下文与路由怎么设计、人怎么插队介入、以及我踩过的几个比较经典的坑。1. 为什么需要“代理代为交互”而不是直连多个模型1.1 入口式集成的核心价值第一版方案很直接给每个客户端配一个模型选择器想用哪个模型就调哪个API。结果跑了几周就发现这不是协同是转接头。问题出在“交互成本”被忽略了。四个角色、五个模型、三套API规范组合起来就是几十种调用路径。研发问代码生成模型要解释产品非得把同一段话再贴给文档模型重写一遍测试又要让数据分析模型把结果重新描述一次。每个模型收到的都是没有上下文的孤立提问每个用户都要手工对齐各方输出。这种模式下模型不是助手是十几个需要分别伺候的“外包专员”。换成AI代理代为交互之后架构逻辑就变了所有用户请求先进代理层由代理统一理解意图、拆解任务、确定路由再代表用户去分发和回收。用户面对的是一个能听懂“帮我看看这段接口性能顺便按测试规范出几条用例”的入口而不是五个互不相识的黑盒子。代理在中间做的事本质上是用一套统一协议把“人的意图”翻译成“模型的任务”再把多个模型的输出汇编成“人的答案”。1.2 多AI协同需要“代理”作为隔离层另一个容易被忽略的原因是模型之间不能直接互相信任。模型A的输出作为模型B的输入时如果没有任何质量闸门错误会沿着链路被放大。比如代码模型生成了一段不存在的函数名文档模型拿到了这个错误信息会一本正经地写出一段使用说明最后人拿到一份描述不存在功能的文档。这种“垃圾进、垃圾出”在链式调用里非常常见。代理层在这里起到了“语义校验”和“格式归一”的作用。每当一个模型的输出要被传给下一个模型之前代理先做三件事检查输出是否满足预定义结构抽取关键实体和结论把内容重新包装成目标模型能理解的prompt格式。这个过程很像企业内部的项目经理各团队交付的东西先由项目经理核对、合并、再转述而不是让后端直接把半成品丢给前端。热词里提到的openclawros那套思路也是同一个逻辑ROS本身解决机器人组件间的通信协议openclaw让AI代理拥有操作外壳两者组合的关键不在单个工具而在“路由与转换”这一层。AI代理协同系统的架构核心不是模型本身而是连接、翻译、仲裁这些“代理化”基础设施。1.3 多人多AI场景下的特殊挑战单人多AI已经够复杂多人多AI则多了一层社会性挑战人的优先级不同、模型的能力边界不同、会话的归属也不同。产品经理让文档模型生成的方案研发希望在同一份文档里直接看到代码模型的技术评审意见两条请求都涉及同一个文档但写权限和决策权重完全不一样。如果每个人直接操作各自的AI冲突没人仲裁。A让AI把文档标题改成“v2方案”B让AI把同一处改成“final版”两个模型各自执行最后文档被改乱。代理层接管后这类冲突被建模为“同一资源上的多个写意图”由代理层的调度器根据角色权限、时间优先级、依赖关系做合并或排队。这套机制本质上就是一个轻量级的事务管理器只不过它管的不再是数据库行锁而是文档段落、代码文件、甚至一段对话的上下文空间。2. 系统整体架构与关键设计决策2.1 四层架构总览在这个项目里我最终把系统分成四层交互层、代理调度层、模型底座层、数据与审计层。这是经过三轮重构后定下来的形态每一层都有明确边界改模型不碰界面改调度不碰模型。层级核心职责关键组件交互层对接用户与呈现结果Web客户端、IM机器人接口、事件订阅代理调度层意图解析、任务路由、编排、仲裁意图引擎、路由表、状态机引擎、消息总线模型底座层接入异构模型与本地能力模型网关、函数调用注册中心、向量检索数据与审计层上下文存储、会话追溯、质量评估时序会话库、向量数据库、日志采集、血缘追踪给每层加上一句解释。交互层解决“人以何种方式提出需求”代理调度层是核心大脑解决“任务怎么拆、交给谁、怎么合”模型底座层解决“不同的AI能力如何被统一调用”数据与审计层解决“整个协同过程凭什么可信、可查、可复盘”。顺手提一句分布式交换机系统架构的思路对代理调度层很有借鉴价值。交换机不关心数据包内容只关心MAC地址和端口映射代理调度层也不应该理解所有业务细节只需要维护“能力注册表”和“路由策略”。把模型看成端口把任务看成帧调度器的工作就是快速、准确地把帧转发到对应端口。2.2 代理的组成结构与生命周期单个AI代理不是一个大而全的模型而是一个由多种组件拼接而成的“虚拟身份”包含意图识别器、记忆容器、工具执行器、策略配置和会话状态机。意图识别器决定了任务属于“代码生成”“文档撰写”还是“数据分析”记忆容器保存了与特定用户相关的偏好和历史结论工具执行器允许代理调用外部API、数据库和文件系统策略配置则写明了这个代理在冲突时的优先级、超时时间、以及哪些操作需要人工审批。生命周期上我采用“长驻代理临时会话”的组合。每个用户有一个常驻的代理实体负责维护长期偏好、权限身份和历史风格每次具体任务则生成一个临时会话子代理负责执行当前请求并收集结果。这样做的理由是长期状态与短时任务解耦避免上下文无限膨胀出问题时只需要销毁会话级代理不用影响整个用户代理。2.3 中心化编排还是去中心化自治这是整个架构里争议最大的决策到底由中心调度器统管所有任务还是让各代理之间自由协商我最后选了中心化编排为主、局部自主为辅的混合模式。纯中心化的优点在于可控性强所有任务都经过统一网关路由、审计、限流都好做缺点也很明显调度器成为单点一旦状态机卡死所有代理都停摆。纯去中心化自治比如让多个代理通过消息协商完成任务好处是扩展性强但排错极度困难而且容易出现两个代理互相等待的死锁。我采用的混合设计是网关中枢负责全局状态与跨代理路由已经下发给单一代理的任务在代理内部以自主执行为主允许代理自行决定调用哪个工具、以什么顺序执行子步骤。这种“中央定方向、地方管执行”的模型既保住了审计和路由的全局可控性又给单个代理保留了灵活操作的空间不会因为每一步都要回中枢而性能暴跌。3. 多AI协同过程中的核心机制3.1 能力注册与动态路由要让多个AI协同工作第一步是让调度器知道“谁有什么能力”。我在模型底座层维护了一张动态能力注册表每个模型或工具启动时向注册中心上报自己的能力标签、输入输出格式、平均延迟和最大并发数。代码模型的上报可能是code_generation; max_tokens8192; latency_p993s数据分析模型则是sql_execution, chart_generation; max_rows5000。路由策略不是简单的“关键字匹配”而是三维度打分能力匹配度、上下文契合度、负载健康度。举个例子用户发起“分析一下上周线上事故分布”调度器先通过embedding把意图映射到“数据分析”标签然后在注册表里找到两个候选模型再检查当前会话的上下文是否包含相关表结构信息最后看两个模型当前的队列长度与错误率。三个分数加权求和得分高的获得任务。这套动态路由在热词里其实有一个很经典的底层参照——“linux系统iommu软件架构分析”。IOMMU做的事情就是为设备建立DMA地址映射决定内存访问走哪条路径同时做权限隔离代理调度器做的事几乎可以一一对应建立任务到模型的路由映射隔离不同会话的数据空间以及对敏感模型做访问控制。3.2 工作流编排串行、并行、条件分支单一意图被拆解成多个子任务之后还需要一个状态机来编排它们之间的关系。我的项目里用了一套非常轻量的DSL来描述协同流程没有引入重型工作流引擎因为代理协同的流程大多数是动态生成的预定义流程图满足不了灵活性。编排器的核心数据结构是DAG有向无环图节点代表子任务边代表依赖关系。任务执行时按照“入度为零优先”的原则逐个执行只有前置节点完成后续节点才能启动。比如“生成接口性能报告”这个任务会被拆成三个节点调用数据分析模型跑SQL、调用代码模型解释性能瓶颈、调用文档模型整合成报告。前两个节点可以并行执行第三个节点必须等前两者完成这就是一个典型的分叉-汇聚模式。条件分支则依靠意图引擎的判定结果。比如分析模型输出的结论如果是“性能瓶颈集中在数据库”后续节点自动触发数据库索引优化建议任务如果是“网络IO瓶颈”则触发另一条链路。这个机制的实现难度不在于DAG算法本身而在于每个分支条件都要有明确的、可被程序判定的触发信号不能依赖模糊语义。3.3 上下文管理与会话隔离多AI协同的另一个核心问题是上下文共享边界。每个模型有各自的上下文窗口但如果各模型的上下文完全隔离协同就成了“接力赛跑每棒重新起跑”如果完全共享又会互相污染A模型看到的B模型的内部思考过程未必是有用的信息。我采用的方案叫做“分层上下文”全局会话层保存目标、约束、角色身份对本次协同的所有模型可见比如“评估订单系统的接口稳定性”就是全局目标。任务执行层保存当前子任务的输入输出与中间结果只对当前执行节点可见。私有暂存层保存模型独立思考过程中的候选信息仅对所属模型可见除最终结论外不外泄。每一层上下文都用一个向量索引ID关联切换任务时只加载对应层既控制了token消耗又避免了干扰。这里踩过一个很深的坑多个模型同时读写同一个全局会话变量会出现类似数据库“脏读”的现象。场景是代码模型先写入“接口QPS为800”随后数据分析模型在另一个分支读到这个还没被校验的值直接把它当成既定事实用于汇总报告。后来所有跨模型变量写入都强制经过“发布订阅”通道只有被主调度器标记为“已确认”的变量才会被其他模型感知这个问题才彻底解决。3.4 人类介入的“控制反转”设计多人多AI协同不代表人在圈外等着恰恰相反人在关键节点必须能插入。我把人工介入设计成三种模式旁观模式、审批模式、接管模式。旁观模式是人只观察代理的执行日志和中间结果不打断适用于低风险任务比如生成日报草稿。审批模式是代理执行到某个指定节点比如修改线上配置、发送对外邮件必须停下来等待人工确认只有收到“批准”信号才能继续这一步本质上是给系统上了权限闸门。接管模式是人主动终止当前代理流程改为直接操作某个底层工具比如数据分析模型生成的SQL有问题用户可以直接把该节点切换到SQL编辑器执行然后把结果回传给后续节点。控制反转的核心经验是必须在流程启动前声明“介入点”不能等任务执行到一半再动态判断哪里需要人。原因是代理一旦进入自动流程它的执行节奏很快人工响应跟不上。我在DSL里为每个流程模板提前标注了human_in_the_loop节点运行时遇到该节点自动挂起等人工信号或超时信号二选一这样既保证了流程不卡死也给人留了足够决策时间。4. 实操落地一套可运行的简化架构4.1 技术选型与部署思路理论框架说了一圈最终要能跑起来才算数。我的简化版架构没有引入云原生全家桶而是围绕一个核心原则只用能明确控制数据流的中件件。消息总线选择了Redis Streams而不是Kafka原因是这个场景下的消息量远没到Kafka的必要规模而Redis Streams天然支持消费者组、消息确认和短延迟处理代理间的任务分发足够。状态存储用了PostgreSQL加JSONB字段没有单独引入图数据库因为协同流程的DAG节点数量通常在几十以内关系型数据库配合递归查询完全够用。模型网关是自己写的轻量HTTP转发层负责统一鉴权、超时控制和结果解析避免依赖各家SDK的差异逻辑。部署形态上我把这套架构内部亲切地叫“边缘软化”模型中心调度器跑在一台普通服务器上模型底座则既有云端API也有本地模型。热词里提到的“ubuntu查看系统架构”和“u盘安装麒麟系统arm架构”这类基础操作在这里也很有意义——本地模型在异构ARM/x86环境上的部署差异会直接影响模型网关的超时和算力分配策略所以我在网关里给每个模型实例打上了cpu架构标签用于调度时的负载预估。核心组件清单如下组件技术选择说明消息总线Redis Streams任务分发、事件广播、延迟队列状态存储PostgreSQL会话状态、DAG定义、执行记录向量检索本地向量数据库分层上下文检索与相似意图匹配模型网关自研HTTP代理统一协议、鉴权、超时熔断人工介入服务WebSocket消息服务实时推送审批请求、接收用户指令4.2 核心数据结构设计代理间的交互和人与人之间的沟通一样需要固定格式才能减少歧义。我定义了统一的任务消息协议包含五个核心字段task_id用于全局唯一定位intent用来标记任务类型input_payload是结构化的输入数据constraints携带权限和超时信息trace_chain记录血缘链路。这个trace_chain字段非常关键。它本质上是一个不短的数组每经过一个代理节点就追加一条记录包含节点ID、输入摘要、输出摘要和执行时间。等到最终结果汇总给人时用户可以倒推“这个结论是哪个模型基于哪条输入得到的”而不是面对一个黑盒合成结果只能听天由命。我在调试多AI协同链路时超过一半的时间都在看trace_chain它能直接暴露“路由绕了一圈”和“上下文在哪个节点漂移了”。DAG流程定义的伪代码结构长这样{ flow_id: perf_report_20241108, nodes: [ {id: n1, type: model_call, target: data_analyzer, input: {sql: query_perf_stats}}, {id: n2, type: model_call, target: code_explainer, depends_on: [n1], input: {code: module_check_online}}, {id: n3, type: merge, depends_on: [n1, n2], strategy: synthesis_to_report} ], human_nodes: [n3] }4.3 代理网关的关键执行逻辑调度器最核心的执行循环大致如下用Python伪代码表示核心逻辑不是完整工程代码# 简化版代理调度主循环 def dispatch_task(task): # 1. 意图解析确定任务类型 intent intent_engine.match(task.input_payload, session_ctx) # 2. 路由决策基于能力注册表打分 candidates capability_registry.query(intent_labels) target route_score(candidates, session_ctx, load_metrics) # 3. 检查人工介入点 if task.flow_definition.has_human_node(task.current_node): wait_for_human_approval(task.task_id) # 挂起等待 # 4. 调用模型网关带超时熔断 result model_gateway.invoke(target, task.input_payload, timeouttask.constraints.timeout) # 5. 更新上下文与血缘 session_ctx.update(task.session_id, result.summary) trace_chain.append(task.task_id, target, result) # 6. 推进DAG找出下一步可执行节点 next_nodes flow_engine.advance(task.flow_id, task.current_node) for node in next_nodes: dispatch_task(node)这个循环里因为早期缺少等人工确认机制卡死过两次。后来加入了超时信号逻辑修改为遇到人工介入点后挂起但超过max_wait_seconds如果没收到人工指令默认采用safe_reject策略——即取消该节点的自动执行并回滚到上一个稳定状态而不是擅自继续。宁可任务中止也不要让错误结论继续向下游传播。4.4 压测与性能调优经验我把这套架构跑在8核16G的服务器上同时接入4个外部模型API和1个本地模型初始压测目标是支撑20个并发用户、每个用户有3个连续协同任务。最初结果惨不忍睹调度器单节点吞吐只有每秒5个任务瓶颈集中在PostgreSQL的会话状态读写上。排查耗时一周最终做了三项优化。第一把会话热数据从PostgreSQL搬到Redis里只把最终结果落库第二给模型网关加了响应式背压限流当外部模型P99延迟大于3秒时不再爆量发送而是把新进任务放入延迟队列等待第三把意图识别模型换成了更小更快的学生模型虽然准确率下降约4%但单次识别时间从600ms降到90ms在协同场景下这4%的准确率损失完全可以通过后续人工介入节点兜底。实测稳定后峰值吞吐达到每秒22个任务P95链路延迟压缩在6秒以内。对于这种“人机不断往返确认”的协同架构这个指标已经满足日常团队协作的体感要求了。5. 常见问题与排查技巧实录5.1 上下文漂移AI协同的经典怪病最典型的现象是第一个模型输出的结论是对的但第二个模型引用时添油加醋第三个模型最终输出离事实越来越远。我把这类问题统一诊断为“上下文漂移”。排查时重点看两层内容。第一层是trace_chain里每条记录的输入摘要是否包含了原始事实如果某一个节点的输入里已经没有“原始SQL结果”这个实体说明上层传给它的上下文已经带了转述损失。第二层是检查分层上下文的引用关系我一度允许子任务读取父任务的全部会话内容结果子任务被无关信息干扰导致输出偏离。修复方案很朴素每个节点只能看到依赖节点的输出不能看到整棵DAG树的全局会话。需要参考全局目标时必须显式在constraints里声明allow_global_context: true一旦声明系统会在写入前对全局信息做一次“事实抽取”只传递关键实体而不是把整个上下文原样复制。这个改动上线后上下文漂移类问题减少了大概七成。5.2 路由震荡与循环调用多代理系统还有一个“鬼打墙”式问题任务在几个模型之间反复横跳始终不产生最终结果。有一次调试发现代码模型输出了一段JSON被调度器误判为“意图不匹配”重新路由给意图解析模型解析模型又把它还原成文本又触发代码模型……形成了一个无限循环。排查方法是在调度器里加了“跳数计数器”。每个任务从创建开始最多允许经过6个节点超过6次路由仍然没有生成最终结论系统自动把当前所有中间结果打包发给人工审核通道并标记为abnormal_completion。这个硬上限看起来简单粗暴但在工程上非常有效——它保证系统任何时候都不会因为逻辑漏洞而死循环。更优雅的解法是用分布式交换机架构里的“MAC地址学习”思路做路由缓存第一次任务经过某条链路后调度器记录“同类意图→最佳路由路径”后续相同意图直接走缓存路径减少中间模型的反复仲裁。我现在在生产环境同时保留跳数上限和路由缓存前者兜底后者提效。5.3 权限边界与审计追溯多人多AI协同一旦开始涉足写操作权限问题就变得尖锐。最初我天真地以为把审批节点加在关键位置就够了结果发现“间接越权”更难防。比如数据分析模型没有权限删除文件但它可以调用代码生成模型生成一段执行删除的Python脚本再由人点击运行实际完成了删除动作。这种跨Agent的“逻辑借权”是系统架构层面必须堵住的。我的解决方案是在工具调用链路上增加“动作累积审计”。每个代理内部维护一份操作列表当某个会话内累积的动作组合触碰敏感行为模式时触发强制审批。例如“读取用户表”和“导出数据”单独看都是普通操作但同一会话内5分钟内同时出现这两者就被标记为“疑似数据导出”必须人工确认。这一层规则基于“操作间的相关性”而非单点权限到目前为止是比较管用的做法。5.4 日志观测的粒度设计多AI协同系统的排错难度远超单机应用。因为一个任务的流转涉及多个模型、多次网络调用、原生的异步事件传统按服务维度看日志的方式完全失效。我把日志按“任务ID节点ID”作为复合索引形成了以任务为主线索的追踪视图。节点级日志只打印三件事收到的输入摘要、做出的路由决策、产生的输出摘要。不需要打印完整prompt和完整response否则日志量会非常恐怖。实践下来单条任务日志控制在2KB以内就能满足绝大多数问题追溯需求如果确实需要看完整prompt单独存对象存储并配置采样率。这个“少打多存”的原则让日志系统稳定服务了整个项目周期从来没因日志洪峰拖垮主流程。另外给每个任务生成一张结构化的“协同过程表格”非常实用。表格的行是节点列是输入来源、路由目标、耗时、是否经过人工批准最后再加上一个结论差异度评分。这张表格同时服务两个场景研发排错时当作线索地图用户验收时当作协作凭证。我在多轮迭代中能快速定位问题一半功劳要归给这张“协同过程表格”的规范化沉淀。这个架构做下来我个人最深的体会是多人多AI协同的瓶颈从来不在模型能力而在于“组织这些能力”的系统机制。代理化交互解决了入口统一的问题编排器解决了任务串联的问题上下文分层解决了信息污染的问题人工介入模式解决了信任边界的问题。每一步看起来都不复杂但把它们耦合在一起要考虑的状态组合会指数膨胀。如果让我对准备动手做类似系统的朋友给一句最直接的建议先把trace_chain和“跳数上限”这两个看似不起眼的机制做扎实再考虑花哨的协同算法。它们不能让你赢在起跑线但能保证你不在深坑里爬不出来。下一步我打算把动态路由的策略参数化让每个团队可以通过配置文件调整模型选择权重而不是每次改路由策略都要动代码——这个方向看起来比继续堆模型更有实用价值。