☰
多智能体协作内耗严重?身份脱敏与系统隔离网关实战
2026/10/6 6:26:36 网站建设 项目流程

1. 当多个Agent开始互相“甩锅”,问题出在哪

如果你最近在折腾多智能体系统,大概率遇到过这种场景:三个Agent协作完成一个任务,结果A把任务推给B,B觉得这不是自己的职责又推回给A,C在旁边反复输出“我建议先明确分工”——整个系统陷入一种诡异的“开会循环”,token烧了一大把,任务原地踏步。更离谱的是,当你去查日志,发现每个Agent的推理链条看起来都“很有道理”,但合在一起就是一团乱麻。

这个现象在圈子里有个很形象的说法,叫机器部落主义。每个Agent基于自己的角色设定和上下文,形成了一套“局部最优”的判断逻辑,当多个局部最优碰撞时,不是产生全局最优,而是产生内耗。你给它们设定了不同的persona、不同的工具权限、不同的知识库,本意是让它们各司其职,结果它们各自为政,甚至互相“甩锅”。

我最近在做一个多智能体协作平台的项目,核心要解决的就是这个问题。具体来说,是通过一套身份脱敏加系统隔离网关的架构,把Agent之间的“身份包袱”卸掉,让它们只关注任务本身,而不是“我是谁、我该不该管这件事”。关键词里的Harness、Agent框架、系统隔离网关,都是这套方案里的核心概念。这篇文章我会把整个设计思路、踩过的坑、以及实际跑下来的效果,完整地拆开讲一遍。

适合谁看?如果你正在做Agent开发、多智能体协同、或者单纯被Agent之间的“内耗”搞得头大,这篇内容应该能给你一些可以直接抄作业的思路。如果你刚接触Agent,还没踩过协作的坑,那更好,提前把坑标出来,省得后面返工。

2. 机器部落主义是怎么形成的:从角色设定到信息茧房

2.1 角色Prompt的“副作用”:越详细越容易画地为牢

做Agent开发的人,一开始都会花大量精力打磨System Prompt。你要给Agent一个清晰的身份:“你是一个资深财务分析师”“你是一个代码审查专家”“你是一个客服代表”。这个思路本身没问题,但问题出在过度细化上。

我试过给一个Agent写这样的Prompt:“你是一个专注于后端API性能优化的专家,你只负责分析接口响应时间、数据库查询效率、缓存命中率,不负责前端渲染、不负责业务逻辑正确性、不负责安全审计。”看起来很清晰对吧?结果在实际协作中,当另一个Agent把“这个接口返回的数据结构有问题”抛过来时,这个“性能专家”直接回了一句“这不属于我的职责范围”,然后把任务原路退回。整个协作链条在这里断掉了。

这就是角色Prompt的副作用:你越是把边界画得清楚,Agent就越倾向于在自己的边界内“安全地”工作,遇到边界模糊的地带,它的第一反应不是“我来试试”,而是“这不是我的事”。多个这样的Agent放在一起,就形成了部落主义——每个Agent守着自己的“一亩三分地”,跨部落的协作变得极其困难。

2.2 上下文隔离带来的“信息茧房”

另一个加剧部落主义的因素是上下文隔离。在多智能体架构里,每个Agent通常有自己的上下文窗口,看到的是经过筛选的信息。A Agent看不到B Agent的完整推理过程,只能看到B输出的结果。这就导致A对B的决策依据缺乏理解,容易产生“它为什么这么做”的困惑,进而引发重复确认、反复询问。

我实测过一个三Agent协作的场景:Agent A负责需求拆解,Agent B负责技术方案设计,Agent C负责代码实现。A把需求拆成五个子任务发给B,B基于自己的理解设计了方案,但方案里有一个假设(“用户数据已经过脱敏处理”)没有明确写出来。C拿到方案后,发现数据格式对不上,于是回头问B,B说“我假设数据是脱敏的”,C说“但A给我的原始数据没有脱敏标记”。然后A被拉进来解释,A说“我拆解需求时默认数据是原始的”。三个人来回扯了七八轮,最后发现只是一个假设没有对齐。

这种问题的根源在于,每个Agent都在自己的上下文里“自洽”,但跨Agent的假设对齐没有机制保障。信息茧房让每个Agent都觉得自己是对的,问题出在别人身上。

2.3 内耗的量化:Token浪费与延迟放大

部落主义和信息茧房带来的内耗,是可以量化的。我做过一组对比测试,同一个任务(一个中等复杂度的数据处理流程),用两种方式跑:

指标无隔离网关有隔离网关
总Token消耗约12万约4.8万
任务完成时间8分32秒3分15秒
Agent间消息轮次23轮9轮
任务成功率67%94%

无隔离网关的情况下,大量Token花在了Agent之间的“确认-澄清-再确认”循环上。有几次甚至出现了死循环:A问B要数据,B说数据在C那里,C说数据已经给A了,A说没收到,然后循环。最后是人工介入才断开的。

延迟放大也很明显。每个Agent的推理都需要时间,23轮消息意味着至少23次模型调用,每次调用哪怕只花2秒,累计就是46秒的纯等待时间。再加上上下文越来越长,每次调用的延迟还会增加。8分32秒里,真正用于“干活”的时间可能不到2分钟。

3. 身份脱敏的核心思路:让Agent忘记“我是谁”

3.1 从“角色驱动”转向“任务驱动”

身份脱敏的核心逻辑很简单:不让Agent知道自己在整个系统中的“身份标签”。传统做法是给每个Agent一个固定的角色(“你是财务专家”),然后期望它在这个角色下做出正确决策。身份脱敏的做法是,Agent在接收任务时,只看到任务描述和必要的上下文,看不到“你是第几号Agent”“你的角色是什么”“你的权限边界在哪里”。

举个例子。传统方式下,Agent B收到的消息可能是:“你是技术方案设计Agent,请基于以下需求设计技术方案。”身份脱敏后,Agent B收到的消息是:“请基于以下需求设计技术方案,输出格式要求如下。”没有角色标签,没有“你是XX专家”的暗示,只有任务本身。

这个改变看起来很小,但效果很显著。Agent不再纠结“这该不该我管”,因为它根本不知道“自己”是谁,它只知道“当前有一个任务需要处理”。任务驱动取代了角色驱动,Agent的注意力从“身份维护”转移到了“任务完成”上。

3.2 脱敏的粒度:哪些信息该隐藏,哪些必须保留

身份脱敏不是把所有信息都抹掉,那样Agent就没法工作了。关键是脱敏的粒度。我总结了一个原则:隐藏身份标签,保留能力描述。

具体来说,以下信息应该被隐藏:

  • Agent的编号或名称(“Agent-001”“财务专家”)
  • Agent在系统中的层级关系(“你是A的下级”“你向B汇报”)
  • Agent的历史交互记录(“你之前和C有过冲突”)
  • Agent的权限边界描述(“你只能访问X数据库”)

以下信息必须保留:

  • 当前任务的具体描述
  • 完成任务所需的数据和工具
  • 输出格式和验收标准
  • 必要的业务规则和约束

这个粒度划分的依据是:身份标签会触发Agent的“自我保护”机制,而能力描述不会。当Agent知道“我是财务专家”时,它会倾向于维护这个身份的一致性,遇到财务相关的问题会更积极,遇到非财务问题会更保守。但当它只知道“当前任务需要分析财务数据”时,它的行为完全由任务本身驱动,没有身份包袱。

3.3 脱敏后的Agent行为变化:实测对比

我做过一组A/B测试,同一个任务,同一组Agent,唯一变量是是否启用身份脱敏。结果很有意思:

启用身份脱敏前:

  • Agent A(需求拆解)在拆解时,会刻意把“技术方案设计”部分标注为“由B负责”,把“代码实现”标注为“由C负责”。这种标注本身就在强化部落边界。
  • Agent B(技术方案)在设计时,会反复确认“这个方案是否符合A的预期”,而不是“这个方案是否合理”。
  • Agent C(代码实现)在遇到方案模糊时,会先问B“你当时是怎么想的”,而不是直接基于代码逻辑做判断。

启用身份脱敏后:

  • Agent A拆解需求时,只输出子任务列表和依赖关系,不标注“谁负责”。
  • Agent B设计技术方案时,直接基于需求和技术约束做决策,不再猜测“A想要什么”。
  • Agent C遇到方案模糊时,直接基于代码逻辑和测试结果做判断,必要时才向上游请求澄清。

最明显的变化是消息轮次从23轮降到了9轮。Agent之间的交互从“确认-澄清-再确认”变成了“任务-结果-下一步”。每个Agent都更关注“怎么把当前任务做好”,而不是“怎么不越界”。

4. 系统隔离网关的工程实现:Harness到底在做什么

4.1 Harness的定位:不是Agent框架,是Agent之间的“交通管制”

很多人第一次听到Harness这个词,会以为它是另一个Agent框架。其实不是。Harness在我的架构里,扮演的是系统隔离网关的角色。它不负责Agent的推理逻辑,不负责工具调用,不负责记忆管理。它只做一件事:管理Agent之间的消息传递,确保身份脱敏和上下文隔离。

你可以把Harness想象成一个邮局。Agent A把消息投递到邮局,邮局把消息里的身份标签抹掉,然后根据路由规则投递给Agent B。Agent B收到消息时,不知道这消息来自A还是C,只知道“这是一个任务请求”。Harness还负责上下文裁剪,确保Agent B只看到与当前任务相关的上下文,而不是整个系统的全局状态。

这个定位很关键。很多Agent框架试图把编排、推理、工具、记忆全部包进来,结果变得极其臃肿。Harness的哲学是只做隔离和路由,其他事情交给Agent自己或者外部的编排层。这样Harness可以保持轻量,也更容易适配不同的Agent实现。

4.2 消息脱敏的具体流程:从发送到接收的完整链路

Harness的消息脱敏流程,我拆成了五个步骤:

第一步:消息拦截。Agent A调用Harness的send接口,传入原始消息。原始消息里可能包含Agent A的ID、角色标签、历史上下文引用等信息。

第二步:身份剥离。Harness解析消息结构,把身份相关的字段(sender_id、sender_role、sender_history等)全部剥离,只保留payload(任务描述、数据、格式要求)。

第三步:上下文裁剪。Harness根据接收方Agent B的当前任务,从全局上下文中裁剪出必要的部分。比如B正在处理“数据清洗”任务,那么Harness只会把与数据清洗相关的上下文传给B,不会把A的完整推理过程传过去。

第四步:路由决策。Harness根据任务类型和Agent的能力注册表,决定把消息路由给哪个Agent。这个路由是动态的,不依赖于固定的角色映射。比如“数据清洗”任务可能路由给Agent B,也可能路由给Agent D,取决于当前哪个Agent有空闲容量。

第五步:消息注入。Harness把脱敏后的消息注入Agent B的输入上下文,B看到的是一条“干净”的任务请求,没有身份信息,没有历史包袱。

这个流程的关键在于第三步和第四步。上下文裁剪决定了Agent能看到多少信息,路由决策决定了任务分配给谁。两者结合,实现了任务驱动的协作模式。

4.3 隔离网关的部署形态:进程内、进程间、还是独立服务

Harness的部署形态有三种选择,我实际都试过:

进程内模式:Harness作为Agent进程内的一个模块,直接函数调用。优点是延迟极低,没有网络开销。缺点是隔离性差,如果Agent进程崩溃,Harness也跟着挂。适合单机部署、Agent数量少的场景。

进程间模式:Harness作为独立的进程,Agent通过IPC或本地Socket通信。优点是隔离性好,Harness可以独立重启。缺点是延迟比进程内高,大概多0.5-1毫秒。适合单机多Agent的场景。

独立服务模式:Harness作为独立的网络服务,Agent通过HTTP或gRPC通信。优点是扩展性好,可以跨机器部署。缺点是延迟最高,网络开销大概2-5毫秒。适合分布式部署、Agent数量多的场景。

我最终选择了进程间模式。原因是:延迟可以接受(0.5-1毫秒相对于模型推理的几百毫秒可以忽略),隔离性足够(Harness崩溃不影响Agent,反之亦然),部署复杂度适中(不需要额外的网络配置)。如果你的Agent数量超过20个,或者需要跨机器部署,可以考虑独立服务模式。

5. 踩坑实录:身份脱敏不是万能药

5.1 脱敏过度导致的任务迷失

一开始我走了一个极端:把所有身份信息都抹掉,连“你是一个AI助手”这样的基础设定都不给。结果Agent变得极其“迷茫”。它不知道自己的能力边界在哪里,遇到需要专业判断的任务时,会反复询问“我应该用什么标准来判断”。

比如一个数据清洗任务,Agent收到的是“请清洗以下数据”。它不知道自己是“数据工程Agent”还是“业务分析Agent”,于是它既做了格式清洗,又做了业务规则校验,还尝试做了一些统计分析。输出了一大堆东西,但大部分都不是当前任务需要的。

这个坑让我意识到:身份脱敏不等于身份消除。Agent需要知道“我能做什么”,只是不需要知道“我是谁”。所以后来的方案里,我保留了能力描述(“你可以使用以下工具”“你可以访问以下数据源”),但去掉了身份标签(“你是XX专家”“你属于XX团队”)。

5.2 上下文裁剪的“误伤”:把关键信息裁掉了

上下文裁剪的粒度很难把握。裁得太少,Agent看到太多无关信息,注意力被分散;裁得太多,关键信息被误伤,Agent做出错误判断。

我遇到过一个典型案例:Agent B在做一个API设计任务,Harness裁剪上下文时,把“该API需要兼容旧版本客户端”这条信息裁掉了,因为Harness判断这条信息属于“历史背景”,与“API设计”这个任务类型不直接相关。结果B设计了一个不兼容旧版本的API,导致下游的Agent C在实现时发现无法对接。

这个问题的根源在于,Harness的裁剪规则是基于任务类型的静态规则,但实际协作中,很多信息是跨任务类型的。后来我改成了动态裁剪:Harness会分析当前任务的所有依赖关系,把直接依赖和间接依赖的信息都保留,只裁掉真正无关的部分。这个改动让裁剪准确率从72%提升到了91%。

5.3 Agent“假装”不知道身份,但行为模式暴露了

身份脱敏后,Agent在显式层面确实不知道自己的身份了。但它的行为模式仍然可能暴露身份。比如一个被设定为“谨慎型”的Agent,即使脱敏后,它在做决策时仍然会倾向于保守选项。一个被设定为“激进型”的Agent,仍然会倾向于冒险。

这个问题在短期内无解,因为Agent的行为模式是由底层模型和训练数据决定的,不是靠Prompt就能完全改变的。我的应对策略是行为模式多样化:在路由任务时,不只看Agent的能力匹配度,还看Agent的当前行为倾向。如果当前任务需要谨慎决策,就路由给行为偏保守的Agent;如果需要快速迭代,就路由给行为偏激进的Agent。

这个策略的效果是,Agent之间的“性格冲突”减少了。以前两个性格迥异的Agent协作时,经常在决策风格上产生分歧。现在Harness在路由层面就做了匹配,协作顺畅了很多。

6. 实测数据:隔离网关到底省了多少成本

6.1 Token消耗对比:从12万降到4.8万

前面提到过,同一个任务,无隔离网关时Token消耗约12万,有隔离网关时约4.8万。这个差距主要来自三个方面:

消息轮次减少:从23轮降到9轮,每轮消息都包含输入和输出Token,轮次减少直接带来Token节省。粗略估算,每轮消息平均消耗5000 Token(输入+输出),14轮的差距就是7万Token。

上下文长度缩短:无隔离网关时,每个Agent的上下文里包含了大量历史交互记录,导致每次调用的输入Token膨胀。有隔离网关后,Harness裁剪了上下文,每个Agent只看到与当前任务相关的部分,输入Token平均减少了40%。

重复推理减少:无隔离网关时,Agent经常需要重复推理“这个任务该不该我管”“我之前有没有处理过类似任务”。有隔离网关后,这些元推理被消除了,Agent的推理全部集中在任务本身。

6.2 任务成功率提升:从67%到94%

任务成功率的提升,主要来自死循环的消除和假设对齐的改善。

无隔离网关时,23轮消息里有相当一部分是“确认-澄清”循环。有几次甚至出现了死循环,需要人工介入。这些情况直接导致任务失败。有隔离网关后,Harness在路由层面就确保了任务分配的明确性,Agent不需要反复确认“这是不是我的任务”。假设对齐的问题也通过上下文裁剪得到了改善,因为Harness会确保所有Agent看到一致的假设前提。

6.3 延迟变化:单次调用增加,整体时间缩短

隔离网关本身会引入额外的延迟。进程间通信大概增加0.5-1毫秒,上下文裁剪大概增加1-2毫秒,路由决策大概增加0.5-1毫秒。总计每次消息传递增加2-4毫秒。

但整体任务完成时间从8分32秒降到了3分15秒。原因是消息轮次从23轮降到了9轮,每轮消息的模型推理时间(几百毫秒到几秒)远大于隔离网关的延迟。所以虽然单次调用变慢了,但整体时间大幅缩短。

这个数据说明一个道理:在多智能体系统里,减少协作轮次比优化单次调用延迟更重要。隔离网关的几毫秒开销,换来的是轮次的大幅减少,整体收益是正的。

7. 这套方案适合什么场景,不适合什么场景

7.1 适合的场景:任务明确、Agent数量多、协作频繁

这套方案最适合的场景是任务明确、Agent数量多、协作频繁的多智能体系统。比如:

  • 数据处理流水线:多个Agent分别负责数据采集、清洗、转换、加载,任务边界清晰,但协作频繁。
  • 代码生成与审查:多个Agent分别负责需求分析、代码生成、代码审查、测试生成,需要频繁交互。
  • 客服工单处理:多个Agent分别负责意图识别、知识检索、回复生成、质量检查,任务流转频繁。

在这些场景里,身份脱敏和隔离网关能显著减少内耗,提升协作效率。

7.2 不适合的场景:需要深度角色扮演、创意协作、强身份依赖

这套方案不适合的场景也很明确:

  • 深度角色扮演:比如模拟谈判、角色扮演游戏,Agent需要明确知道自己的身份和立场,脱敏会破坏角色一致性。
  • 创意协作:比如头脑风暴、创意写作,Agent需要知道“我是谁”来贡献差异化的视角,脱敏会导致输出同质化。
  • 强身份依赖:比如权限管理、审计追踪,Agent需要知道自己的权限边界,脱敏会导致权限失控。

在这些场景里,身份脱敏反而会带来问题。所以这套方案不是万能的,需要根据具体场景选择。

7.3 混合模式:部分脱敏、动态脱敏

对于介于两者之间的场景,可以考虑混合模式。比如:

  • 部分脱敏:隐藏Agent的编号和层级关系,但保留角色标签(“你是财务专家”)。这样Agent知道自己的专业领域,但不知道自己在系统中的位置。
  • 动态脱敏:根据任务类型动态决定脱敏程度。任务明确时完全脱敏,任务模糊时保留部分身份信息。

我目前在生产环境里用的是部分脱敏。隐藏了Agent的编号和层级,但保留了角色标签。这样既减少了部落主义,又保留了专业分工的优势。实测下来,Token消耗比完全脱敏高约15%,但任务成功率比完全脱敏高约8%。这个 trade-off 在我的场景里是值得的。

8. 几个容易被忽略的工程细节

8.1 消息ID的生成与追踪

身份脱敏后,Agent不知道消息来自谁,但系统需要知道。所以Harness需要维护一个消息ID映射表:每条脱敏后的消息都有一个唯一的消息ID,Harness通过这个ID追踪消息的原始发送方和接收方。

这个映射表的设计要注意两点:一是ID不能包含身份信息,不能用“AgentA-001”这样的格式,要用随机UUID;二是映射表要有TTL,消息处理完成后一段时间自动清理,避免无限增长。

我一开始用自增整数做消息ID,结果Agent通过ID的大小顺序推断出了消息的先后关系,间接暴露了身份。后来改成了UUID,这个问题就解决了。

8.2 错误处理与重试机制

隔离网关引入了一个新的故障点:如果Harness挂了,整个协作就断了。所以错误处理和重试机制很重要。

我的做法是:Harness维护一个消息队列,Agent发送的消息先入队,Harness异步处理。如果Harness处理失败,消息留在队列里,等待重试。重试策略是指数退避:第一次重试等1秒,第二次等2秒,第三次等4秒,最多重试5次。

同时,Agent端要有超时机制。如果Agent发送消息后一段时间(比如30秒)没有收到响应,就认为Harness出了问题,触发降级逻辑(比如直接点对点通信,绕过Harness)。这个降级逻辑在Harness恢复后会自动切回。

8.3 监控与可观测性

身份脱敏后,调试变得困难了。以前你可以直接看“Agent A发给Agent B的消息”,现在你只能看到“消息ID xxx从某个Agent发往某个Agent”。所以监控和可观测性变得尤为重要。

我在Harness里加了几个关键指标:

  • 消息吞吐量:每秒处理多少条消息
  • 脱敏延迟:从消息入队到脱敏完成的时间
  • 路由准确率:路由决策被Agent接受的比例
  • 上下文裁剪命中率:裁剪后的上下文被Agent实际使用的比例

这些指标帮助我快速定位问题。比如有一次路由准确率突然下降,查下来发现是Agent的能力注册表没有及时更新,导致Harness把任务路由给了错误的Agent。

8.4 安全边界:脱敏不等于无权限

最后强调一点:身份脱敏不等于权限脱敏。Agent不知道自己的身份,但仍然需要遵守权限规则。Harness在路由消息时,会检查目标Agent是否有权限访问消息中的数据。如果没有权限,Harness会拒绝路由,并返回错误。

这个检查是在脱敏之后、路由之前做的。Agent看不到身份信息,但Harness知道每条消息的原始发送方和接收方,可以基于原始身份做权限校验。这样既实现了身份脱敏,又没有牺牲安全性。

我在实际项目里踩过的一个坑是:一开始把权限校验也脱敏了,结果Agent A把敏感数据发给了没有权限的Agent B,B直接处理了数据,造成了数据泄露。后来加回了权限校验,这个问题就解决了。

9. 从Harness到Agent框架:一些延伸思考

Harness和Agent框架的关系,我琢磨了很久。一开始我觉得Harness应该集成到Agent框架里,作为框架的一个模块。后来发现这样不行,因为不同Agent框架的实现差异太大,Harness集成进去会变得很臃肿。

现在的做法是:Harness作为独立的中间层,通过标准接口与Agent框架对接。Agent框架只需要实现两个接口:send(发送消息)和receive(接收消息)。Harness负责剩下的所有事情。这样Harness可以适配任何Agent框架,不管是基于Python的、基于Rust的、还是基于其他语言的。

这个设计还有一个好处:Harness可以独立演进。Agent框架的更新不影响Harness,Harness的优化也不影响Agent框架。两者解耦,各自迭代。

如果你正在做Agent开发,我建议把Harness作为一个独立的关注点来设计。不要把它塞进Agent框架里,也不要让它承担太多职责。只做隔离和路由,其他事情交给别人。这个原则让我的系统稳定了很多,也更容易维护。

最后分享一个我在实际使用中发现的小技巧:Harness的日志要分级。DEBUG级别记录完整的消息内容(包括脱敏前的),用于调试;INFO级别只记录消息ID和路由结果,用于监控;ERROR级别记录异常和失败原因,用于告警。这样既保证了可调试性,又避免了日志泄露敏感信息。这个分级策略在排查线上问题时特别有用,你可以快速定位到某条消息的完整链路,而不用在浩如烟海的日志里翻找。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询