A2A(Agent-to-Agent,智能体对智能体)

A2A 是开放的 Agent2Agent 协议(v1.0,由 Linux Foundation 托管),用于独立 AI agent 之间的通信。Hermes A2A 插件双向工作:你的 agent 可以把其他 A2A agent 当工具调用,其他 agent 也可以通过 HTTP 把任务发给你的 Hermes。

它可与任何 A2A 兼容的对等方互操作——另一个 Hermes、LangChain、CrewAI、Google ADK agent,或任何基于官方 a2a-sdk 构建的东西。

何时用 A2A

  • 跨机器的 Hermes ↔ Hermes——让你的桌面 agent 把任务交给服务器上的 Hermes,或反之,各自拥有自己的记忆、工具和凭据。
  • 委派给专家 agent——在其 Agent Card 上声明了 web_search/research/coding 技能的对等方可在对话中途被发现并调用。
  • 作为可被调用的服务——把你的 Hermes 暴露出去,让其他框架的 agent 能给它发任务。

当你想让多个 agent 跑在同一台机器上时,优先用委派(进程内子 agent)或看板(持久的多 profile 工作队列)——A2A 用于跨越进程/机器/框架边界。

启用

hermes gateway setup      # 选 A2A

或在 ~/.hermes/config.yaml 中:

gateway:
  platforms:
    a2a:
      enabled: true
      extra:
        port: 9900

出站客户端工具以 a2a 工具集形式提供,默认关闭——按平台启用:

hermes tools enable a2a --platform cli        # CLI/TUI 会话
hermes tools enable a2a --platform telegram   # 或任何消息平台
hermes tools enable a2a --platform a2a        # 让入站 A2A 任务调用对等方(agent 链式调用)

这些工具在每种进程类型中都可用——CLI、TUI、网关和 cron——无需启用入站平台。

出站:调用其他 agent

启用 a2a 工具集后,agent 获得:

工具作用
a2a_discover(url)拉取并总结一个对等方的 Agent Card
a2a_call(agent, message, context_id?)发任务,拿回复;通过 context_id 多轮
a2a_list()已配置的对等方、已保存的会话、指标
a2a_history(context_id)召回一段持久化的 A2A 会话
a2a_orchestrate(capability, message, mode?)把任务扇出到所有声明了某能力的对等方(all / first / best)

在 config.yaml 中配置已知对等方:

a2a_agents:
  researcher:
    url: "http://research-box.local:9900"
    auth: { type: bearer, token: "..." }
    timeout: 120
    capabilities: [web_search, research]

然后直接提问即可:"让 researcher agent 总结今天 arXiv 上的新帖。" 直接给 URL 也行——a2a_call 接受任何 A2A 端点。

入站:成为可被调用的服务

启用平台后,Hermes 提供:

  • Agent Card,位于 GET /.well-known/agent-card.json(v1.0 规范路径;旧版 agent.json 也响应)——声明你 agent 的名字、技能(派生自已启用的工具集)和认证要求。
  • JSON-RPC 2.0,位于 POST /——v1.0 规范方法(SendMessage、SendStreamingMessage、GetTask、ListTasks、CancelTask、SubscribeToTask、推送通知配置 CRUD),加上 1.0 之前的路径风格别名(message/send 等)。
  • 面向 SendStreamingMessage 的 SSE 流式,帧为符合规范的 JSON-RPC 封装。
  • 面向长时间任务的推送通知(webhooks),HMAC-SHA256 签名。

入站任务被注入一个活跃的网关会话——与服务你其他渠道的是同一个 agent、记忆和工具——最终回复作为任务结果返回给调用方。会话以 A2A contextId 为键,因此对等方可以进行多轮交流。

互操作性已对照官方 Python a2a-sdk 验证(卡片解析、SendMessage、流式)。

安全模型

默认安全;每一步放宽都是显式的:

  • 无 token ⇒ 仅 localhost。 服务器绑定 127.0.0.1。对外暴露需要 bearer token 且显式设置 A2A_HOST。
  • 按对等方发 token——A2A_PEER_TOKENS="alice:tok1,bob:tok2" 给每个对等方各自的凭据;已认证的名字用于限流、信任和审计。
  • 提示注入过滤——入站文本会被过滤并当作不可信的对等方输入。远程对等方无法调用操作者的斜杠命令。
  • 出站脱敏——回复中形如凭据的字符串(API key、JWT、token)会被擦除。
  • 审计日志——每次交流都追加到 ~/.hermes/a2a_audit.jsonl。
  • 防循环——按上下文的轮次上限阻止两个 agent 无限对打。

配置参考

环境变量默认值含义
A2A_PEER_TOKENS(未设置)按对等方的凭据 name:token,…(推荐)
A2A_BEARER_TOKEN(未设置)共享 token;身份回退到调用方 IP
A2A_HOST127.0.0.1绑定主机——仅在设置了 token 时才放宽
A2A_PORT9900入站端口
A2A_AGENT_NAME由主机名派生Agent Card 上的名字
A2A_PUBLIC_URL(未设置)卡片上声明的可路由 URL(反向代理 / k8s)
A2A_TRUSTED_PEERS(未设置)已认证身份的允许列表
A2A_ALLOW_ALL_USERSfalse允许任何已认证对等方(仅开发用)
A2A_RATE_LIMIT60每身份每分钟请求数
A2A_MAX_PINGPONG_TURNS5每上下文防循环轮次上限(最大 20)
A2A_REPLY_TIMEOUT300等待 agent 回复的秒数。孤儿任务清扫在该窗口过去前绝不会判任务失败(下限 300s),也绝不会在请求仍在等待它时判失败
A2A_PUSH_SECRETbearer token推送通知签名的 HMAC 密钥
A2A_ADVERTISED_TOOLSETS全部已注册限制 Agent Card 上出现哪些技能

在反向代理或 Kubernetes Service 之后,设置 A2A_PUBLIC_URL(或依赖 X-Forwarded-Host/X-Forwarded-Proto),让 Agent Card 声明一个对等方真正能回调的 URL。

快速测试

# 从另一台机器 / 另一个 agent:
curl http://your-host:9900/.well-known/agent-card.json

curl -X POST http://your-host:9900/ \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <token>' \
  -d '{"jsonrpc":"2.0","id":1,"method":"SendMessage",
       "params":{"message":{"messageId":"m1","role":"ROLE_USER",
                 "parts":[{"text":"What tools do you have?"}]}}}'

故障排查

  • 对等方访问不到卡片 URL——卡片声明的是你的绑定地址;把 A2A_PUBLIC_URL 设为外部可路由 URL。
  • 401 Unauthorized——token 不匹配;检查服务器上的 A2A_PEER_TOKENS/A2A_BEARER_TOKEN 和对等方的 auth: 块。
  • 服务器不肯绑定非 localhost——这是设计使然:先设 bearer token,再 A2A_HOST=0.0.0.0。
  • 长任务回复超时——调大 A2A_REPLY_TIMEOUT(孤儿清扫跟随它,所以迟到的回复会被存储而非丢弃),或让调用方注册推送通知配置并轮询 GetTask。