当多个 AI Agent 需要协同工作时,Agent 之间的通信机制成为关键基础设施。Aqua(AQUA Queries & Unifies Agents)是一个专为 AI Agent 设计的 CLI 消息工具,它通过简洁的 JSON 消息协议实现分布式 Agent 间的可靠通信。与 Cloudflare Agents 框架偏重状态编排、Claude Code 聚焦终端编码、HuggingFace Skills 专注技能定义不同,Aqua 解决的问题更加基础但至关重要:如何让不同 Agent 通过命令行界面进行结构化的消息传递。
Aqua 协议的核心设计理念
Aqua 的核心设计哲学是将每个 Agent 视为一个独立的通信节点,通过 P2P 网络实现直接连接。其协议设计遵循几个基本原则:每条消息都是独立的 JSON 对象,采用 NDJSON(Newline Delimited JSON)格式进行帧分割;所有消息共享一个轻量级的信封结构,包含消息类型、唯一标识符、发送者与接收者信息、时间戳以及主题标签;具体的业务负载则通过 JSON Schema 进行约束验证。
这种设计的优势在于它既保证了消息的标准化格式,又为不同业务场景提供了足够的扩展灵活性。Aqua 基于 libp2p 构建底层网络通信,这意味它天然支持端到端加密、节点身份验证以及跨网络的中继转发能力。Agent 节点可以通过官方中继服务(aqua-relay.mistermorph.com)实现防火墙后的通信,也可以配置直接连接模式供同一网络内的节点使用。
消息信封结构与类型系统
Aqua 协议定义了一个通用的消息信封结构,它是所有消息的公共容器。信封中的核心字段包括:id 字段作为消息的唯一标识符,用于消息追踪和响应关联;type 字段标识消息的高层类别,常见取值有 event(事件通知)、request(请求)、response(响应)和 error(错误);topic 或 channel 字段用于 Pub/Sub 路由,接收方根据订阅关系过滤消息;from 和 to 字段分别标识发送方和接收方的 Agent 标识。
在类型系统方面,Aqua 采用了请求 - 响应模式与事件驱动模式相结合的设计。当一个 Agent 需要调用另一个 Agent 的能力时,它会发送 type 为 request 的消息,消息体中包含目标 Agent 标识(agent 字段)、要执行的动作(action 字段)以及输入参数(input 字段)。被调用 Agent 处理完成后,会返回 type 为 response 的消息,其中包含状态码(status 字段,取值为 ok 或 error)和输出结果(output 字段)。对于异步事件通知场景,则使用 type 为 event 的消息,接收方根据 topic 进行过滤处理。
Pub/Sub 路由机制详解
Aqua 的路由机制借鉴了云原生消息队列的设计理念,但将其精简适配到 CLI 场景。每个 Agent 可以订阅感兴趣的主题,当有消息发布时,Aqua CLI 扮演本地消息代理的角色,它会检查消息的 topic 字段,将消息转发给所有订阅该主题的 Agent。这种设计允许一对多和多对多的通信模式,Agent 无需维护复杂的连接管理逻辑,路由逻辑由 Aqua 统一处理。
在实际部署中,Pub/Sub 路由可以支持多种拓扑结构。对于简单的双 Agent 通信,发送方直接指定接收方的 ID,消息点对点传递;对于需要广播的场景,发送方可以将 topic 设置为广播主题,所有订阅该主题的 Agent 都会收到消息;对于工作流场景,可以设计请求主题和响应主题,Agent 向请求主题发送任务,多个工作 Agent 订阅该主题并竞争处理,处理结果发送到对应的响应主题。
JSON Schema 约束的实现策略
Aqua 协议的可扩展性很大程度上依赖于 JSON Schema 的约束机制。虽然 Aqua 协议本身定义了消息信封的结构,但对于 payload(负载内容)的具体格式并没有硬编码,而是交由每个 topic 独立定义 Schema 进行验证。这种设计允许不同的业务场景定义自己的消息格式,同时保证同一主题内的消息具有一致的结构。
以请求消息为例,其 Schema 定义要求 payload 必须包含三个必填字段:agent(目标 Agent 标识)、action(要执行的动作)和 input(结构化输入参数)。可选的 metadata 字段可以携带追踪 ID、用户标识等元数据。响应消息的 Schema 则要求 status 和 output 为必填字段,当 status 为 error 时,error 对象必须包含错误码(code)和错误信息(message),可选的 details 字段可以提供详细的调试信息。
这种 Schema 驱动的设计带来了几个实际好处。首先,它提供了运行时验证能力,接收方可以在解析消息前验证其结构是否符合预期,拒绝格式错误的消息;其次,它支持文档自动生成,开发者可以从 Schema 推断出消息格式,无需额外维护接口文档;最后,它便于版本演进,当需要扩展消息格式时,只需更新 Schema 定义并确保向后兼容即可。
工程实践中的关键参数配置
在生产环境中部署 Aqua 时,有几个关键参数需要关注。连接模式配置方面,通过 --relay-mode 参数可以控制连接策略:auto 模式会优先尝试直接连接,失败后自动切换到中继模式;off 模式仅支持直接连接;required 模式强制使用中继。当 Agent 运行在防火墙或 NAT 后的环境中时,建议使用 auto 模式并配置官方中继端点。
消息持久化方面,Aqua 默认将接收到的消息存储在 inbox 目录,发送的消息存储在 outbox 目录。通过 aqua inbox list --unread 可以查看未读消息,该命令会自动将消息标记为已读。对于需要可靠传递的场景,可以在发送端实现重试逻辑,并通过 aqua outbox list 查看消息的发送状态。
身份验证与信任建立是 Aqua 安全模型的核心。通过 aqua contacts add <address> --verify 可以添加联系人并发起身份验证请求,这需要带外确认对方的身份指纹。验证完成后,该联系人会被标记为可信,后续通信可以自动使用端到端加密。对于临时通信场景,可以不验证直接添加联系人,但通信安全性会相应降低。
与现有技术栈的集成路径
Aqua 的设计使其可以与现有的 Agent 开发框架无缝集成。对于基于 Python 的 Agent 项目,可以通过 subprocess 调用 aqua CLI 或使用 libp2p 的 Go SDK 编写原生客户端;对于基于 Node.js 的项目,可以使用 @libp2p 包直接接入 Aqua 网络。由于 Aqua 支持 --json 参数输出结构化数据,集成方可以方便地解析命令输出并转换为内部数据模型。
在监控系统集成方面,Aqua 消息本身携带的元数据字段可以用于构建追踪链路。通过在 metadata 中注入 trace_id,不同系统间的请求可以串联起来形成完整的调用链。同时,Aqua 的 inbox/outbox 本地存储也提供了基础的审计能力,运维人员可以查询历史消息记录进行问题排查。
总结与适用场景评估
Aqua CLI 为 AI Agent 提供了一套轻量级但功能完备的通信基础设施。它不依赖于特定的 Agent 框架,不强制规定 Agent 的内部实现,只需各 Agent 遵循统一的 JSON 消息格式即可实现互操作。这使得 Aqua 特别适合以下场景:多供应商 Agent 组成的混合团队,需要一个与语言和框架无关的通信协议;需要在隔离网络环境中部署的 Agent 集群,通过中继实现跨防火墙通信;对消息格式有严格验证要求的合规场景,利用 JSON Schema 确保数据结构一致性。
然而,Aqua 也有其局限性。作为 CLI 工具,它的实时性受限于进程启动和 stdout 解析的开销,对于超低延迟场景可能不够理想。此外,其 P2P 模型的信任建立需要带外操作,在需要中心化授权的场景下可能需要额外的适配层。总体而言,Aqua 代表了一种务实的设计思路:在保持协议简洁性的同时,通过结构化的消息格式和 Schema 约束为 Agent 间通信提供必要的可靠性保障。
资料来源:本文技术细节参考 Aqua 官方 GitHub 仓库(github.com/quailyquaily/aqua)及项目文档。