☰
多 Agent 协同中的通信协议演进:从 JSON-RPC 到事件总线
2026/10/1 21:19:03 网站建设 项目流程

多 Agent 协同中的通信协议演进:从 JSON-RPC 到事件总线

在多智能体(Multi-Agent System)从实验室 Demo 走向企业级交付的过程中,绝大多数团队踩到的第一个深坑并不是大模型能力不足,而是Agent 之间的通信拓扑设计失控。

早期做多 Agent 协作时,最自然的想法就是把每个 Agent 封装成一个独立的微服务,通过 HTTP RESTful API 或 JSON-RPC 进行点对点的同步 RPC 调用:Planner 调 Research Agent,Research Agent 调 Search Agent。在 3 个以内 Agent 的简单场景下,这种模式跑得通;但当系统扩展到 8~10 个专业 Agent、执行涉及跨系统审计、数据分析与报告生成的复杂任务时,点对点同步通信直接导致了生产级灾难。

本文将复盘我们工作室在真实交付中,多 Agent 通信协议从点对点 JSON-RPC 演进到分布式事件总线(Event-Driven Bus)的完整工程历程。


一、点对点 JSON-RPC 的生产“三大死穴”

在 9 月初承接的一个大型集团风控审计 Agent 项目中,我们最初采用了标准的 JSON-RPC 2.0 协议进行 Agent 间的方法调用。上线不到三天,压测和真实业务并发就暴露了致命缺陷:

1. 级联延迟与连接池雪崩

JSON-RPC 是典型的同步请求-响应(Request-Response)模式。当主控 Agent A 调用行业分析 Agent B,Agent B 又必须同步调用 SQL 提取 Agent C 和舆情检索 Agent D 时,整个调用链条形成了一条长达 15~30 秒的同步阻塞链。

  • 只要最下游的 Agent D 遇到网络抖动或模型推理稍慢,整个调用链上的所有工作线程和 HTTP 连接全部被挂起;
  • 上游调用方为了防止超时,不断增大 Timeout 阈值,最终导致网关层连接数被打满,产生级联雪崩。

2. 拓扑僵化与环形依赖死锁(Deadlock)

在真实复杂的推理场景中,Agent 之间的交互往往不是严格单向的。例如:

  • 规划 Agent 派发任务给代码生成 Agent;
  • 代码生成 Agent 发现需求定义模糊,需要向知识库检索 Agent 查询,检索 Agent 发现需要补充业务元数据,又反向向规划 Agent 索取上下文;
  • 在同步 RPC 体系下,如果两个并发请求在不同的子步骤中互相等待对方返回,整个工作流立刻陷入死锁。

3. 多播与协作协同的扩展性极差

如果一个任务完成后需要同时通知“合规审计 Agent”、“日志分析 Agent”和“计费 Agent”,在 RPC 模式下,主调方必须硬编码这三个下游的地址并依次或并发调用。一旦新增一个观察者 Agent,就必须修改上游代码,系统耦合度极高。


二、架构演进:基于事件总线的解耦通信体系

为了彻底根治同步调用的脆弱性,我们在架构重构中全面废弃了 Agent 间的点对点 RPC,转向了基于事件驱动架构(Event-Driven Architecture, EDA)的分布式事件总线。

┌─────────────────────────────────┐ │ Distributed Event Bus (NATS) │ └──────┬───────────────────▲──────┘ │ │ Publish / Sub │ │ Publish / Sub ▼ │ ┌────────────────┴───────────────────┴────────────────┐ │ │ ▼ ▼ ┌─────────────────────────┐ ┌─────────────────────────┐ │ Planner Agent (Node) │ │ Data Analysis Agent │ │ ┌─────────────────────┐ │ │ ┌─────────────────────┐ │ │ │ Local Event Router │ │ │ │ Local Event Router │ │ │ └─────────────────────┘ │ │ └─────────────────────┘ │ │ ┌─────────────────────┐ │ │ ┌─────────────────────┐ │ │ │ In-Memory LLM │ │ │ │ Execution Worker │ │ │ └─────────────────────┘ │ │ └─────────────────────┘ │ └─────────────────────────┘ └─────────────────────────┘

在事件驱动体系中:

  1. 彻底解耦:每个 Agent 都是一个完全独立的事件发布者(Publisher)与消费者(Subscriber),彼此不知道对方的 IP、端口和物理拓扑;
  2. 异步非阻塞:Agent 处理完一个阶段的任务后,只需向特定 Topic 发布领域事件(Domain Event),然后立刻释放当前工作协程;
  3. 弹性缓冲:底层的消息中枢(如 NATS JetStream 或 Redis Streams)天然具备流量削峰填谷能力,慢消费者不会拖垮上游。

三、生产级事件封套(Envelope)与路由实现

要让事件在异构的 Agent 网络中被准确解析、溯源和防死锁,标准化的事件数据包(Envelope)设计是重中之重。

以下是我们生产环境中基于 Go 语言实现的事件封套与分发模型:

package bus import ( "context" "encoding/json" "time" ) // AgentEvent 标准事件信封 type AgentEvent struct { EventID string `json:"event_id"` TraceID string `json:"trace_id"` // 全链路追踪 ID SessionID string `json:"session_id"` // 用户会话 ID SourceAgent string `json:"source_agent"` // 事件发起源 EventType string `json:"event_type"` // 事件类型,如: TaskAssigned, StepCompleted HopCount int `json:"hop_count"` // 跳数计数器,防死循环 MaxHops int `json:"max_hops"` // 最大允许跳数 Timestamp int64 `json:"timestamp"` Payload map[string]interface{} `json:"payload"` } type EventHandler func(ctx context.Context, event *AgentEvent) error type EventBus interface { Publish(ctx context.Context, topic string, event *AgentEvent) error Subscribe(ctx context.Context, topic string, handler EventHandler) error } // 安全路由处理:包含跳数检查与反死循环熔断 func SafeHandleEvent(ctx context.Context, event *AgentEvent, handler EventHandler) error { // 1. 防循环风暴检查 if event.HopCount > event.MaxHops { // 超过最大跳数,强制路由到死信队列并报警 return RecordDeadLetter(ctx, event, "Exceeded MaxHops threshold") } // 2. 递增跳数 event.HopCount++ // 3. 执行业务处理 return handler(ctx, event) } func RecordDeadLetter(ctx context.Context, event *AgentEvent, reason string) error { // 生产中落库审计并触发告警通知 return nil }

四、事件总线落地中的关键避坑原则

从 JSON-RPC 切换到事件总线,虽然解决了并发和解耦问题,但带来了分布式系统固有的复杂度。我们在实践中沉淀了以下三条铁律:

1. 严格控制事件跳数(Max Hops)与防风暴熔断

多 Agent 异步交互最怕出现“隐式递归循环”:Agent A 发布事件触达 Agent B,Agent B 的输出又被 Agent C 消费,而 Agent C 再次触发了 Agent A 关心的事件。

  • 治理手段:所有事件必须携带HopCount与全局TraceID。系统默认设置MaxHops = 10。一旦跳数越界,事件总线强行阻断并推送到 Dead Letter Queue(DLQ),同时拉响报警。

2. 消息消费幂等性(Idempotency)保障

在分布式网络中,网络抖动导致的 At-least-once 重投极为常见。如果某个扣费或数据库更新工具被重复消费两次,后果不堪设想。

  • 治理手段:每个 Worker 节点在执行关键变更前,以SessionID + StepID + EventID为复合 Key,在 Redis 中原子抢占 Distributed Lock 并写入执行状态缓存。若已存在成功标记,则直接跳过执行。

3. OpenTelemetry 全链路上下文透传

异步事件总线会打碎传统的线程调用栈(Call Stack),排查问题极难。

  • 治理手段:在事件封套中将 OpenTelemetry 的TraceParent、SpanID作为标准元数据透传。无论事件经过多少个 Agent、经历多少轮消息中转,在 Jaeger / Grafana Tempo 看板中都能渲染出完整连续的有向无环调用图。

五、演进总结与选型指南

下表汇总了点对点 JSON-RPC 与分布式事件总线在多智能体系统中的核心能力对比:

维度点对点 JSON-RPC / HTTP分布式事件总线 (NATS / Redis Streams)
耦合度强耦合(显式依赖下游 IP/端口/契约)零耦合(仅依赖标准事件 Schema)
容错能力差(单点故障引发全链路级联中断)极高(消息持久化,支持 Worker 宕机重拉)
长任务吞吐极低(长连接同步挂起线程池)极高(全异步并发,按事件响应驱动)
调试与排障相对直观(基于 HTTP 状态码)依赖成熟的 TraceID 链路追踪与 DLQ
推荐适用场景2~3 个轻量 Agent 的内部短调用生产级、多角色协同的复杂企业级业务流

多 Agent 协同的本质不是让模型在单机内存里自言自语,而是建立一套稳健、有序的分布式协作契约。放弃脆弱的同步 RPC,拥抱事件驱动架构,是迈向工业级自主体系统的必经之路。

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

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

立即咨询