news 2026/6/26 4:57:55

A2A 协议落地 —— 从“前瞻设计“到“标准化接入“

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
A2A 协议落地 —— 从“前瞻设计“到“标准化接入“

讨论 MCP 时,我们用"标准协议替代手写胶水"解决工具暴露问题。但那是"纵向"的——Agent 怎么调用工具。本文讨论"横向"的问题:当有多个 Agent 要相互协作,或者外部系统想把 Shop-Agent 当成一个黑盒能力直接调用时,他们怎么发现 Shop-Agent 能做什么、怎么把任务提交给它、怎么拿到结果?

答案是 A2A(Agent-to-Agent)协议。与 MCP 一样,A2A 本身不是"功能",是"接口标准化"——它不替代业务逻辑,但让业务逻辑能被更多人、更多系统发现和使用。


先看问题:外部系统怎么"用" Shop-Agent?

在没有标准协议之前,外部系统要集成 Shop-Agent 只有两条路:

  1. 直接调 HTTP API:看源码找到对话端点,自己构造请求体、解析响应格式。问题是这套接口是"为人设计的"——同步阻塞、一次一问、没有任务概念。
  2. 用 WebSocket:更低延迟但协议完全自定义。

两个方案的共同问题:没有人能仅凭"标准约定"就知道 Shop-Agent 对外暴露了什么。你永远需要看源码或文档——这就是胶水。A2A 的核心价值不在于"更快"或"更准",在于让机器通过标准协议自动发现和调用 Agent


A2A 协议的四层设计

以 Google A2A 规范为参考,实现了四层:

  • P0 异步任务:提交任务并返回task_id,支持轮询结果和取消——区别于同步 HTTP API 的核心能力。
  • P1 Webhook:任务完成后主动回调订阅方,HMAC 签名防伪造,替代高频轮询。
  • P2 对话共享:外部系统可拉取历史消息,让多个 Agent 读同一段上下文,避免重复提问。
  • P3 健康检查:不只报告进程存活性,对 LLM、向量库、Redis、MCP Server 逐一做依赖探测。

配合Agent CardGET /.well-known/agent-card.json),外部系统在访问任何业务 API 之前就先知道这个 Agent 叫什么、能做什么、能力边界在哪。


核心设计决策

实现中几个关键决策值得展开聊聊——不是"怎么写",而是**“为什么这么选”**。

1. Agent Card 与 MCP 的数据同源

Agent Card 和 MCP 的tools/list都在描述"Shop-Agent 能做什么"——如果两套描述来自不同数据源,早晚会不一致。所以Agent Card 的 skill 列表直接从SkillRegistry生成,与 MCP 共享同一份数据。skills/目录下的 Markdown 文件是唯一的 truth source,加一个 skill 两处自动同步。

Card 里除了 skill 列表,还声明了capabilities.asyncTasks=true——这是 A2A 协议区别于普通 REST API 的关键字段。外部系统看到它就明白:任务异步执行,需要轮询或等 Webhook 回调。

首次构建触发冷启动,之后内存缓存命中——对 discovery 端点来说足够了。

2. 异步任务的"薄壳"模式

A2A 的任务 API 不是另起炉灶重写一套 Agent 调用逻辑。提交任务后立即创建任务记录(状态pending),返回task_id,然后在后台异步调已有的对话服务。

这是刻意为之——只在现有同步调用外面包一层异步外壳。好处很明显:A2A 层薄到不需要维护自己的 Agent 逻辑,所有意图识别、路由、工具调用的改进自动对 A2A 入口生效。

任务状态机只有五个值:pending → running → completed | failed | cancelledcancelled是终态不可恢复。列表接口支持分页,当前使用内存存储。

3. Webhook 与轮询的取舍

轮询方案最简单:每 N 秒查一次任务状态。但高频轮询浪费带宽,低频轮询增加端到端延迟。

Webhook 是 push 模式——任务完成后主动 POST 到订阅方。代价是订阅方需要暴露 HTTP 端点,而且需要防止伪造回调。所以加上了 HMAC-SHA256 签名:注册时提供secret,每次回调在X-A2A-Signature头携带签名。订阅有 TTL 过期机制,内部定时清理。

两个方案不是非此即彼——A2A 协议同时支持轮询和 Webhook,集成方按自己的场景选择。轻量集成(比如脚本)用轮询;生产级集成(n8n、Dify)用 Webhook。

4. 对话共享:A2A 层的公共存储

多 Agent 协作有一个常见痛点:BuyerAgent 问了用户订单号,轮到 MediatorAgent 时又要再问一遍。A2A 层的对话共享就是解这个的——每次对话完成后自动存入公共存储,外部系统通过 API 拉取历史。

公共存储根据数据特点保存到 Redis 或数据库中。

5. 健康检查与服务降级

健康检查对 LLM、向量库、Redis、MCP Server 等依赖做独立探测,返回各自状态。上游编排系统可据此做降级路由——比如 LLM 不可用时暂停任务分发、向量库断连时 RAG 退化为纯 BM25。


A2A + MCP 的职责边界

这两个协议经常被放在一起讨论,但它们的职责完全不重叠:

业务逻辑层

Skill

RAG

DisputeCoordinator

Emotion Detection

MCP 层 — Agent → Tool

工具暴露

资源访问

Schema 自描述

A2A 层 — Agent ↔ Agent

发现

提交任务

轮询

Webhook

A2A 管"谁跟谁说话"——发现 Agent、提交任务、等结果。MCP 管"手里有什么工具"——列出工具、调工具、取资源。两层互不重叠:A2A 不关心 ReActAgent 调了哪个 tool,MCP 不关心任务是谁提交的。


MCP 和 A2A 不能提升意图识别准确率,不能降低 RAG 延迟。它们解决的是另一个层级的问题:当你把系统做完了,谁能"看见"它?如果没有标准协议,答案是"只有你自己"——因为别人要读懂你的源码才知道怎么调用你。有了 MCP 和 A2A,任何遵循相同协议的系统都可以自动发现你、调用你——不需要看源码,不需要写胶水。

配合 MCP 实践,MCP 管纵向(Agent → Tool),A2A 管横向(Agent → Agent),两协议构成了 Shop-Agent 的标准化层。接入成本从"读源码翻文档"降为"读一张 Agent Card + 调一次tools/list"。

实现上有一条核心原则值得单拎出来:A2A 是对外的门,不是对内的水管道。ReActAgent ↔ ToolService 同进程内走直接函数调用就够了——不必把 JSON-RPC 序列化强塞进进程内部。反过来,也没有把DisputeCoordinator内部的 BuyerAgent/SellerAgent/MediatorAgent 拆成独立进程走 A2A 通信——因为它们在同一进程中闭环,拆了只增加网络开销,没有显性收益。知道什么时候不用一个协议,和知道什么时候用它一样重要。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/26 4:56:21

华为OD机试新系统真题【设计能量管理系统】

设计能量管理系统(C/C++/Py/Java/Js/Go)题解 华为OD机试新系统真题 华为OD上机考试新系统真题 6月24号 100分题型 华为OD机试新系统真题目录点击查看: 华为OD机试新系统真题题库目录|机考题库 + 算法考点详解 题目内容 设计一个能量管理系统,用于管理多种能源的生产、消耗…

作者头像 李华
网站建设 2026/6/26 4:54:28

问题解决策略动态规划训练2

ai写的。问题 A: 3.1.2 Score Inflation 总分题目描述学生在我们 USACO 的竞赛中的得分越多我们越高兴。我们试着设计我们的竞赛以便人们能尽可能的多得分,这需要你的帮助。我们可以从几个种类中选取竞赛的题目,这里的一个“种类”是指一个竞赛题目的集合…

作者头像 李华
网站建设 2026/6/26 4:54:17

Python实战AES-CBC数据加密:原理、实现与安全实践

1. 项目概述:为什么选择AES-CBC模式进行数据加密?在数据安全领域,加密是保护信息机密性的基石。作为一名开发者,我经常需要在项目中处理敏感数据,比如用户的个人身份信息、配置凭证或者应用内的通信内容。直接存储或传…

作者头像 李华
网站建设 2026/6/26 4:52:55

构建企业级Java接口测试框架:从契约驱动到CI/CD集成

1. 项目概述:为什么我们需要一个企业级的接口测试框架? 如果你是一名Java后端开发或者测试工程师,每天的工作里肯定少不了和各种HTTP接口打交道。从早期的Postman手动点点点,到后来写一堆零散的JUnit测试方法,再到尝试…

作者头像 李华
网站建设 2026/6/26 4:52:09

Rust的std--sync--Once:线程安全的一次性初始化

Rust的std::sync::Once:线程安全的一次性初始化 在多线程编程中,初始化共享资源是一个常见但容易出错的场景。如果多个线程同时尝试初始化同一个资源,可能会导致数据竞争或重复初始化的问题。Rust作为一门注重安全性和性能的系统编程语言&am…

作者头像 李华