Wire Shark分析A2A协议
文章目录
bilibili
A2A 协议介绍
A2A(Agent-to-Agent,智能体间通信协议)是专门用于不同 AI 智能体(Agents)之间进行身份认证、能力协商、任务分发与数据交换的标准网络协议。
如果说 HTTP 是人类与网页通信的桥梁,API 是软件与软件对齐的规则,那么 A2A 就是 AI 与 AI 之间进行复杂协作的“通用语言”。
- 调度 Agent 被称为 A2A Client 或者 Client Agent
- 被调度 Agent 被称为 A2A Server 或者 Remote Agent
特点和使用场景
核心要点与特点
:::color1
- 能力宣告(Discovery & Handshake): 智能体可以向外“自我介绍”,广播自己擅长什么(如“精通机票预订”或“擅长代码分析”)。
- 上下文透传(Context Sharing): 在跨 Agent 协同传递任务时,保持短期记忆和上下文会话不丢失。
- 状态与回调(State Management): 支持长流程任务的异步回调、进度轮询与中断恢复。
- 统一鉴权(Auth & Security): 解决 Agent 代表用户去调用另一个 Agent 时的身份绑定与权限限制问题。
:::
典型使用场景
:::color2
- 多智能体复杂任务协作(Multi-Agent System): 例如用户喊“帮我策划一次东京旅行”,主 Agent 将拆解后的任务分别分发给“机票 Agent”、“酒店 Agent”、“景点规划 Agent”协同完成。
- 跨平台/跨厂商服务调用: 你的个人助理(如苹果 Siri 或 Google Gemini)需要调用第三方企业(如携程、滴滴)的专有 AI Agent 来完成具体交易。
- 自动化企业工作流: 研发 Agent 编写完代码后,自动触发测试 Agent 进行 Code Review,通过后再通知部署 Agent 执行上线。
:::
A2A 协议协作流程
以下以一个“自动化旅游出行规划”场景,展示主智能体通过 A2A 协议与其他专业 Agent 的交互过程:
启动 Agents
启动 A2A Server
- 克隆马克的技术工作坊仓库,并进入
A2A 协议深度解析(1)\weather目录 - 执行
uv run .命令启动 Agent_(每一个 Agent 本质是一个内容符合 A2A 协议的 http 服务器)_



如果发生这种情况,则说明端口被占用 Agent 启动失败。这里的启动端口为 10000,要么更改端口,要么让端口空闲,重新启动 Agent。
启动 Host Agent
-
前往Google AI Studio获取 Google 的 API Key
-
克隆Google的a2a-samples仓库并进入
a2a-samples\demo\ui目录 -
创建
.env文件,并写入刚获取的API Key
-
执行
uv run main.py启动 Agent -
访问http://localhost:12000进入平台。

抓包分析 A2A 协议
抓包注册 A2A Server
- 启动
wireshark进行抓包

- 注册 A2A Server




- 过滤数据包并得到注册流




- 分析注册流
请求包详细分析
GET /.well-known/agent-card.json HTTP/1.1
Host: localhost:10001
User-Agent: python-requests/2.34.2
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
- 目标路径
**/.well-known/agent-card.json**:符合 A2A 协议规范。A2A 规定 Server 应在此 URI 暴露其配置名片,以便外部 Client 或 Registry 进行自动化发现。 - **客户端 **
**User-Agent: python-requests/2.34.2**:表明发起发现请求的是一个基于 Python(如使用了 A2A Python SDK 或自定义脚本)的 Agent 客户端。 - **主机与端口 **
**localhost:10001**:说明目前处于本地开发或微服务容器间网络调测阶段。
响应包与 AgentCard JSON 数据结构解析
HTTP/1.1 200 OK
date: Wed, 22 Jul 2026 06:42:40 GMT
server: uvicorn
content-type: application/json
- **服务器引擎 **
**uvicorn**:说明该 A2A Server 是基于 Python 异步框架(如 FastAPI、Starlette、A2A Python SDK 内置 Web 服务)搭建的。 - 响应负载分析(JSON Payload):
响应体遵循了 A2A Spec v0.3 / v1.0 规范的AgentCard字段定义:
{
"capabilities": { "streaming": false },
"defaultInputModes": ["text"],
"defaultOutputModes": ["text"],
"description": "提供天气相关的查询功能",
"name": "天气 Agent",
"preferredTransport": "JSONRPC",
"protocolVersion": "0.3.0",
"skills": [
{
"description": "给出某地的天气预告",
"examples": ["给我纽约未来 7 天的天气预告"],
"id": "天气预告",
"name": "天气预告",
"tags": ["天气", "预告"]
},
{
"description": "给出某地当前时间的空气质量报告,不做预告",
"examples": ["给我纽约当前的空气质量报告"],
"id": "空气质量报告",
"name": "空气质量报告",
"tags": ["空气", "质量"]
}
],
"url": "http://127.0.0.1:10001",
"version": "1.0.0"
}
| 字段名 | 当前抓包中的值 | 协议语义解释 |
|---|---|---|
protocolVersion |
"0.3.0" |
声明遵循的 A2A 协议版本号为 0.3.0。 |
version |
"1.0.0" |
该 Agent 业务逻辑或服务自身的软件版本号。 |
name |
"...... Agent" (示例脱敏) |
Agent 的可读名称,向人类或调度器展示。 |
description |
"..................." |
Agent 的整体功能简介。 |
url |
"[http://127.0.0.1:10001](http://127.0.0.1:10001)" |
该 Agent 接收实际 Task / Message 请求的基础 Endpoint。 |
preferredTransport |
"JSONRPC" |
告诉 Client 后续的任务调用优先选择 JSON-RPC 2.0 协议进行传输。 |
capabilities |
{"streaming": false} |
声明 Agent 的全局能力。当前 streaming: false 表示不支持流式响应(如 SSE),仅支持同步/异步完整返回。 |
defaultInputModes |
["text"] |
默认支持的输入 MIME 类型/模式(文本输入)。 |
defaultOutputModes |
["text"] |
默认支持的输出 MIME 类型/模式(文本输出)。 |
skills |
[ { "id": "...", "name": "...", "tags": [...], "examples": [...] }, ... ] |
能力/技能列表。列出了该 Agent 暴露的具体子功能(Skill),包括 Prompt 示例 (examples) 和检索标签 (tags),供主控 Agent 判别是否协同。 |
{
"capabilities": { "streaming": false },
"defaultInputModes": ["text"],
"defaultOutputModes": ["text"],
"description": ".................................",
"name": "...... Agent",
"preferredTransport": "JSONRPC",
"protocolVersion": "0.3.0",
"skills": [
{
"description": "...........................",
"examples": [".................. 7 .................."],
"id": "............",
"name": "............",
"tags": ["......", "......"]
},
{
"description": "............................................................",
"examples": ["......................................."],
"id": "..................",
"name": "..................",
"tags": ["......", "......"]
}
],
"url": "http://127.0.0.1:10001",
"version": "1.0.0"
}
如果抓到的响应体是这样子的,说明数据脱敏,访问http://127.0.0.1:10001/.well-known/agent-card.json得到响应体

也可以将显示格式进行转换为 RAW 或者 UTF-8


抓包分析 Host Agent 调度 A2A Server
- 保持 wireshark 开启状态
- 发送天气相关请求

- 过滤数据包并得到调度流


- 分析数据包
请求包解析
POST / HTTP/1.1
Host: 127.0.0.1:10001
Content-Type: application/json
User-Agent: python-httpx/0.28.1
JSON-RPC Payload 核心字段分解:
{
"id": "744647dc-3b51-4e64-b688-6d552ee6ef0e",
"jsonrpc": "2.0",
"method": "message/send",
"params": {
"configuration": { "acceptedOutputModes": [], "blocking": true },
"message": {
"contextId": "0ccdfd0c-7204-42fb-9ec4-fc9beb0b926b",
"kind": "message",
"messageId": "e432ce4c-c641-4502-a009-0681d507788e",
"parts": [
{
"kind": "text",
"text": "纽约明天(请以明天日期)的天气情况如何?"
}
],
"role": "user"
}
}
}
:::color1
**jsonrpc**** & ****id**:标准的 JSON-RPC 2.0 格式(ID 为744647dc-3b51-4e64-b688-6d552ee6ef0e),用于匹配异步或同步的请求与响应。**method**:"message/send":A2A 协议规范中定义的标准 API 方法,用于向 Agent 提交一条用户消息。params.configuration:"blocking": true:客户端显式要求阻塞式等待(同步响应),即 Server 必须等任务完全执行结束后再返回响应,而不是立即返回一个 Pending 状态的 Task。params.message:contextId:0ccdfd0c-7204-42fb-9ec4-fc9beb0b926b(会话/上下文 ID),用于多轮对话的追踪。parts:包含了标准的多模态消息结构(此处为单段文本text: “纽约明天(请以明天日期)的天气情况如何?”)。
:::
响应包解析
HTTP/1.1 200 OK
date: Wed, 22 Jul 2026 07:57:03 GMT
content-type: application/json
JSON-RPC Result 核心字段分解:
{
"id": "744647dc-3b51-4e64-b688-6d552ee6ef0e",
"jsonrpc": "2.0",
"result": {
"artifacts": [
{
"artifactId": "1d3939c1-4c88-420c-a0b7-f61dff19652d",
"name": "天气查询结果",
"parts": [
{
"kind": "text",
"text": "未来 3 天的天气如下:1. 明天(2025年6月1日):晴天;2. 后天(2025年6月2日):小雨;3. 大后天(2025年6月3日):大雨。"
}
]
}
],
"contextId": "0ccdfd0c-7204-42fb-9ec4-fc9beb0b926b",
"history": [
{
"contextId": "0ccdfd0c-7204-42fb-9ec4-fc9beb0b926b",
"kind": "message",
"messageId": "e432ce4c-c641-4502-a009-0681d507788e",
"parts": [
{
"kind": "text",
"text": "纽约明天(请以明天日期)的天气情况如何?"
}
],
"role": "user",
"taskId": "674ed6af-dd27-4c9d-abfa-bdffab019603"
}
],
"id": "674ed6af-dd27-4c9d-abfa-bdffab019603",
"kind": "task",
"status": { "state": "completed" }
}
}
:::color2
status.state:"completed":表明服务端已顺利处理完该任务。id** (TaskId)**:674ed6af-dd27-4c9d-abfa-bdffab019603,服务端为本次生成任务分配的全局唯一标识。artifacts** (产出物)**:
A2A 协议中用于承载 Agent 最终输出结果的核心字段:name:"天气查询结果"parts: 返回了具体的查询文本内容。history:回传并确认了本次触发该 Task 的原始消息上下文。
:::
核心概念
结合前面两个阶段的报文数据,我们可以清晰地还原出 A2A(Agent-to-Agent)协议 的核心领域模型。
在 A2A 协议中,AgentCard、Task、Message、Part、Artifact 构成了 Agent 之间相互发现、协作和交付结果的基础骨架。
| 概念 | 层次/定位 | 相当于经典 HTTP/Web 概念 | 核心职责 |
|---|---|---|---|
| AgentCard | 服务级 (Service Level) | OpenAPI Specs / WSDL |
告诉别人“我是谁、能干啥、怎么调” |
| Task | 实例级 (Instance Level) | 线程/后台 Job (Async Job) |
控制“事情处理得怎么样了(生命周期)” |
| Message | 交互级 (Interaction Level) | 聊天记录 (Chat Item) |
传递“对话与交互指令” |
| Artifact | 成果级 (Output Level) | 导出文件 / 最终 Response Body | 交付“最终干出来的实体成果” |
| Part | 原子级 (Data Level) | MIME Type Body / 多模态 Block | 承载“具体的文本/图片/二进制数据” |
AgentCard(Agent 名片)
📌 定义:AgentCard 是 Agent 向外暴露的静态自描述元数据元组。它放置在符合 RFC 5785 规范的固定路径 /.well-known/agent-card.json 下,类似于 API 界的 OpenAPI/Swagger 文档或微服务中的服务注册信息。
🔍 详解与实战映射
- 核心作用:服务发现与能力协商。客户端在发起任何调用前,必须先拉取
AgentCard,以此决定使用什么协议通信、传入什么格式的数据、调用哪些技能。 - 报文对应:
- 传输与接口协商:
url([http://127.0.0.1:10001](http://127.0.0.1:10001)) +preferredTransport(JSONRPC),告诉客户端后续通过该 URL 发送 JSON-RPC 请求。 - 能力声明:
capabilities.streaming: false说明该 Agent 不支持流式输出,客户端必须使用阻塞/同步方式(blocking: true)获取结果。 - 技能列表:
skills数组,包含了该 Agent 能处理的具体任务(如天气查询),每个 Skill 包含id、description和examples。
Task(任务)
📌 定义:Task 是 A2A 协议中有状态的执行单元与生命周期容器。当客户端通过 message/send` 发起一个需要 Agent 计算或处理的请求时,服务端会为其分配或关联一个 Task。
🔍 详解与实战映射
- 核心作用:追踪一次调用的处理状态、上下文关系及最终产出。
- 报文对应:
- 在阶段二响应的
result根节点中,kind: "task"表明返回的核心对象就是一个 Task。 id(674ed6af-...):Task 的唯一标识,用于异步轮询或后续状态查询。status.state("completed"):表示任务当前的生命周期状态(常见的状态包括:working、completed、failed、input_required等)。contextId(0ccdfd0c-...):将 Task 绑定到某条特定的会话上下文链条上。
Message(消息)
📌 定义:Message` 是客户端与服务端之间、或 Agent 与 Agent 之间的单次对话交互载体。它记录了“谁(role)在什么上下文(contextId)里说了什么(parts)”。
🔍 详解与实战映射
- 核心作用:表达交互意图或提供对话上下文,是触发 Task 状态更新的“输入”。
- 报文对应:
- 请求端:
params.message中包含kind: "message",role: "user",messageId: "e432ce4c-..."。 - 响应端:在
result.history数组中,服务端会将本次接收到的Message原样归档,并补充关联的taskId。
Artifact(产出物 / 构件)
📌 定义:Artifact` 是 Task 执行完成后生成的结构化最终业务成果。它不同于中间的对话过程,代表了可以直接交付给用户或其他 Agent 使用的“确定性产物”(如生成的代码文件、查询到的天气结果、渲染的图表数据等)。
🔍 详解与实战映射
- 核心作用:将 Agent 的“思考/执行过程”与“交付成果”进行解耦,方便上层业务直接提取结果。
- 报文对应:
- 阶段二响应中的
result.artifacts数组:
"artifacts": [{
"artifactId": "1d3939c1-4c88-420c-a0b7-f61dff19652d",
"name": "天气查询结果",
"parts": [...]
}]
- 一个 Task 可以产生 0 个或多个
Artifact。此处成功生成了一个名为“天气查询结果”的构件。
Part(数据分块 / 多模态原子)
📌 定义:Part 是 A2A 协议中承载具体内容的最小数据单元。不管是 Message(输入)还是 Artifact(输出),其具体的内容都是由一个或多个 Part 组成的。
🔍 详解与实战映射
- 核心作用:支持多模态(Multimodal)交互。一个 Message 或 Artifact 可以同时包含
text(文本)、image(图片)、file(文件)等多个Part。 - 报文对应:
- 在 Message 中:
"parts": [{"kind": "text", "text": "纽约明天...的天气情况如何?"}] - 在 Artifact 中:
"parts": [{"kind": "text", "text": "未来 3 天的天气如下:..."}]
运行链路流程图
Agent 注册阶段
用户问答阶段
更多推荐


所有评论(0)