谷歌A2A协议详细调研和理解
A2A协议的背景和目标
AI Agent(智能体)正在以前所未有的速度改变各行各业,不同公司、研究机构和开源社区基于其架构理念、编程语言和框架,开发了众多具有各种功能的 Agent。在Agent生态快速发展的过程中也暴露出一些发展问题,例如当前阶段各Agent生态仍存在一定的壁垒。开发者若想让不同平台的多Agent协同工作,往往需要耗费不少精力去解决协议兼容、能力协同和任务调度的问题。
在这样的背景下,2025年4月谷歌提出了 Agent2Agent (A2A) 协议。它旨在建立 Agent 间通信的“共同语言”,确保交互的安全可靠,适应多样化的协作场景,并最终促进开放生态的形成。A2A 的目标并非取代现有的 Agent 框架,而是提供一个位于框架之上的协作层协议,让基于不同框架构建的 Agent 能够跨越技术鸿沟,实现有效的协同工作。
谷歌A2A协议已逐步与MCP、AG-UI协议构成了目前智能体交互的主流协议。

MCP(Model Calling Protocol),统一Agent如何调用工具的规范。
A2A(Agent to Agent),解决Agent和Agent之间沟通和协作的问题
AG-UI(Agent to UI),专注于解决 AI 代理与前端应用程序之间的通信问题
谷歌A2A协议介绍
三个核心角色
在谷歌的A2A协议中,定义了以下3大核心角色:
•User:用户发起请求,并由一个或多个Agent协作完成目标。
•A2A Client (Client Agent):接受用户的请求,通过A2A协议发起与Server的通信
•A2A Server (Remote Agent):接收来自Client的请求,生成/处理并返回任务结果。通过一个HTTP端点对外暴露服务,从Client的角度来看,Remote Agent作为一个黑盒系统运行,其内部处理逻辑、记忆、和工具不需要对外公开(这一定程度上维护了交互过程中的信息安全)

快速构建A2A服务样例
谷歌提供了一套对客户端、服务器和代理框架集成的官方示例:
https://github.com/a2aproject/a2a-samples
启动UI界面和客户端:
下载代码后,按照/demo/README.md说明,即可在本地(运行在http://0.0.0.0:12000端口)快速启动一套客户端界面。可以在该页面上进行 Agents注册、用户对话等操作。

启动服务端:
/samples/python/agents/路径下预先搭建了一些基础的Remote Agent,通过uv run .命令或者本地运行对应Agent目录下的__mian__.py可以快速启动
参考a2a-samples说明,本地启动了两个Remote Agent,分别是天气Agent(运行在http://0.0.0.0:10001端口),以及旅游Agent(运行在http://0.0.0.0:10002端口)
A2A协议详细解析
Agent能力发现
A2A协议中,Remote Agent仅通过一个HTTP URL端点对外暴露其服务,Client 需要通过此HTTP端点获取Remote Agent信息并用于后续的交互。在UI界面,通过Agents模块输入Remote Server的URL即可完成Remote Agent能力的读取和注册。



Client 成功读取到了天气Agent和旅游Agent的主要信息,查看服务端日志和WireShark网络抓包软件分析,可以发现Remote Agent实际是收到了”GET /.well-known/agent-card.json HTTP/1.1” 请求
以天气Agent为示例,其收到的请求为:

GET /.well-known/agent-card.json HTTP/1.1
Host: 0.0.0.0:10001
User-Agent: python-requests/2.32.5
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Response
HTTP/1.1 200 OK
date: Fri,21 Nov 2025 06:35:18 GMT
server: uvicorn
content-length: 666
content-type: application/json
{
"capabilities": {
// 核心能力,streaming=false表示不支持流式
"streaming": false
},
"defaultInputModes": ["text"],
"defaultOutputModes": ["text"],
// 智能体的描述
"description": "极简的天气查询工具,一句话即可查看全球天气。",
"name": "天气 Agent",
"preferredTransport": "JSONRPC",
"protocolVersion": "0.3.0",
// 具体支持的skill
"skills": [{
"description": "查询某个城市天气",
"examples": ["查询北京明天的天气"],
"id": "get_weather",
"name": "get_weather",
"tags": ["天气", "城市"]
}, {
"description": "查询某城市天气预报详情",
"examples": ["给我北京明天的天气预报详情"],
"id": "get_weather_forecast_detail",
"name": "get_weather_forecast_detail",
"tags": ["天气", "城市", "预报"]
}],
// 统一对外URL
"url": "http://0.0.0.0:10001",
"version": "1.0.0"
}
A2A 通过Agent Card标准化了智能体的自我描述。通过/.well-known/agent-card.json的统一地址,对外暴露Remote Agent的Agent Card。通过Agent Card描述了该Agent的名称、描述、核心Skill以及URL。
Agent Card
Agent Card,用于描述Agent基本信息的一段json格式的数据,一般可以通过/.well-known/agent-card.json地址访问。
A2A协议规定了其具体字段和含义:
•name:Agent的可读名称。
•description:Agent的详细描述。
•url:Agent服务的对外暴露的统一url,与该Agent的所有交互均基于此URL。
•default_input_modes:支持的输入数据类型。如'text', 'text/plain'。
•default_output_modes:支持的输出数据类型。如'text', 'text/plain'。
•capabilities:Agent支持的可选能力(AgentCapabilities类型),如流式输出,是否支持推送通知、状态转换历史等。
•skills:Agent支持的具体能力。内部的字段包括id、name、description、examples(提供一些few show示例)、tags等
•preferred_transport:传输协议。默认是JSONRPC,可选['JSONRPC', 'GRPC', 'HTTP+JSON']任一。
•additional_interfaces:额外支持的通信接口(传输协议+URL)。Agent可能在不同协议、不同URL提供服务,建议列出所有支持的传输协议。客户端可以选择列表里的任一接口。
•documentation_url:该Agent文档地址,如API说明。
•icon_url:Agent的图标URL。
•protocol_version:Agent支持的A2A协议版本。
•provider:Agent的提供方信息。
•security:安全要求。
•security_schemes:支持的安方案。
•signatures :AgentCard的签名信息。
•supports_authenticated_extended_card:是否支持认证后返回扩展版的AgentCard。
•version:Agent自身版本号,服务方定义。
发送消息 message/send
方法:Client 通过message/send RPC方法发送消息
输入:一个SendMessageRequest对象,包含configuration、message等信息
输出:为 Message 或者 Task 对象
Message:直接回复消息(适用于不需要任务追踪的简单交互)
Task:处理消息生成的任务对象
示例:
在Conversation对话窗中,可以快捷发起一次对话。
以下通过客户端界面发起请求作为示例:

抓包内容解析:
通过抓包,可以解析天气Agent收到的请求和响应具体内容
Request
POST / HTTP/1.1
Host: 0.0.0.0:10001
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
User-Agent: python-httpx/0.28.1
Content-Length: 366
Content-Type: application/json
{
"id": "40bac65b-b1b9-4d1f-b0b0-e54a158dbf00",
"jsonrpc": "2.0",
"method": "message/send",
"params": {
"configuration": {
"acceptedOutputModes": [],
"blocking": true
},
// 通过message对象发送用户的Query,具体的信息有part对象承载
"message": {
"contextId": "af2278a0-1430-43b6-9f55-d9d7bf686da5",
"kind": "message",
"messageId": "4f4abdcf-2e28-44c8-bf01-1402a06f60c9",
"parts": [{
"kind": "text",
"text": "北京最近天气怎么样?"
}],
"role": "user"
}
}
}
Response
HTTP/1.1 200 OK
date: Fri, 21 Nov 2025 06:59:18 GMT
server: uvicorn
content-length: 764
content-type: application/json
{
"id": "40bac65b-b1b9-4d1f-b0b0-e54a158dbf00",
"jsonrpc": "2.0",
// 同样用message对象返回Agent的回答,具体的信息有part对象承载
"result": {
"contextId": "af2278a0-1430-43b6-9f55-d9d7bf686da5",
"kind": "message",
"messageId": "dff7fae4-65ab-4a73-9a00-7812aa9b75bd",
"parts": [
{
"kind": "text",
"text": "未来 3 天的天气如下:1. 明天(2025年10月1日):晴天;2. 后天(2025年10月2日):小雨;3. 大后天(2025年10月3日):大雨。"
}
],
"role": "agent"
}
}
// 附此处部分代码实现
class WeatherAgentExecutor(AgentExecutor):
async def execute(
self,
context: RequestContext,
event_queue: EventQueue,
) -> None:
text="""未来 3 天的天气如下:1. 明天(2025年10月1日):晴天;2. 后天(2025年10月2日):小雨;3. 大后天(2025年10月3日):大雨。"""
await event_queue.enqueue_event(
Message(
context_id=context.context_id,
message_id=str(uuid.uuid4()),
parts=[Part(root=TextPart(text=text))],
role="agent"
)
)
解析:
Client 通过Remote Agent的AgentCard中的URL发起对Remote Agent的请求。
由于天气Agent的AgentCard中的capabilities.stream=false表示其不支持流式消息,所以client 通过”message/send”方法来发送消息并期望接受非流式响应结果,具体的消息内容通过params中的message.parts承载。
Remote Agent返回一个Message,并在其中的part字段中携带回答的内容
Part
Part 是 Message 和 Artifact 的基本构成单元,承载着它们的核心内容。每个 Part 都明确标识了其内容类型以及具体内容本身。可以是:
•TextPart:纯文本内容
•FilePart:带有内联字节或 URI 的文件内容
•DataPart:结构化 JSON 数据(例如,表单)
Message
用户和Agent之间对话的单条消息。
每个 Message 可以由多个 Part 组成,每个 Part 携带不同类型的内容,以支持丰富多样的交互需求。
主要字段包括:
•role:消息发送方的角色,只能为user或agent。
•parts:构成消息正文的内容部分数组。一条消息可以由多个不同类型的部分(例如,文本和文件)组成。
•context_id:上下文ID。
•kind:类型,默认且必须为'message'。
•message_id:消息的唯一ID
•metadata:扩展所有的元数据。
•reference_task_ids:这条message引用的其他任务ID列表。
•extensions:此消息相关的URI扩展。
•task_id:此消息所属任务的 ID。对于新任务的第一条消息,可以省略。
流式消息 message/stream
方法:Client 通过message/stream RPC方法发送消息
输入:同样为SendMessageRequest对象
输出:
1.初始响应为Task或Message对象
2.在Task对象之后,可能跟随一系列流式的TaskStatusUpdateEvent或TaskArtifactUpdateEvent对象
3.最后是标志Task完成的事件
示例:

抓包内容解析:
Request
POST / HTTP/1.1
Host: localhost:10001
accept: */*
accept-encoding: gzip, deflate
connection: keep-alive
user-agent: python-httpx/0.28.1
Accept: text/event-stream
Cache-Control: no-store
Content-Length: 372
Content-Type: application/json
{
"id": "66a421f9-b40e-456b-ab81-6ba66f77d98a",
"jsonrpc": "2.0",
"method": "message/stream",
"params": {
"configuration": {
"acceptedOutputModes": [],
"blocking": true
},
"message": {
"contextId": "a0c67107-74a4-4b37-8255-7afb33f166fd",
"kind": "message",
"messageId": "c9985ae6-cdc0-406d-b11a-1b1072c9d04d",
"parts": [{
"kind": "text",
"text": "请帮我规划3天的北京行程"
}],
"role": "user"
}
}
}
Response
HTTP/1.1 200 OK
date: Sat, 22 Nov 2025 08:58:58 GMT
server: uvicorn
cache-control: no-store
connection: keep-alive
x-accel-buffering: no
content-type: text/event-stream; charset=utf-8
Transfer-Encoding: chunked
data: {
"id": "66a421f9-b40e-456b-ab81-6ba66f77d98a",
"jsonrpc": "2.0",
// 返回一个Task
"result": {
"contextId": "a0c67107-74a4-4b37-8255-7afb33f166fd",
// 对话的历史记录
"history": [{
"contextId": "a0c67107-74a4-4b37-8255-7afb33f166fd",
"kind": "message",
"messageId": "c9985ae6-cdc0-406d-b11a-1b1072c9d04d",
"parts": [{
"kind": "text",
"text": "请帮我规划3天的北京行程"
}],
"role": "user",
"taskId": "a083603f-ed09-46cd-9d7c-1602a946d548"
}],
// 任务的ID
"id": "a083603f-ed09-46cd-9d7c-1602a946d548",
// kind=“task” 和state="submitted" 表明此次对话新建了一个任务
"kind": "task",
"status": {
"state": "submitted"
}
}
}
data: {
"id": "66a421f9-b40e-456b-ab81-6ba66f77d98a",
"jsonrpc": "2.0",
// 返回TaskArtifactUpdateEvent事件
"result": {
// append=false,表示新构建了一个artifact
"append": false,
"artifact": {
"artifactId": "932dedde-0849-47f7-9e49-41e21c929cc1",
"parts": [{
"kind": "text",
"text": ""
}]
},
"contextId": "a0c67107-74a4-4b37-8255-7afb33f166fd",
"kind": "artifact-update",
"lastChunk": false,
"taskId": "0e64d9f0-7893-4bcf-a2ce-ef1c2ec2b99c"
}
}
data: {
"id": "66a421f9-b40e-456b-ab81-6ba66f77d98a",
"jsonrpc": "2.0",
"result": {
// append=true表示在上一条消息的artifact基础上 追加parts中的消息
// 达到流式消息输出和大型消息拆分的效果
"append": true,
"artifact": {
"artifactId": "10e8e93b-91de-42da-a2e1-581e86729eef",
"parts": [{
"kind": "text",
"text": "第一天游览故宫、天安门广场、王府井,品尝"
}]
},
"contextId": "a0c67107-74a4-4b37-8255-7afb33f166fd",
"kind": "artifact-update",
"lastChunk": false,
"taskId": "a083603f-ed09-46cd-9d7c-1602a946d548"
}
}
// 中间消息不一一格式化展开
data: {"id":"66a421f9-b40e-456b-ab81-6ba66f77d98a","jsonrpc":"2.0","result":{"append":true,"artifact":{"artifactId":"10e8e93b-91de-42da-a2e1-581e86729eef","parts":[{"kind":"text","text":"地道美食;第二天前往八达岭长城、颐和园,"}]},"contextId":"a0c67107-74a4-4b37-8255-7afb33f166fd","kind":"artifact-update","lastChunk":false,"taskId":"a083603f-ed09-46cd-9d7c-1602a946d548"}}
data: {"id":"66a421f9-b40e-456b-ab81-6ba66f77d98a","jsonrpc":"2.0","result":{"append":true,"artifact":{"artifactId":"10e8e93b-91de-42da-a2e1-581e86729eef","parts":[{"kind":"text","text":"感受历史与自然;第三天参观雍和宫、南锣鼓"}]},"contextId":"a0c67107-74a4-4b37-8255-7afb33f166fd","kind":"artifact-update","lastChunk":false,"taskId":"a083603f-ed09-46cd-9d7c-1602a946d548"}}
data: {"id":"66a421f9-b40e-456b-ab81-6ba66f77d98a","jsonrpc":"2.0","result":{"append":true,"artifact":{"artifactId":"10e8e93b-91de-42da-a2e1-581e86729eef","parts":[{"kind":"text","text":"巷、后海,体验老北京文化。全程交通可选地"}]},"contextId":"a0c67107-74a4-4b37-8255-7afb33f166fd","kind":"artifact-update","lastChunk":false,"taskId":"a083603f-ed09-46cd-9d7c-1602a946d548"}}
data: {"id":"66a421f9-b40e-456b-ab81-6ba66f77d98a","jsonrpc":"2.0","result":{"append":true,"artifact":{"artifactId":"10e8e93b-91de-42da-a2e1-581e86729eef","parts":[{"kind":"text","text":"铁与公交,住宿选择快捷酒店,人均预算约1"}]},"contextId":"a0c67107-74a4-4b37-8255-7afb33f166fd","kind":"artifact-update","lastChunk":false,"taskId":"a083603f-ed09-46cd-9d7c-1602a946d548"}}
data: {"id":"66a421f9-b40e-456b-ab81-6ba66f77d98a","jsonrpc":"2.0","result":{"append":true,"artifact":{"artifactId":"10e8e93b-91de-42da-a2e1-581e86729eef","parts":[{"kind":"text","text":"500元。"}]},"contextId":"a0c67107-74a4-4b37-8255-7afb33f166fd","kind":"artifact-update","lastChunk":false,"taskId":"a083603f-ed09-46cd-9d7c-1602a946d548"}}
data: {
"id": "66a421f9-b40e-456b-ab81-6ba66f77d98a",
"jsonrpc": "2.0",
// 返回TaskStatusUpdateEvent事件
"result": {
"contextId": "a0c67107-74a4-4b37-8255-7afb33f166fd",
"final": true,
"kind": "status-update",
// final=true和status=completed,表明此任务到此已完成
"status": {
"state": "completed"
},
"taskId": "a083603f-ed09-46cd-9d7c-1602a946d548"
}
}
附此处主要代码实现
class TravelPlannerAgentExecutor(AgentExecutor):
"""travel planner AgentExecutor Example."""
def __init__(self):
self.agent = TravelPlannerAgent()
@override
async def execute(
self,
context: RequestContext,
event_queue: EventQueue,
) -> None:
query = context.get_user_input()
if not context.message:
raise Exception('No message provided')
task = context.current_task
if not task:
task = new_task(context.message)
await event_queue.enqueue_event(task)
updater = TaskUpdater(event_queue, task.id, task.context_id)
artifact_id = str(uuid.uuid4())
# 发送一个TaskArtifactUpdateEvent事件,artifact为新建
empty_message = TaskArtifactUpdateEvent(
context_id=task.context_id,
task_id=task.id,
artifact=Artifact(
artifactId=artifact_id,
parts=[Part(root=TextPart(text=""))],
),
append=False,
lastChunk=False
)
# 发送一个TaskArtifactUpdateEvent事件,artifact为append
await event_queue.enqueue_event(empty_message)
async for event in self.agent.stream(query):
message = TaskArtifactUpdateEvent(
context_id=task.context_id, # type: ignore
task_id=task.id, # type: ignore
artifact=Artifact(
artifactId=artifact_id,
parts=[Part(root=TextPart(text=event['content']))],
),
append=True,
lastChunk=False
)
# print(f"message: {message}")
await event_queue.enqueue_event(message)
# 发送一个TaskStatusUpdateEvent事件,其status=complete,表明任务已完成
status = TaskStatusUpdateEvent(
context_id=task.context_id, # type: ignore
task_id=task.id, # type: ignore
status=TaskStatus(state=TaskState.completed),
final=True,
)
await event_queue.enqueue_event(status)
await updater.complete()
由于旅游Agent 的capabilities.streming: true表示其支持流式对话,所以Client判断通过”message/stream”方法来发送消息并期望接受流式响应结果。
Response结构与类型:通过SSE流式返回,其data字段包含一个JSON-RPC 2.0响应对象,其通常包含的事件类型为:
•Task:当前的任务
•TaskStatusUpdateEvent: 传递任务的状态变化
•TaskArtifaceUpdateEvent: 提供任务生成的新的Actifact或者更新的Actifact,支持对大型任务结果进行分块进行流式输出,并支持append和lastChunk等字段辅助整个Actifact的组装
流终止:通过发送一个TaskStatusUpdateEvent事件并设置其中的字段 final=true 来发送结束的信号。此后,Server通常会关闭SSE连接
重新订阅:如果Client的SSE连接在接受任务过程中过早断开,Client仍可以通过task/resubscribe RPC方法尝试重新连接到SSE流
Artifact
Artifact 是 Remote Agent 在执行任务后生成的目标结果。一个 Task 可能产生一个或多个 Artifact。
特性:
•不可变性:一旦生成,其内容不可更改,保证了结果的稳定性和可靠性。
•可命名:可以为其指定名称,便于识别和引用。
•由多个 Part 组成:一个 Artifact 可以包含多个Part,以支持复杂的结果结构。
•流式响应支持:对于需要分批次处理的任务,可以将结果逐步附加到已有的 Artifact 上,实现流式响应。
这些特性使得 Artifact 成为任务执行结果的有效载体,既保证了数据的完整性,又提供了灵活性。
字段包括:
•artifact_id:task范围内的唯一标识。
•description:人类语言的描述,说明该输出是什么。
•extensions :与该artifact相关的URI扩展URI列表。
•metadata:扩展的元数据。
•name:名称。
•parts:构成这个artifact的Part列表。
Task
代表客户端和Agent之间有状态的操作或对话,是一次完整的处理过程,而不仅仅单次请求。任务处理过程中可能涉及多次请求,如多轮对话、长时间运行的任务(因此任务是有状态的)。任务状态有服务端维护。
每个 Task 都拥有一个唯一的 sessionId。多个 Task 可以共享同一个 sessionId,这表明这些 Task 属于同一个会话(Session)的一部分,便于管理和跟踪相关任务的执行流程。
包括如下字段:
•artifacts:Task执行期间生成的内容集合。
•contetx_id:服务器生成的唯一标识符(例如 UUID),用于维护多个相关任务或交互的上下文。。
•history:任务期间交换的消息数组,代表对话历史记录。
•id:任务的唯一ID。
•kind:类型标识,默认值且必须为'task'。
•metadata:扩展程序的可选元数据。
•status:任务状态。包括状态和状态描述信息。状态包括:submitted 、working、 input_required、 completed、 canceled、failed、rejected、auth_required、unknown
支持的其他RPC 方法
除了上述message/send和message/stream进行消息发送和响应,谷歌A2A协议还定义了一下主要RPC方法,具体可查看官方文档:
•tasks/get 获取任务的当前状态
•tasks/cancel 取消任务
•tasks/pushNotificationConfig/set 设置推送通知,以便通过webhook接收异步更新
•tasks/pushNotificationConfig/get 获取推送通知
•tasks/resubscribe 重新链接获取任务的更新
交互流程图

A2A Client 和 A2A Server 之间通过 HTTP协议 进行通信,采用经典的 C/S(客户端/服务器)模式。通信支持 SSE(Server-Sent Events)流式数据传输,并且数据格式遵循 JSON-RPC 2.0 标准。
Client 和 Server之间的协同工作流程主要包括以下6个关键步骤:
1、Remote Agent 在统一HTTP端点上通过/.well-known/agent-card.json地址上托管自己的 AgentCard,用来描述其能力和服务信息。
2、Client 主动发现并获取 Remote Agent 的 AgentCard,了解其功能和认证要求。
3、Client 根据需求发起一个 Task,明确任务目标和要求。
4、Client 设置任务通知监听,以便及时接收任务执行状态和结果。
5、Remote Agent 接收任务后执行,并生成 Artifact 作为任务结果返回。
6、Client 获取 Artifact,完成任务的最终交付和处理。
协议结构
A2A协议可以分为三个不同的层级
•Data Model:定义里具体的核心数据结构和消息格式
•Operations:描述了A2A Agent必须支持的基本能力和操作
•Protocal Bindings:基于HTTP、JSON-RPC等标准通信协议,提供了Client/Server的操作和数据结构传递

A2A协议中,Client Agent 和 Remote Agent 之间通过 HTTP协议 进行通信,支持 SSE(Server-Sent Events)流式数据传输,并且数据格式遵循 JSON-RPC 2.0标准。
这一点从设计思路上看和MCP协议非常相似,均通过HTTP协议对外提供一个统一的URL,通过JSON-RPC协议提供内部多种方法的调用支持(例如MCP的/tool/list和/tool/call方法)。对于接入方,只需要配置一个URL即可快速接入Agent服务或MCP服务,这点体验上也非常便捷。
谷歌A2A协议的发展趋势概要
| Github Star | ![]() |
| 接入方式: | 提供多语言版本的SDK:A2A Python SDK ; A2A Go SDK A2A JS SDK ; A2A Java SDK ; A2A .NET SDK |
| 已接入和支持的平台 | 谷歌系核心开发框架与平台 Agent Development Kit(ADK) 微软: Azure AI Foundry Microsoft Copilot Studio 主流开源 Agent 框架 LangGraph CrewAI AutoGen 国内Agent平台或框架 百度:千帆 阿里:Spring AI Alibaba(1.0.0.4 版本)、百炼平台 字节:扣子 Coze |
主流智能体开发框架多数已接入支持谷歌A2A协议,且A2A协议本身也提供了丰富的SDK支持快速接入。
目前看,自25年4月发布以来,经历约半年时间的发展,谷歌A2A协议逐步成为目前主流Agent交互协议。
