返回资料库
A2A

将 A2A 与现有智能体框架集成:Hermes Agent 示例

最后更新:2026年7月13日

为什么 A2A 对智能体编排至关重要

Agent2Agent Protocol (A2A) 是 Google 于 2025 年 4 月推出的一项开放标准,用于智能体间通信。它定义了一个 AI 智能体如何发现另一个智能体的能力、向其发送任务、接收流式输出,并跟踪任务的生命周期——所有这些均基于 JSON-RPC 2.0,且不假设双方智能体共享同一框架、同一模型提供方或同一部署拓扑。

A2A 填补了 MCP 未覆盖的一个空白。MCP 将智能体连接到工具和数据源——它是一个工具调用协议。A2A 将智能体连接到智能体。一个需要特定能力(定价逻辑、目录搜索、RFQ 处理)的智能体,可以将工作委派给一个通过 A2A 端点暴露该能力的远程智能体,以 A2A 任务的形式接收结果,然后继续自己的工作流。这两个协议是互补的:MCP 赋予智能体双手,A2A 赋予智能体同事。

A2A 规范 定义了三个核心原语:

  • Agent Card — 位于 /.well-known/agent-card.json 的一个 JSON 文档,描述智能体的身份、能力、技能和服务端点。这是智能体互相发现的方式。
  • Task — 工作单元。客户端通过 message/send(非流式)或 message/stream(流式)发送任务。任务在以下状态间转换:submittedworkinginput-requiredcompletedfailedcanceled
  • Artifact — 任务执行期间产生的结构化输出,在生成时即流式传输给客户端。

对于 B2B 部署而言,其价值主张是具体的:与其构建一个包揽一切的单体智能体,不如组合多个各自拥有一个领域的专业智能体——它们通过协议协调,而非通过共享内存或硬编码的函数调用。

集成问题

大多数现有的智能体框架并不说 A2A。它们有各自的原生 API 接口、各自的任务模型、各自的流式传输机制。Hermes Agent(由 Nous Research 开发)在 /v1/chat/completions 暴露一个 OpenAI 兼容的 API Server,并在 /v1/runs/v1/runs/{id}/events 暴露一个基于 runs 的 SSE 流式接口。OpenClawPOST /v1/responses 提供一个 OpenResponses 兼容的 API。LangGraph 有自己的图执行模型。CrewAI 有自己的 crew 调度。

这些框架都不会为了支持 A2A 而重写其内部实现。它们也不应该如此——其原生 API 很好地服务于各自的生态系统。问题是:它们能否在不修改代码的情况下参与 A2A 智能体网络?

答案是一个桥接层——一个位于 A2A 协议与框架原生 API 之间的组件。桥接层在一侧实现 A2A JSON-RPC 接口(Agent Card、任务生命周期、流式传输),在另一侧翻译为框架的原生调用。框架不知道自己正在被通过 A2A 调用。A2A 客户端也不知道是哪个框架在执行任务。

本文以 Hermes Agent 为示例讲解桥接模式。同一模式适用于 OpenClaw 及其他框架——唯一需要改变的是桥接处理器。

桥接架构

这一模式的一个可运行参考实现是 a2a_daemon_engine——一个 A2A 协议守护进程,以网关模块方式运行,并将执行路由到可插拔的处理器。其架构如下:

A2A Client (any agent or application)
  │
  POST /{endpoint_id}/a2a  (message/send | message/stream)
  │
  ▼
Gateway (auth, routing, SSE client management)
  │
  ▼
A2A Daemon Executor
  │
  resolve_agent(uuid) → Database lookup
  load_agent_handler()  ← data-driven, metadata-based routing
  │
  ├── HermesAgentHandler
  │     → POST /v1/runs → GET /v1/runs/{id}/events → SSE streaming
  │     → POST /v1/chat/completions (non-streaming)
  │
  └── [AnyFrameworkHandler]  ← same interface, different translation
        → framework's native API

桥接层有三层:

  1. A2A 协议层 — 处理 JSON-RPC 分发、Agent Card 服务、任务状态机,以及 A2A SDK EventQueue。它与框架无关,在每一次集成中都是相同的。

  2. 网关传输层 — 处理 HTTP、认证、SSE 客户端生命周期和路由。同样与框架无关。网关拥有线路;桥接层拥有翻译。

  3. 框架处理器 — 唯一与框架相关的代码。它实现一个 ask_model() 接口:接受 A2A 消息部件和上下文,调用框架的原生 API,将响应转换回 A2A 消息部件,并(对于流式传输)将 token 增量转发到 SSE 通道。

添加一个新框架意味着编写一个处理器类。其余一切——协议接口、网关分发、SSE 管理、任务持久化——都是共享基础设施。

示例:Hermes Agent 桥接

HermesAgentHandler 是一个完整的实例。它将 A2A 任务语义桥接到 Hermes Agent API Server。该处理器支持两种执行模式:

非流式:message/sendmessage_response

处理器调用 Hermes API Server 上的 POST /v1/chat/completions——即 OpenAI 兼容端点。请求将转换后的 A2A 消息部件作为 chat completion 负载携带。Hermes 处理请求(模型推理、工具调用、智能体推理)并返回单个响应。处理器将该响应转换为带有 ROLE_AGENT 的 A2A Message,并将其发射到 SDK EventQueue。

客户端收到一个包含完整智能体文本的 JSON-RPC 响应。没有中间状态事件,没有流式分块——请求阻塞直到 Hermes 完成。

流式:message/sendtask_executionstream: true

处理器调用 POST /v1/runs 创建一个 run,然后打开到 GET /v1/runs/{id}/events 的 SSE 连接。Hermes 在事件发生时流式传输:token 增量、推理元数据、工具调用/结果通知、审批请求,以及生命周期事件(run.created、run.completed、run.failed)。

处理器在后台线程中运行一个排空循环。每个 message.delta 事件被推送到网关的 SSE 管理器,以便实时传递给已连接的客户端。处理器将 token 累积到单个缓冲区中。当 run.completed 到达时,累积的文本作为单个 A2A Message 发射到 SDK EventQueue,并且一个 COMPLETED 状态事件仅被推送到 SSE。

这种双路径设计——SSE 用于实时分块,SDK EventQueue 用于最终累积消息——是对 A2A SDK v2 中一个约束的回应,下文将详细讨论。

跨智能体边界的人在环中审批

Hermes 支持人在环中审批门——当智能体需要权限来执行敏感操作时,它会暂停并发出一个审批请求。桥接层将其翻译为 A2A 的 INPUT_REQUIRED 状态,该状态向调用智能体(或人工操作员)发出需要输入的信号。响应通过 POST /v1/runs/{id}/approval 返回,run 继续。

这正是桥接模式体现其价值之处。A2A 将 INPUT_REQUIRED 定义为一等任务状态。Hermes 有自己的审批机制。桥接层将两者相互映射,而调用智能体——它本身可能是一个运行在完全不同框架上的 A2A 客户端——看到的是一个标准协议状态转换,而非一个 Hermes 专有的细节。一个智能体委派链可以包含一个需要人工审批的步骤(采购授权、数据访问决策、报价审批),而 A2A 协议将该门控透明地跨越框架边界传递。

A2A 状态映射

A2A 定义了一个任务状态机:submittedworkinginput-required | completed | failed | canceled。每个框架有各自的事件词汇表。桥接层在两者之间映射。

Hermes 事件到状态的映射:

Hermes SSE 事件 A2A 任务状态 桥接动作
run.created WORKING 注册 run_id 以支持取消
message.delta WORKING 累积 token;逐块发射到 SSE
reasoning.available WORKING 推理元数据——不发射 token
tool.call / tool.result WORKING 仅工具执行元数据
approval.required INPUT_REQUIRED 发射审批分块;存储 pending_approval
run.completed COMPLETED 设置流事件;累积最终文本
run.failed FAILED 发射错误分块;设置 FAILED 状态
POST /v1/runs/{id}/stop CANCELED 通过 tasks/cancel 外部取消
POST /v1/runs/{id}/approval (继续 run) 通过 operation="approval_response" 解决

这张表是桥接层的核心。每一个框架集成都会产生一张等价的表——左侧是框架的原生事件,右侧是 A2A 状态,中间是桥接动作。参考实现中的 HERMES_INTEGRATION.md 文档记录了确切的 Hermes 事件格式、配置键和端到端流程细节。

A2A SDK v2 约束与双路径修复

A2A SDK v2(a2a-sdk==1.0.2)对 on_message_send 路径施加了两项约束,塑造了每一个桥接实现:

  1. 仅允许单个 Message。 向 SDK EventQueue 发射多个 Message 对象会引发 InvalidAgentResponseError: Multiple Message objects received.
  2. 不允许 TaskStatusUpdateEvent。 状态事件会引发 InvalidAgentResponseError: Received TaskStatusUpdateEvent in message mode.

一个朴素的桥接层会为每个 token 增量发射一个 Message——这是自然的流式模式。SDK 拒绝这样做。它还拒绝在 message/send 路径上的状态事件(WORKING、COMPLETED)。

修复方式是一个双路径输出通道:

  • SSE(网关管理): Token 分块实时推送到 SSE。已连接的客户端可以看到流式输出在发生时即呈现。状态事件(WORKING、COMPLETED、FAILED)也仅发送到 SSE。
  • SDK EventQueue: 在流完成后,一个包含完整响应文本的单个累积 Message 被发射到 SDK EventQueue。这是 JSON-RPC message/send 响应返回的内容。

客户端通过 SSE 获得实时流式传输,并通过 SDK 获得干净的单消息 JSON-RPC 响应。两个通道都正常工作;两者都不违反 SDK 约束。这一模式与框架无关——无论后端是 Hermes、OpenClaw 还是任何未来的处理器,它都适用。

将同一模式应用于 OpenClaw

OpenClaw 的 Gateway API 暴露了一个不同于 Hermes 的原生接口,但桥接模式是相同的。一个 OpenClawHandler 会实现相同的 ask_model() 接口,并将 A2A 任务语义翻译为 OpenClaw Gateway 调用:

  • 非流式 映射到 POST /v1/responses,A2A 消息部件被转换为 OpenResponses 输入项。响应被转换回 A2A Message
  • 流式 映射到带 stream: truePOST /v1/responses,消费 SSE 事件流并将 token 增量转发到 A2A SSE 通道。OpenResponses 流式格式使用 response.output_text.delta 表示 token 分块,response.completed 表示完成——事件名称不同,桥接结构相同。
  • 智能体选择 使用 model 字段(openclaw/<agentId>)或 x-openclaw-agent-id 头,从 A2A 智能体元数据映射而来。
  • 会话连续性 利用 OpenClaw 的 previous_response_iduser 字段实现稳定的会话路由,这自然地映射到 A2A 任务持久化。

OpenClaw 的状态映射表如下:

OpenClaw 事件 A2A 任务状态 桥接动作
response.created WORKING 注册响应 ID
response.output_text.delta WORKING 累积 token;发射到 SSE
response.completed COMPLETED 累积最终文本;发射 Message
response.failed FAILED 发射错误;设置 FAILED

相同的列,相同的结构,不同的事件名称。桥接处理器是框架之间唯一需要改变的部分。

配置:元数据驱动的路由

智能体路由由元数据驱动,而非由环境变量驱动。数据库中的每条智能体记录在 metadata JSON 列中携带其处理器配置。对于一个 Hermes 后端的智能体:

{
  "module_name": "a2a_daemon_engine.handlers.a2a_hermes_handler",
  "class_name": "HermesAgentHandler",
  "hermes_api_url": "http://127.0.0.1:8642",
  "hermes_api_key": "hermes-local-key",
  "hermes_model": "hermes-agent",
  "hermes_timeout": 300.0
}

对于一个 OpenClaw 后端的智能体,元数据将指向 OpenClaw 处理器:

{
  "module_name": "a2a_daemon_engine.handlers.a2a_openclaw_handler",
  "class_name": "OpenClawHandler",
  "openclaw_api_url": "http://127.0.0.1:3000",
  "openclaw_api_key": "openclaw-key",
  "openclaw_agent_id": "pricing-agent",
  "openclaw_timeout": 300.0
}

配置解析遵循一条优先级链:智能体元数据(数据库)→ 设置字典 → Config 默认值(环境变量)。按智能体的覆盖优先于全局默认值。两个智能体可以指向不同的框架——一个指向 Hermes 用于推理密集型任务,另一个指向 OpenClaw 用于工作流编排任务——而 A2A 协议接口对调用智能体而言看起来完全相同。

这带来了什么能力

桥接模式赋予你三项难以从零拼装的能力:

1. 带流式传输的智能体间委派。 A2A 客户端智能体可以向一个 Hermes 后端的智能体发送任务,并通过 SSE 接收实时 token 流。调用智能体无需知道远程智能体运行 Hermes——它看到的是一个带有 Agent Card 和 JSON-RPC 接口的 A2A 端点。

2. 跨智能体边界的人在环中审批。 框架原生的审批门(Hermes 审批请求、OpenClaw 操作员审批)映射到 A2A INPUT_REQUIRED 状态。一个智能体委派链可以包含一个需要人工审批的步骤,而 A2A 协议将该状态转换传递回发起智能体或操作员——无论链中每个智能体运行在哪个框架上。

3. 从单一网关进行多框架路由。 同一个网关、同一个执行器、同一个 A2A 协议接口服务于不同框架的处理器。添加一个新框架就是编写一个处理器类并插入一条智能体记录——不需要新部署,不需要新协议实现。

该参考实现还支持用于无服务器 A2A 的 AWS Lambda 调度、带双向流式传输的实验性 gRPC 传输,以及双后端持久化(DynamoDB 或 PostgreSQL),并通过复合分区键实现多租户隔离。a2a_daemon_engine 仓库及其 Hermes 集成指南包含完整的实现、配置参考和状态映射细节。


一个中型分销商需要报价智能体与目录智能体对话,目录智能体与库存智能体对话——每个智能体由不同的框架支撑,每个智能体由不同的团队拥有。A2A 为这些智能体提供一个共享协议。桥接层让 Hermes Agent、OpenClaw 以及任何其他框架无需重写内部实现即可参与。a2a_daemon_engine 是该桥接模式的一个可运行参考实现,以 Hermes Agent 为示例。

申请一次限定范围的构建

一周发现。你会得到一份系统清单、工作流地图和固定范围——无论你是否与我们一起构建。

想为您的系统构建这个吗?

这里的每份文档都来自真实的生产工作。如果您有目标系统和工作流想法,我们可以在一周内确定范围。

申请定制开发

为期一周的发现阶段。您会拿到系统清单、工作流地图和固定范围——无论您最终是否与我们合作开发。