最近一年多,我一直在做一个内部项目:基于AI代理代为交互,把公司里七八个AI应用——智能客服、销售助手、文档助手、代码审查机器人——接到同一个系统里,让它们支持多人协作。做之前我以为最大的难点是模型能力,做之后才发现,真正难的是让多个AI以同一套节奏运作,并且不让用户变成人肉中转站。这个项目推动我围绕“AI代理代为交互”做了一套系统架构层面的研究,结论集中在一点:在多人和多AI同时出现的场景里,系统架构的核心不是把模型堆得多强,而是让AI代理替用户完成信息的分发、路由、仲裁和反馈。这篇文章就聊聊我在这套“多人多AI协同系统架构”上的设计思路、落地取舍和踩坑记录,适合正在搭同类系统的架构师、团队技术负责人,以及被一堆AI工具搞到疲惫不堪的工具使用者。
1. 为什么需要“代为交互”:多人多AI场景的协作痛点
1.1 多人协同不只是一个任务拆分问题
很多讲AI Agent的文章都在说“把一个任务拆成多个子任务,让多个代理分头完成”。这个方向确实有用,但本质上还是当用户在系统里下达目标、系统拆解任务、多个代理执行,属于“单人单目标”的优化。
而“多人多AI协同”是另一个复杂度量级:系统里同时存在多个用户身份、多个业务上下文、多个甚至互相冲突的目标。举个我实际遇到的场景:产品经理、研发、测试三个人一起评审一个需求变更,每人都带一个自己的AI助手。产品经理助手整理用户反馈和竞品分析,研发助手评估技术方案和工时,测试助手分析回归风险。如果没有一个“代为交互”的中枢,三个人各自在AI窗口里问来问去,信息就是碎片化的——产品经理不知道研发助手评估过什么约束,测试不知道产品经理助手从用户反馈里挖到了哪些风险。最后只能由一个人把所有AI输出复制粘贴成汇总文档,这个人就是人肉集成总线。
所以我理解的“多人多AI协同”,本质上不是“多个AI并行干活”,而是“多个拥有不同身份、不同上下文、不同目标的参与者在同一个目标空间里协作,由AI代理代替每个参与者去感知、判断、沟通和行动”。这句话是整个系统的需求原点,后面所有架构决策都是从这句展开的。
1.2 认知带宽瓶颈:人肉中转站不可持续
我在项目里做过一次很朴素的时间统计:在一场持续45分钟的需求评审中,一个人同时维护三个AI对话窗口,大约会花40%的时间在复制粘贴、整理格式、确认“刚才那个AI说的到底是哪一版方案”这类低价值动作上,真正用来做决策判断的时间不到一半。这不是工具不好,而是交互模式出了问题——多点直连导致链路爆炸。
假设有M个用户、N个AI,用点对点的方式直连,系统里就有M×N条人机对话链路;再考虑AI与AI之间的通信,链路数会膨胀到M×N+N²的量级,人根本不可能在这种链路密度下保持上下文一致。引入AI代理之后的降维效果很明显:每个用户只面对自己的一个代理,人机链路从M×N退化成M条;AI与AI的通信在代理层内部用结构化方式完成,不必让用户关心。这和“别让每个业务直接连数据库,而是通过服务层访问”是一个思路——架构问题的本质往往不是某个组件不够强,而是连接关系不合理。
1.3 从“人找AI”到“AI找人”:交互模式的倒置
传统的工具使用模式是“人找AI”:你有问题,打开对话框,组织语言,期望AI理解。在多AI协同系统里这个模式需要倒过来——代理要主动感知事件、主动分发任务、在需要人做决定时把问题推到人面前。
我做过一个销售场景:销售助理代理发现客户合同里出现了一个超出标准的折扣条款,它不会等销售来问,而是自动把问题发给法务AI代理去审查;法务代理完成分析之后,把风险摘要推送到销售人员的工作台,同时把完整分析写入审计档案。销售全程没有主动“找”任何一个AI,他只是在系统提醒他做决策时介入了一次。这种“代为交互”模式,才是多人多AI系统里最实际提效的部分。
2. AI代理“代为交互”的四层职能拆解
“代为交互”这四个字里,最容易引起误解的是“代理”这个词。我这里说的是智能体(Agent),也就是拥有感知能力、决策偏好和工具调用权限的AI实体,而不是网络层的转发代理。搞清楚这一点之后,再看它的职能边界就好办多了。我把一个合格的代理拆成四层来看:感知、决策、执行、交流,每一层对应一套独立的设计约束。
2.1 代感知:订阅、检索与聚合
代理的第一个职责是替人看。人的注意力有限,但系统可以用代理去订阅事件流、监听数据库变更、接收外部回调,并在需要时发起检索和外部请求。
在设计感知层时,重点不是“能查多少数据”,而是“查什么、查到以后给谁看”。我的做法是让每个代理持有一份“感知配置”,明确它订阅的事件类型和数据源清单。感知结果统一封装成带有来源引用的结构化对象:
{ "event_id": "evt_20250124_001", "agent_id": "sales_assistant", "type": "contract_change_detected", "payload": { "contract_id": "CT-2025-0117", "changed_clause": "discount_rate", "new_value": 0.12 }, "source_refs": ["crm/contract_archive/CT-2025-0117"] }所有感知数据都带“来源引用”,这一点非常重要——后面做多模型仲裁、做错误链排查时,能不能找到一条信息的出处,直接决定系统的可信度。
2.2 代决策:角色化偏好与授权边界
代理替人做决定,靠的是用户配置的“决策偏好”,而不是模型临场发挥。我把它抽象成一份授权边界配置,按权限从松到严分四档:
- 完全自动:代理可以直接决定并执行,比如“常规会议邀请自动接受”。
- 自动处理但事后通知:比如“低风险合同修改,处理后立即发摘要给用户”。
- 需实时确认:比如“对外报价超过基准价5%必须等人确认”。
- 止步待命:比如“涉及法律争议或敏感人事变动的操作,代理只收集信息,不做任何响应”。
这四档配置会直接影响代理在分布式系统里的行为。为什么必须显式化?因为代理一旦替人做了不可逆的决定,边界不清晰就是事故根源。我在内部让每个代理都加载一份JSON配置,明确“什么类型的操作可以走到哪一档”,再把这份配置同步给交互中枢,路由和仲裁都会读取它。
2.3 代执行:工具调用与工作流触发
决策之后是执行。代理可以调用工具API、发起审批流、写入业务系统,但一条铁律是:代理只负责发起动作,真正的系统变更必须走业务后台的既定接口。要让代理调用工具,就得先把工具封装成幂等、可控、可审计的操作单元。
我在封装工具时统一了三个属性:最小权限(代理有一个只读的默认权限,提权必须走到确认档)、幂等键(同一操作重复执行不会产生重复影响)、审计日志(每次调用自动追加事件)。举个反面例子:早期版本里,销售代理可以直接调用“修改合同”接口,结果有一次它把折扣字段从0.08填成了0.12,因为模型的输入里混进了一条过期报价。从那以后,所有写操作代理只能“发起变更请求”,真正落库交给审批流去处理,错误率直接降了一个量级。
2.4 代交流:代理与代理的通信协议
代理与代理之间怎么说话,决定了这套系统的天花板。不能用自然语言来回发——那既低效又容易产生歧义。我采用的是一条结构化的消息协议,无论底层是MCP这类通用协议还是自研协议,消息结构都至少包含三块:
{ "header": { "msg_id": "msg_20250124_003", "session_id": "sess_review_0117", "from_agent": "sales_assistant", "to_agent": "legal_reviewer", "type": "analysis_request" }, "payload": { "intent": "evaluate_contract_risk", "params": { "contract_id": "CT-2025-0117", "changed_clause": "discount_rate", "new_value": 0.12 }, "confidence": 0.9, "source_refs": ["crm/contract_archive/CT-2025-0117"] }, "constraints": { "timeout_sec": 120, "reply_mode": "structured_only" } }header做路由,payload做语义,constraints做行为约束。这看起来只是接口设计,却是“代为交互”能否成立的关键——因为代理与代理的语言,必须比人与AI的对话更严格,机器才能可靠地理解彼此。
3. 系统架构的分层设计与核心组件
3.1 五层架构全景
基于上面四层职能,我把整体系统架构画成五个层次,每层只解决一类问题:
| 层级 | 核心职责 | 关键组件 |
|---|---|---|
| 接入层 | 多端接入、会话建立 | Web端、IM、API网关、SSE通道 |
| 编排层 | 任务解析、路由、仲裁、人工确认 | 交互中枢、DAG编排器 |
| 执行层 | 运行AI代理实例 | 代理运行时、工具调用框架 |
| 模型层 | 统一模型接入 | 模型网关、云端/本地模型调度 |
| 基础设施层 | 消息、状态、观测、安全 | 事件总线、状态存储、日志链路 |
执行层和模型层常常被混为一谈,但严格区分它们是有好处的:模型层只负责“生成Token”,执行层才拥有“身份、权限、记忆和工具”。这样模型换掉不影响代理逻辑,代理换掉不影响推理厂商。
3.2 交互中枢:路由与仲裁的关键地位
交互中枢是整个系统最核心的组件,它承担两件事:一是把事件分发给正确的代理,二是把多个代理的反馈聚合、仲裁后再呈现给用户。
我的实现思路是“中枢不写业务逻辑”——它是一张可配置的路由表,再加上一套仲裁规则。比如“合同变更事件”会同时发给销售助理、法务审查和财务合规三个代理;不同代理的返回结果如果一致,直接汇总;如果不一致,进入仲裁逻辑。路由表用配置管理,仲裁规则也尽量配置化,这样业务调整时不需要改代码。这个设计让我在三个月内接入了七个业务AI代理,切路由全部靠改配置,没有重构过执行层。
3.3 记忆与上下文管理:让代理“记得住”“忘得掉”
单代理的记忆管理已经很难,多代理共享同一个“全局事实”时更难。我把记忆分成三层:工作记忆(当前任务会话内,控制在几千Token)、会话记忆(单次会话的摘要)、长期记忆(向量数据库里的用户偏好、业务事实)。每层都有独立的读写权限和更新策略。
多代理场景里最麻烦的是“记忆污染”:代理A把一条过期信息写进长期记忆,代理B读到以后当成事实去决策。我最后的处理策略是三条:长期记忆必须带时间戳和来源;每个代理对外传递记忆片段时必须携带原始事件ID;写操作之前先做一次“是否与已知事实冲突”的检查。这三条不复杂,但能把记忆污染的概率压低很多。
3.4 模型接入层:云端模型与本地模型混合调度
模型接入层要解决的是“不同任务用不同模型”。我的做法是做一个模型网关,统一适配多个推理服务,对外只暴露一组接口。调度策略很简单:摘要、实体抽取、路由判断这类低风险任务优先走本地模型,把数据留在内部网络,成本低且响应快;复杂推理、创意生成、跨文档综合判断走云端大模型;嵌入模型固定走本地小模型。这里说的本地模型,指的是通过Ollama或者vLLM部署在自有机器上的开放权重模型。我实践下来最明显的收益是两类任务成本差了近一个数量级,同时敏感数据的处理半径被收紧了。
模型网关的核心是“模型择路不能出错”。我会给每个任务打一个标签,网关根据标签选择模型策略,而且这个策略要可回滚。
4. 多AI协同的关键机制:编排、仲裁与一致性
4.1 任务编排:用有向无环图表达协作流程
多个AI代理分头干活并不是“讲一句话就都能自发动起来”,背后必须有一个显式的任务编排。我把流程建模成有向无环图(DAG):节点是代理动作,边是条件触发。相比链式调用的好处是,它天然支持多分支、多汇合和条件跳转。
拿需求评审举例子:入口节点先做“变更解析”,同时生成两条分支,一条给研发评估、一条给测试预判;两条分支都完成后汇合到“冲突识别”节点;如果识别出冲突,进入人工评审节点;没有冲突则自动生成会议纪要并通知全员。每条分支独立超时、独立重试,一个分支失败不会拖垮整条链。这套DAG跑在编排器里,每个节点都有状态机,支持暂停、恢复、观察。
4.2 冲突仲裁:多个AI意见不一致时怎么办
多个代理协作,意见冲突是常态,不是异常。我的经验是仲裁规则必须在流程之外预先定义,不能靠“让模型之间互相辩论”来决定——那是把决策逻辑又交给了不确定因素。我的仲裁设计分三层:
| 层次 | 触发条件 | 策略 |
|---|---|---|
| 字段级 | 各代理返回的同一字段不一致 | 取带来源引用且置信度更高的一条,低置信的作为备注保留 |
| 规则级 | 与预先配置的业务规则冲突 | 规则优先,比如“折扣上限12%”是硬约束 |
| 人工级 | 以上都无法消除歧义 | 路由到交互中枢,生成一份争议摘要,推给相关用户裁决 |
前面提到的例子在实际系统里是这样走的:销售代理认为可以给12%的折扣,因为它看到竞品给到了14%;法务代理认为不能给,理由是合同模板里写了标准折扣不超过8%。两个代理的字段不一致,来源引用都有效,字段级仲裁无法收敛;规则级配置又没覆盖“竞争性折扣”这一项,于是系统生成了一份包含双方论据、各自置信度和来源引用的争议摘要,推送给销售和财务。整个过程不需要人重新去两个AI窗口里翻聊天记录。
4.3 会话快照与事件溯源:状态一致性的根基
多代理并行操作共享状态,必然会遇到一致性问题。我用的是事件溯源模型:每个会话或任务维护一条事件流,所有状态变化都以追加事件的方式记录下来,代理之间不直接改写对方状态,只发送请求事件和结果事件。
这个设计有三个直接好处。第一,任何时刻的状态都可以从事件流重放得到,不怕并发写冲突。第二,出问题时可回放时间线,定位是哪条事件把状态带偏了。第三,审计天然存在,谁在什么时刻基于什么依据做了操作,全部有据可查。事件类型我固定在五种:用户指令事件、代理感知事件、代理决策事件、工具执行事件、人工确认事件。每种事件都带事件ID、时间戳、发起者和来源引用。
5. 工程落地的技术选型与演进路径
5.1 智能体运行时:框架选型不是关键决策
一说多Agent,很多人第一反应是选框架。我自己的结论是:框架选型不是关键决策,关键决策是“路由/仲裁逻辑放在框架外还是框架内”。早期的坑就是想靠LangGraph完成所有编排,结果业务规则一多,图里全是条件边,改起来痛不欲生。后来我把框架当执行库用,路由和仲裁全部收到交互中枢来做,框架只负责单代理的内部工具循环。对比下来:
| 方案 | 优点 | 我的使用场景 |
|---|---|---|
| LangGraph | 状态机能力强,图执行直观 | 单代理内部循环、有状态工具调用 |
| AutoGen | 多Agent对话模式丰富 | 模型间信息交换的快速原型 |
| CrewAI | 角色分工模型清晰 | 有稳定角色分工的小规模任务 |
| 自研编排 | 路由/仲裁完全可控 | 所有线上业务,配合事件总线 |
我并不是说框架没用,而是提醒别让框架替你做架构决策。
5.2 消息与任务队列选型
M×N链路问题必须用事件总线来解。我的建议是从Redis Stream起步:它部署简单、内置消费者组,足够撑住千万级事件处理能力。等到需要分区顺序保证、延迟严格要求的场景,再迁移到NATS或Kafka。事件结构就是4.3节里那五种类型,发布订阅关系由交互中枢配置管理。
实际落地时有一个容易被忽视的细节:任务事件和AI响应事件要走不同的主题(Topic)。任务事件用队列语义,保证每条任务都被处理且能被消费组竞争;AI响应事件用广播语义,让所有关注该会话的代理都能订阅。这个区分让不同需求的流量自然隔离,后来排查性能问题时省了很多事。
5.3 从MVP到生产级:一条务实的演进路径
我不建议一上来就追求完整架构,更推荐按阶段演进:
第一阶段,单进程跑通“代理路由”的思路,哪怕直接用Python脚本模拟代理选择和消息转发,目的是验证“代为交互”的概念闭环。第二阶段,引入本地模型做摘要实体任务,减少对云端模型的依赖,验证成本和数据边界。第三阶段,把函数直调替换成Redis Stream事件总线,让代理之间不再直接耦合。第四阶段,状态存储外置到PostgreSQL,会话快照和事件流有了持久化。第五阶段,加上可观测面板和审计查询,系统才具备上线条件。每阶段都有明确的产出物和回滚边界,这条路我走过,比一次性设计出十个微服务再上线要稳得多。
6. 实测踩坑与工程经验
6.1 上下文污染与token爆炸
多人多AI系统里最容易出现的问题就是token爆炸。代理A想把“所有用户反馈”给代理B,实际全量塞进消息里,一次几十万token直接超限。我后来定了一条规则:代理之间只能传“加工后的信号”,不允许互传原始数据。所谓信号,就是“经过筛选的Top10反馈+风险信号+来源引用”。这样既保住了信息密度,又让token消耗可控。给每个代理设一个Token预算,工作记忆超过预算就强制做摘要压缩,这个机制上线后再没出现过因为上下文超限导致的任务失败。
6.2 错误链放大:模型幻觉的连锁反应
单模型会有幻觉,多模型协同会把错误链放大。有一次系统把“客户认为价格偏高”这条模型生成的推测,当成真实反馈传递给销售代理,销售代理又基于它调整了报价。事后复盘,源头只是模型在自己下结论时忘了加置信度标志。这个案例让我定了两条硬规矩:任何AI生成的消息必须携带置信度字段;任何要写入长期记忆或知识库的关键事实,必须经过交叉验证——至少两个独立数据源或一次人工确认。
6.3 循环依赖与任务卡死
两个代理互相等待对方输出时,任务会直接卡死。我见过最夸张的一次,一个审核流程在“销售代理等法务结果,法务代理等销售补充材料”上停了整整一天,还没有任何告警。解决办法是三层保险:所有代理间请求必须带超时时间;编排器对单任务设置最大轮次上限(比如20轮);任务启动前对DAG做一次循环引用校验。一旦超时或超轮次,任务进入死信队列并推送给人工处理,绝不静默挂起。
6.4 权限边界与审计:代理不能拥有“无限权力”
代理的权限必须始终小于等于真实用户的权限,且操作不能越出用户的业务范围。我在代理运行时里做了一次强制拦截:代理调用工具前,权限模块先校验“当前代理绑定的用户身份、配置档位、目标资源”三者是否匹配,不匹配的一律拒绝并记录。所有操作事件都写在事件流里,可以按代理ID、用户ID、时间范围快速查询。这套机制虽然让代理的自主能力打了折扣,但换来的信任是值得的。
6.5 协同质量怎么量化:没有标准答案的系统如何评估
多AI协同系统的输出没有标准答案,但质量是可以量化的。我目前埋了几个指标:任务完成率(DAG正常到达终态的比例)、人工介入次数(每完成100个任务需要人确认/纠正几次)、平均任务时延、仲裁触发率与仲裁后纠正率。第四项的“纠正率”最有意思——如果仲裁后人工经常推翻仲裁结果,说明仲裁规则需要调整,而规则调整又能继续减少人工介入。这些指标帮我从“感觉系统还行”走到了“知道系统还需要改哪里”。
如果让我现在就给准备搭这套系统的人一个建议,我会说:先别急着选框架和模型,先把“代为交互”的链路图画出来——谁感知、谁决策、谁执行、谁仲裁,人手一张,再谈技术实现。多AI协同的难点从来不在模型数量,而在代理之间那几条链路是否有清晰的规则。