Skip to content

mq9:RobustMQ 为 AI Agent 设计的通信层

从一个真实的问题出发

人和人之间有飞书、钉钉、邮件。我发出去,你空了来看,不需要同时在线。这件事我们觉得理所当然,因为人类的异步通信基础设施已经非常成熟。

Agent 和 Agent 之间呢?

Agent 不是服务——它是临时的,任务完成就消亡,可能只存在几秒钟。Agent A 给 Agent B 发消息,B 不在线,消息直接丢了。没有标准机制保证"我发出去的消息,对方上线后能收到"。每个构建多 Agent 系统的团队,都在用自己的临时方案绕过这个问题——HTTP callback、Redis pub/sub、轮询数据库、自研任务队列。能用,但都是绕路。

更进一步,如果两个 Agent 运行在不同人的不同机器上,今天完全没有办法让它们直接通信。每个 Agent 系统都是孤岛。

这是 mq9 想解决的问题。


mq9 是什么

mq9 是一个为 AI Agent 设计的消息 broker。不是协议,不是 SDK,不是框架——是一个可部署的服务。docker run 一行命令,Agent 就有了异步通信的能力。

mq9 是 RobustMQ 的第五个原生协议层,与 MQTT、Kafka、NATS、AMQP 并列,生长于 RobustMQ 的底层统一存储架构之上。不是插件,不是外部集成,是原生能力。

bash
docker run -d -p 4222:4222 robustmq/robustmq:latest

这一行之后,Agent 就可以创建邮箱、发消息、订阅广播。

mq9 只解决通信问题——消息怎么可靠送达。至于消息里装什么、怎么用、业务语义是什么,mq9 不管。消息内容是 byte 数组,不解析、不校验、不限制。


核心概念:邮箱

mq9 只有一个核心抽象:邮箱(MAILBOX)

邮箱是 Agent 的通信地址。临时的,TTL 驱动生命周期,到期自动销毁。Agent 为每个任务申请一个邮箱,拿到一个 mail_id,这就是它在这个任务里的通信地址。任务结束,邮箱自动过期清理。不需要注销,不需要手动删除。

mail_id 不可猜测即安全边界。 mail_id 是系统生成的不可猜测字符串。知道 mail_id 就能往里发消息、能订阅——就像知道邮件地址就能发邮件。不知道 mail_id 就无从操作。没有 token,没有 ACL,没有额外的权限控制。

一个 Agent 可以同时持有多个邮箱——一个接收任务分配,一个接收审批结果,完全隔离,互不干扰。

邮箱分两种:

私有邮箱公开邮箱
mail_id系统生成,不可猜测用户自定义,有意义的名字
可发现性不公开,只有知道 mail_id 的 Agent 能找到自动注册到 PUBLIC.LIST,任何 Agent 可发现
适合场景点对点私信、任务结果回传任务队列、公共频道、能力公告

公开邮箱的 mail_id 本身就是地址,起一个有意义的名字——task.queueanalytics.result——比 UUID 更容易被其他 Agent 发现和理解。


三件事,六条命令

mq9 的全部操作只有三件事:创建邮箱、发消息、订阅邮箱。

创建邮箱

bash
# 私有邮箱
nats req '$mq9.AI.MAILBOX.CREATE' '{"ttl":3600}'
{"mail_id":"mail-d7a5072lko83gp7amga0-d7a5072lko83gp7amgag","is_new":true}

# 公开邮箱,自动注册到 PUBLIC.LIST
nats req '$mq9.AI.MAILBOX.CREATE' '{"ttl":3600, "public":true, "name":"task.queue", "desc":"任务队列"}'
{"mail_id": "task.queue"}

ttl 是邮箱的生命周期,单位秒。到期自动销毁,消息随之清理。

发消息

知道 mail_id 即可发送,无需任何授权。消息按优先级发送:

bash
nats pub '$mq9.AI.MAILBOX.MSG.mail-d7a5072lko83gp7amga0-d7a5072lko83gp7amgag'          'payload'  # 常规(默认,无后缀)
nats pub '$mq9.AI.MAILBOX.MSG.mail-d7a5072lko83gp7amga0-d7a5072lko83gp7amgag.urgent'   'payload'  # 紧急
nats pub '$mq9.AI.MAILBOX.MSG.mail-d7a5072lko83gp7amga0-d7a5072lko83gp7amgag.critical' 'payload'  # 最高优先级,优先处理

三个优先级:

级别语义典型场景
critical最高优先级,优先处理中止信号、紧急指令、安全事件
urgent紧急,时间敏感任务中断、时间敏感指令
normal常规通信(默认,无后缀)任务分发、结果返回、审批请求

存储层保证优先级顺序。边缘设备离线 8 小时后上线,先收到紧急停机指令,再收到常规配置更新。消费方无需自行排序。

订阅邮箱

bash
nats sub '$mq9.AI.MAILBOX.MSG.mail-d7a5072lko83gp7amga0-d7a5072lko83gp7amgag'           # 仅常规(默认)优先级
nats sub '$mq9.AI.MAILBOX.MSG.mail-d7a5072lko83gp7amga0-d7a5072lko83gp7amgag.*'         # 所有优先级(critical + urgent + normal)
nats sub '$mq9.AI.MAILBOX.MSG.mail-d7a5072lko83gp7amga0-d7a5072lko83gp7amgag.critical'  # 仅最高优先级

订阅即全量推送——所有未过期消息立即推送,后续新消息实时推送。Agent 重连后不会漏消息,不需要单独的拉取接口。

没有已读未读,没有消费位点,没有 QUERY 命令。每条消息带唯一 msg_id,客户端自行去重。

禁止的操作:

bash
nats sub '$mq9.AI.MAILBOX.MSG.*'  # 禁止,broker 拒绝
nats sub '$mq9.AI.MAILBOX.MSG.#'  # 禁止,broker 拒绝

订阅必须精确到 mail_id,不允许通配符订阅所有邮箱。


发现公开邮箱

$mq9.AI.PUBLIC.LIST 是系统内置地址,broker 维护,不接受用户写入。

public:true 的邮箱创建后自动注册到 PUBLIC.LIST,TTL 到期自动移除。Agent 无需手动维护注册表。

bash
nats sub '$mq9.AI.PUBLIC.LIST'

订阅即全量推送——当前所有 public 邮箱立即推送,后续新增和移除实时推送。Agent 启动后订阅一次,就能持续感知网络里有哪些公开频道。


为什么现有方案不够

HTTP:要求双方同时在线。Agent 频繁上下线,HTTP 的假设不成立。加 retry loop 是在同步协议上贴异步补丁,越贴越复杂。

Redis pub/sub:没有持久化。对方不在线,消息直接丢。加 Redis Streams 可以持久化,但引入了 consumer group、offset 管理——为发一条 Agent 消息,不值得。

Kafka:为高吞吐数据管道设计。topic 需要预创建,partition 需要规划,consumer group 需要管理。Agent 是临时的,Kafka 的资源模型假设长期存在、精心维护,根本不匹配。

NATS Core:纯内存转发,没有持久化,对方不在线消息直接丢。做不了邮箱。

JetStream:stream、consumer、offset、replay,一整套对标 Kafka 的语义。为 Agent 发个消息,概念太重。

这些方案有一个共同假设:对方在线。Agent 频繁上下线这个最本质的特征,在所有现有方案里都是需要绕过去的问题。mq9 不绕路——store-first delivery,消息到达先写存储,持久化是默认行为,不是可选项。


为什么选择 NATS 协议

mq9 兼容 NATS 协议。所有 NATS 客户端 SDK——Go、Python、Rust、JavaScript、Java、.NET——直接就是 mq9 的客户端,零生态成本。

选择 NATS 有三个原因:

第一,Agent 天然懂 NATS。 LLM 在训练过程中接触了大量 NATS 的代码和文档。pub/sub、subject 寻址、queue group——这些概念已经在模型的先验知识里。mq9 不发明新概念,站在 Agent 已经懂的东西上定义语义约定,采用成本为零。

第二,NATS 的 subject 模型天然适合邮箱寻址。 $mq9.AI.MAILBOX.MSG.mail-d7a5072lko83gp7amga0-d7a5072lko83gp7amgag.critical——一行字符串,清晰表达:协议、场景、消息类型、邮箱地址、优先级。裸地址(无后缀)承载常规优先级消息,通配符让 Agent 灵活选择订阅粒度。

第三,NATS 足够轻。 协议本身是文本协议,解析简单,连接开销小,适合大量临时 Agent 频繁上下线的场景。


八个场景

场景一:点对点,离线可达 子 Agent 完成任务,结果发回主 Agent。主 Agent 可能不在线,不需要等待。

bash
nats pub '$mq9.AI.MAILBOX.MSG.m-orchestrator' '{"task_id":"t-001","result":"done"}'

场景二:任务广播,竞争消费 Orchestrator 创建公开任务队列,多个 Worker 竞争消费,每条任务只被一个 Worker 处理。

bash
nats req '$mq9.AI.MAILBOX.CREATE' '{"ttl":86400,"public":true,"name":"task.queue"}'
nats sub '$mq9.AI.MAILBOX.MSG.task.queue.*' --queue workers

场景三:能力发现 Agent 启动,订阅 PUBLIC.LIST,发现网络里有哪些公开频道,决定订阅哪些。

bash
nats sub '$mq9.AI.PUBLIC.LIST'

场景四:优先级,离线边缘设备 云端给离线边缘设备发紧急指令和普通配置。设备上线后紧急指令先到。

bash
nats pub '$mq9.AI.MAILBOX.MSG.m-device-001.critical' '{"cmd":"abort"}'
nats pub '$mq9.AI.MAILBOX.MSG.m-device-001'          '{"cmd":"update_config"}'

场景五:异步 request-reply Agent A 问离线的 Agent B,B 上线后处理并回复。

bash
# A 发请求,payload 里带 reply_to
nats pub '$mq9.AI.MAILBOX.MSG.m-uuid-b' '{"reply_to":"m-uuid-a","payload":"..."}'
# B 上线后处理,结果发回 A 的邮箱
nats pub '$mq9.AI.MAILBOX.MSG.m-uuid-a' '{"correlation_id":"...","result":"..."}'

场景六:人机混合工作流 Agent 发审批请求到审批员邮箱,审批员回复到 Agent 邮箱。人和 Agent 用同一套协议。

场景七:广播告警 Agent 发现异常,发到公开频道,所有订阅者响应。离线的 handler 上线后也能收到未过期的告警。

bash
nats req '$mq9.AI.MAILBOX.CREATE' '{"ttl":3600,"public":true,"name":"alert.anomaly"}'
nats pub '$mq9.AI.MAILBOX.MSG.alert.anomaly.critical' '{"type":"anomaly","confidence":0.95}'

场景八:Orchestrator 感知 Worker 状态 多个 Worker 定期上报状态到各自邮箱,Orchestrator 订阅感知。Worker TTL 到期,Orchestrator 感知消亡。


mq9 和 RobustMQ 的关系

mq9 不是一个独立的产品,是 RobustMQ 的一部分。

RobustMQ 是用 Rust 构建的统一消息引擎——单个二进制,零外部依赖,原生支持 MQTT、Kafka、NATS、AMQP 四种协议,底层统一存储。mq9 是从这个地基上生长出来的第五个协议层。

对用户来说,mq9 就是一个 broker。部署一个 RobustMQ,IoT 设备通过 MQTT 发数据,分析系统通过 Kafka 消费,Agent 通过 mq9 协作——同一个 broker,同一份存储,零桥接,零复制。


什么 mq9 不是

  • 不是更好的 NATS。 mq9 不跟 NATS 竞争通用消息场景。兼容 NATS 协议是为了零生态成本,不是为了替代。
  • 不是数据管道。 不替代 Kafka 做高吞吐流处理。
  • 不是服务间 RPC。 不替代 HTTP/gRPC 做始终在线的服务通信。
  • 不是编排框架。 mq9 搬运消息,不做决策。编排逻辑属于上层框架。

我们的判断

Agent 之间缺乏异步通信机制,这个问题是真实的。协议层和基础设施层分别做了努力,但"Agent 原生语义 + 原生 store-and-forward + 轻量开箱即用 + 可私有部署"这个组合,今天没有人做。这是 mq9 填的空白。

mq9 还在建设中。协议在迭代,功能在完善。这不是一个做完的产品,是一个正在生长的方向。

只要你需要跑多个 Agent,你就需要 mq9。

🎉 既然都登录了 GitHub,不如顺手给我们点个 Star 吧!⭐ 你的支持是我们最大的动力 🚀