前言:为什么需要A2A协议?
2026年,我们正处在"智能体爆发年"的浪潮之中。随着大语言模型的快速发展,单个AI Agent已经能够处理相当复杂的任务。但是,现实世界的问题往往更加复杂------一次旅行规划可能同时需要查询天气、预订票务、安排住宿等多个环节。如果让一个Agent包揽所有工作,不仅开发成本高,而且难以维护和扩展。
正是在这样的背景下,Google于2025年4月9日正式发布了Agent2Agent Protocol(简称A2A协议)。这个协议为不同类型的智能体之间搭建了一座高效沟通与协作的桥梁。
本文将带你从零开始,全面掌握A2A协议的核心概念、架构设计和实战应用。
一、A2A协议核心概念解析
1.1 什么是A2A协议?
A2A协议是一个开放标准,它允许不同的AI Agent相互发现、通信和协作。无论是独立Agent与独立Agent、独立Agent与企业Agent,还是企业Agent与企业Agent,都能借助该协议实现通信交互和协作。
核心设计目标:
-
安全协作:确保所有智能体间的通信和数据交换都是安全的
-
任务与状态管理:有效管理任务的整个生命周期及其状态变化
-
用户体验协商:智能体之间协商如何更好地为用户提供服务
-
能力发现:智能体能够自动发现其他智能体的能力
1.2 A2A架构剖析
A2A协议的核心角色包括:

角色说明:
-
User:用户,发起请求的人
-
Client Agent:客户端代理,将用户问题下发给Agent Host
-
Agent Host:代理主机,进行任务规划并决定远程调用哪些Agent
-
Server Agent:服务端代理,提供具体服务的Agent
二、A2A核心组件详解
2.1 AgentSkill:定义Agent的能力单元
AgentSkill是Agent能力的最小描述单元,就像一个人的"技能证书"。
python
from python_a2a import AgentSkill
# 定义一个票务预订技能
ticket_skill = AgentSkill(
name="book_ticket", # 技能名称
description="预订火车票的技能", # 技能描述
examples=["预订从上海到北京的火车票"], # 使用示例
input_modes=["text/plain"], # 支持的输入格式
output_modes=["text/plain"] # 支持的输出格式
)
print(ticket_skill.to_dict())
输出结果:
python
{
"id": "63c15f99-544b-42fe-9d15-937d270f5396",
"name": "book_ticket",
"description": "预订火车票的技能",
"examples": ["预订从上海到北京的火车票"],
"inputModes": ["text/plain"],
"outputModes": ["text/plain"]
}
2.2 AgentCard:Agent的"电子名片"
AgentCard是Server Agent的"名片",描述了Agent的能力、认证机制等信息。
python
from python_a2a import AgentCard, AgentSkill
# 创建技能
ticket_skill = AgentSkill(
name="book_ticket",
description="预订火车票的技能",
examples=["预订从上海到北京的火车票"],
input_modes=["text/plain"],
output_modes=["text/plain"],
)
# 创建Agent名片
agent_card = AgentCard(
name="TicketAgent",
description="一个可以预订票务的代理",
url="http://127.0.0.1:5009",
version="1.0.0",
skills=[ticket_skill],
capabilities={"streaming": True},
)
print(agent_card.to_dict())
2.3 Task:任务的生命周期管理
Task是A2A协议中的核心工作单元,由Client Agent创建,Server Agent维护其状态。
python
from python_a2a import Task, Message, MessageRole, TextContent
# 创建消息
message = Message(
content=TextContent(text="查询天气"),
role=MessageRole.USER
)
# 创建任务
task = Task(message=message.to_dict())
print(f"Task ID: {task.id}")
print(f"Session ID: {task.session_id}")
print(f"Status: {task.status.state}")
2.4 TaskState:任务状态机
TaskState定义了任务可能处于的各种状态:
| 状态名称 | 值 | 描述 |
|---|---|---|
| SUBMITTED | submitted | 任务已提交,等待处理 |
| WAITING | waiting | 任务正在等待外部资源 |
| INPUT_REQUIRED | input-required | 需要用户额外输入 |
| COMPLETED | completed | 任务成功完成 |
| CANCELED | canceled | 任务被取消 |
| FAILED | failed | 任务执行失败 |
python
from python_a2a import TaskState, TaskStatus
# 创建不同状态的任务
status_completed = TaskStatus(
state=TaskState.COMPLETED,
message={"info": "任务成功完成"}
)
status_failed = TaskStatus(
state=TaskState.FAILED,
message={"error": "无法处理请求"}
)
print(status_completed.to_dict())
print(status_failed.to_dict())
2.5 Artifacts:任务的输出产物
Artifacts用于存储任务执行的结果,支持多种内容类型。
python
# 在Server Agent中设置artifacts
task.artifacts = [{
"parts": [
{
"type": "function_response",
"name": "book_ticket",
"response": {"status": "success"}
},
{
"type": "text",
"text": "上海到北京的火车票预订成功!G1001,10车1A"
}
]
}]
三、A2A Server实战:从零构建第一个Agent
3.1 创建基础A2A Server
python
from python_a2a import A2AServer, run_server, AgentCard, AgentSkill, TaskStatus, TaskState
# 1. 定义Agent名片
ticket_card = AgentCard(
name="TicketAgentServer",
description="票务代理",
url="http://127.0.0.1:5009",
skills=[AgentSkill(name="book_ticket", description="预订票务")]
)
# 2. 自定义A2A Server
class TicketServer(A2AServer):
def __init__(self):
super().__init__(agent_card=ticket_card)
def handle_task(self, task):
"""处理任务的核心方法"""
# 获取用户查询
query = (task.message or {}).get("content", {}).get("text", "")
print(f"收到任务: {query}")
# 处理业务逻辑
if "上海" in query and "北京" in query:
result = "上海到北京的火车票预订成功!G1001,10车1A"
else:
result = "请提供明确的出发地和目的地"
# 设置返回结果
task.artifacts = [{"parts": [{"type": "text", "text": result}]}]
task.status = TaskStatus(state=TaskState.COMPLETED)
return task
# 3. 启动服务
if __name__ == "__main__":
server = TicketServer()
run_server(server, host="127.0.0.1", port=5009)
3.2 创建A2A Client
python
from python_a2a import A2AClient, Message, MessageRole, TextContent
# 创建客户端
client = A2AClient(endpoint_url="http://127.0.0.1:5009")
# 发送消息
message = Message(
content=TextContent(text="预订一张从上海到北京的火车票"),
role=MessageRole.USER
)
# 获取响应
response = client.send_message(message)
print(response.to_dict())
四、A2A协作模式
4.1 串行协作:一个接一个执行
python
from python_a2a import AgentNetwork
async def serial_collaboration():
# 1. 创建Agent网络
network = AgentNetwork(name="TravelOrchestrator")
network.add("WeatherAgent", "http://127.0.0.1:5008")
network.add("TicketAgent", "http://127.0.0.1:5009")
# 2. 先查询天气
weather_client = network.get_agent("WeatherAgent")
weather_result = await weather_client.ask("北京的天气怎么样")
# 3. 根据天气结果预订票务
ticket_client = network.get_agent("TicketAgent")
ticket_query = f"预订北京到上海的票,当前天气:{weather_result}"
ticket_result = await ticket_client.ask(ticket_query)
return ticket_result
时序图:
用户 → 主控Agent → WeatherAgent → 返回天气 → TicketAgent → 返回票务 → 用户
4.2 智能路由:LLM驱动的动态调度
python
from python_a2a import AIAgentRouter, AgentNetwork
from langchain_openai import ChatOpenAI
# 1. 创建Agent网络
network = AgentNetwork(name="TravelNetwork")
network.add("WeatherAgent", "http://127.0.0.1:5008")
network.add("TicketAgent", "http://127.0.0.1:5009")
# 2. 创建LLM路由器
llm = ChatOpenAI(model="gpt-4", temperature=0)
router = AIAgentRouter(llm_client=llm, agent_network=network)
# 3. 智能路由
query = "帮我查下北京的天气"
agent_name, confidence = router.route_query(query)
print(f"路由到: {agent_name}, 置信度: {confidence}")
# 4. 调用对应Agent
agent_client = network.get_agent(agent_name)
result = agent_client.ask(query)
4.3 A2A + MCP:让Agent拥有工具能力
MCP(Model Context Protocol)让Agent能够调用外部工具,而A2A让Agent之间能够协作。
python
"""
┌─────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ Client │────▶│ A2A │────▶│ MCP │────▶│ Weather │
│ │ │ Server │ │ Client │ │ API │
└─────────┘ └──────────┘ └──────────┘ └──────────┘
│ │
主控Agent 工具调用
"""
python
# MCP工具Agent (mcp_weather_tool.py)
from python_a2a.mcp import FastMCP
mcp = FastMCP(name="WeatherTool")
@mcp.tool(name="get_weather", description="获取城市天气")
def get_weather(city: str) -> str:
if city == "北京":
return "北京今天阳光明媚,29°C"
return f"找不到{city}的天气"
# A2A主控Agent (a2a_main_agent.py)
class MainAgentServer(A2AServer):
def __init__(self):
super().__init__(agent_card=agent_card)
self.mcp_client = MCPClient("http://127.0.0.1:6005")
def handle_task(self, task):
query = (task.message or {}).get("content", {}).get("text", "")
if "天气" in query:
# 通过MCP调用工具
weather_result = asyncio.run(
self.mcp_client.call_tool("get_weather", city="北京")
)
task.artifacts = [{"parts": [{"type": "text", "text": weather_result}]}]
task.status = TaskStatus(state=TaskState.COMPLETED)
return task
五、高级实战:智能旅行助手系统
下面我们构建一个完整的智能旅行助手,它能够:
-
理解用户的复合意图
-
自动分解为多个子任务
-
智能路由到对应的专家Agent
-
并行执行并整合结果
5.1 系统架构图

5.2 完整代码实现
天气Agent (weather_agent.py):
python
from python_a2a import A2AServer, run_server, AgentCard, AgentSkill, TaskStatus, TaskState
agent_card = AgentCard(
name="WeatherAgentServer",
description="专业的天气预报查询Agent",
url="http://127.0.0.1:5008",
skills=[
AgentSkill(
name="weather_query",
description="查询天气信息",
examples=["帮我查下北京的天气", "北京天气怎么样"]
)
]
)
class WeatherAgentServer(A2AServer):
def __init__(self):
super().__init__(agent_card=agent_card)
def handle_task(self, task):
query = (task.message or {}).get("content", {}).get("text", "")
if "天气" in query:
weather_result = {"温度": 30, "天气": "晴天"}
task.artifacts = [{"parts": [{"type": "text", "text": weather_result}]}]
else:
task.artifacts = [{"parts": [{"type": "text", "text": "无法理解的任务"}]}]
task.status = TaskStatus(state=TaskState.COMPLETED)
return task
if __name__ == "__main__":
server = WeatherAgentServer()
run_server(server, host="127.0.0.1", port=5008)
票务Agent (ticket_agent.py):
python
ticket_card = AgentCard(
name="TicketAgentServer",
description="专业的票务预订Agent",
url="http://127.0.0.1:5009",
skills=[
AgentSkill(
name="book_ticket",
description="预订各种交通票务",
examples=["预订一张从北京到上海的火车票"]
)
]
)
class TicketServer(A2AServer):
def __init__(self):
super().__init__(agent_card=ticket_card)
def handle_task(self, task):
query = (task.message or {}).get("content", {}).get("text", "")
if "上海" in query and "北京" in query:
result = "上海到北京的火车票预订成功!G1001,10车1A"
else:
result = "请提供明确的出发地和目的地"
task.artifacts = [{"parts": [{"type": "text", "text": result}]}]
task.status = TaskStatus(state=TaskState.COMPLETED)
return task
if __name__ == "__main__":
server = TicketServer()
run_server(server, host="127.0.0.1", port=5009)
智能路由器 (router_agent.py):
python
from python_a2a.langchain import to_a2a_server
from langchain_openai import ChatOpenAI
from python_a2a import run_server
llm = ChatOpenAI(
model="gpt-4",
temperature=0.1,
streaming=True
)
# 将LLM转换为A2A服务器
llm_server = to_a2a_server(llm)
if __name__ == '__main__':
run_server(llm_server, port=5555)
主控客户端 (main.py):
python
import asyncio
import json
from python_a2a import AgentNetwork, AIAgentRouter, A2AClient, Task, Message, MessageRole, TextContent
async def main():
# 1. 创建Agent网络
network = AgentNetwork(name="TravelAgentNetwork")
network.add("TicketAgentServer", "http://127.0.0.1:5009")
network.add("WeatherAgentServer", "http://127.0.0.1:5008")
# 2. 创建路由器(使用LLM服务)
router = AIAgentRouter(
llm_client=A2AClient("http://localhost:5555"),
agent_network=network
)
# 3. 处理多个查询
queries = [
"帮我查下北京的天气",
"预订一张从北京到上海的火车票",
"预订一张从北京到上海的火车票,顺便查一下北京天气"
]
for query in queries:
print(f"\n处理查询: {query}")
# 路由决策
agent_name, confidence = router.route_query(query)
print(f"路由到: {agent_name} (置信度: {confidence})")
# 调用Agent
if agent_name:
agent_client = network.get_agent(agent_name)
if agent_client:
message = Message(
content=TextContent(text=query),
role=MessageRole.USER
)
task = Task(message=message.to_dict())
result = await agent_client.send_task_async(task)
# 解析结果
for artifact in result.artifacts:
for part in artifact["parts"]:
if part["type"] == "text":
print(f"结果: {part['text']}")
if __name__ == "__main__":
asyncio.run(main())
5.3 运行效果
python
"""
处理查询: 帮我查下北京的天气
路由到: WeatherAgentServer (置信度: 0.9)
结果: {'温度': 30, '天气': '晴天'}
处理查询: 预订一张从北京到上海的火车票
路由到: TicketAgentServer (置信度: 0.9)
结果: 上海到北京的火车票预订成功!G1001,10车1A
处理查询: 预订一张从北京到上海的火车票,顺便查一下北京天气
路由到: TicketAgentServer (置信度: 0.85)
结果: 上海到北京的火车票预订成功!G1001,10车1A
"""
5.4 主控客户端:真正实现分解+并行
python
import asyncio
import json
import re
import uuid
from python_a2a import (
AgentNetwork,
AIAgentRouter,
A2AClient,
Task,
Message,
MessageRole,
TextContent,
)
from langchain_openai import ChatOpenAI
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import StrOutputParser
from config import Config
conf = Config()
# ============================================================
# 核心1:使用LLM将复合查询分解为多个单一意图的子查询
# ============================================================
decompose_chain = (
PromptTemplate.from_template(
"""
将以下用户查询分解为独立的子查询,每个子查询对应一个单一意图。
返回 JSON 格式的列表:{{"sub_queries": ["子查询1", "子查询2", ...]}}
示例:
查询: "预订火车票,查天气"
输出: {{"sub_queries": ["预订火车票", "查天气"]}}
查询: {query}
"""
)
| ChatOpenAI(
model=conf.model_name,
api_key=conf.api_key,
base_url=conf.base_url,
temperature=0.1,
)
| StrOutputParser()
)
async def handle_complex_query(query, router, network):
"""
处理可能包含多个意图的复杂查询
核心流程:
1. LLM分解复合查询 → 多个子查询
2. 对每个子查询分别路由 → 找到对应的Agent
3. 并行执行所有子任务 → asyncio.gather
4. 整合并输出所有结果
"""
print(f"\n[用户查询] {query}")
print("-" * 50)
# ========== 步骤1:LLM分解复合查询 ==========
try:
decompose_response = decompose_chain.invoke({"query": query})
# 清理LLM返回的markdown格式
decompose_response = re.sub(r"^```json\n|\n```$", "", decompose_response.strip())
decompose_data = json.loads(decompose_response)
sub_queries = decompose_data.get("sub_queries", [query])
except Exception as e:
print(f"[分解失败] {e},使用原始查询")
sub_queries = [query]
print(f"[步骤1-分解] {len(sub_queries)}个子任务: {sub_queries}")
# ========== 步骤2:为每个子查询路由到对应Agent ==========
tasks = [] # 存储异步任务
agents = [] # 存储对应的Agent名称
sub_list = [] # 存储子查询文本
for sub_query in sub_queries:
agent_name, confidence = router.route_query(sub_query)
print(f"[步骤2-路由] '{sub_query}' → {agent_name} (置信度:{confidence})")
if agent_name and confidence >= 0.5:
agent_client = network.get_agent(agent_name)
if agent_client:
# 创建任务
message = Message(
content=TextContent(text=sub_query),
role=MessageRole.USER,
)
task = Task(
id="task-" + str(uuid.uuid4()),
message=message.to_dict(),
)
# 收集异步任务
tasks.append(agent_client.send_task_async(task))
agents.append(agent_name)
sub_list.append(sub_query)
# ========== 步骤3:并行执行所有子任务 ==========
print(f"[步骤3-并行] 同时执行 {len(tasks)} 个子任务...")
if tasks:
# 关键:asyncio.gather 让所有Agent并行工作
results = await asyncio.gather(*tasks, return_exceptions=True)
# ========== 步骤4:整合输出结果 ==========
print(f"\n[步骤4-结果] 并行执行完成:")
for i, result in enumerate(results):
if isinstance(result, Exception):
print(f" ❌ {agents[i]}: 错误 - {result}")
else:
# 从artifacts中提取文本结果
for artifact in getattr(result, "artifacts", []):
for part in artifact.get("parts", []):
if part.get("type") == "text":
print(f" ✅ {agents[i]}: {part.get('text')}")
else:
print("[错误] 未找到合适的Agent")
print("=" * 50)
async def main():
"""主函数:构建网络和路由器,处理多个测试用例"""
# 1. 构建Agent网络(注册所有专家Agent)
network = AgentNetwork(name="TravelAgentNetwork")
network.add("TicketAgentServer", "http://127.0.0.1:5009")
network.add("WeatherAgentServer", "http://127.0.0.1:5008")
# 2. 创建路由器(使用A2A封装的LLM服务)
router = AIAgentRouter(
llm_client=A2AClient("http://localhost:5555"), # router_agent.py
agent_network=network,
)
# 3. 测试用例
test_queries = [
"帮我查下北京的天气", # 单意图
"预订一张从北京到上海的火车票", # 单意图
"预订一张从北京到上海的火车票,查一下北京天气", # 复合意图
]
for query in test_queries:
await handle_complex_query(query, router, network)
if __name__ == "__main__":
print("请确保以下服务已启动:")
print(" - weather_agent.py (端口5008)")
print(" - ticket_agent.py (端口5009)")
print(" - router_agent.py (端口5555)")
print()
asyncio.run(main())
运行结果
python
"""
decompose_chain = (
PromptTemplate.from_template(...) # 步骤1:构造提示词模板
| ChatOpenAI(...) # 步骤2:调用LLM
| StrOutputParser() # 步骤3:解析输出为字符串
)
"""
python
"""
请确保以下服务已启动:
- weather_agent.py (端口5008)
- ticket_agent.py (端口5009)
- router_agent.py (端口5555)
[用户查询] 帮我查下北京的天气
--------------------------------------------------
[步骤1-分解] 1个子任务: ['帮我查下北京的天气']
[步骤2-路由] '帮我查下北京的天气' → WeatherAgentServer (置信度:0.9)
[步骤3-并行] 同时执行 1 个子任务...
[步骤4-结果] 并行执行完成:
✅ WeatherAgentServer: {'天气': '晴天', '温度': 30}
==================================================
[用户查询] 预订一张从北京到上海的火车票
--------------------------------------------------
[步骤1-分解] 1个子任务: ['预订一张从北京到上海的火车票']
[步骤2-路由] '预订一张从北京到上海的火车票' → TicketAgentServer (置信度:0.9)
[步骤3-并行] 同时执行 1 个子任务...
[步骤4-结果] 并行执行完成:
✅ TicketAgentServer: 上海到北京的火车票已经预订成功!G1001,10车1A
==================================================
[用户查询] 预订一张从北京到上海的火车票,查一下北京天气
--------------------------------------------------
[步骤1-分解] 2个子任务: ['预订一张从北京到上海的火车票', '查询一下北京天气']
[步骤2-路由] '预订一张从北京到上海的火车票' → TicketAgentServer (置信度:0.9)
[步骤2-路由] '查询一下北京天气' → WeatherAgentServer (置信度:0.9)
[步骤3-并行] 同时执行 2 个子任务...
[步骤4-结果] 并行执行完成:
✅ TicketAgentServer: 上海到北京的火车票已经预订成功!G1001,10车1A
✅ WeatherAgentServer: {'天气': '晴天', '温度': 30}
==================================================
"""

5.5 核心代码解析
| 步骤 | 关键代码 | 作用 |
|---|---|---|
| 分解 | decompose_chain.invoke() |
LLM将"订票+查天气"拆成2个独立子任务 |
| 路由 | router.route_query(sub_query) |
每个子任务分别找到最合适的Agent |
| 并行 | asyncio.gather(*tasks) |
多个Agent同时工作,互不阻塞 |
| 整合 | 遍历results提取artifacts |
汇总所有Agent的返回结果 |
六、A2A vs MCP:理解两者的关系
在学习过程中,很多同学会混淆A2A和MCP。这里用一个表格帮你理清:
| 维度 | A2A协议 | MCP协议 |
|---|---|---|
| 全称 | Agent-to-Agent | Model Context Protocol |
| 目的 | Agent之间的协作通信 | Agent调用外部工具/API |
| 关系 | 水平协作(对等) | 垂直调用(上下级) |
| 典型场景 | 天气Agent + 票务Agent协作 | Agent调用天气API |
| 通信方向 | 双向、多对多 | 单向调用 |
| 协议特点 | 任务状态管理、能力发现 | 工具注册、标准化调用 |
简单理解:
-
MCP:让Agent拥有"手",能够操作外部工具
-
A2A:让Agent拥有"社交能力",能够与其他Agent协作
两者结合使用,才能构建出真正强大的智能体系统。
七、最佳实践与建议
7.1 设计原则
-
单一职责:每个Agent专注于一个领域
-
明确定义:AgentCard中的技能描述要清晰、具体
-
状态管理:合理使用TaskState,让调用方了解任务进展
-
错误处理:完善的异常捕获和降级机制
7.2 常见问题
Q: 什么时候用串行,什么时候用并行?
-
串行:任务之间有依赖关系(如先查天气再订票)
-
并行:任务相互独立(如同时查天气和查机票)
Q: 置信度阈值应该设多少?
-
0.9以上:高置信度,可直接路由
-
0.7-0.9:中等置信度,可考虑人工确认
-
0.7以下:低置信度,建议使用默认Agent或请求用户澄清
Q: 如何调试A2A系统?
-
开启debug模式:
run_server(server, debug=True) -
查看日志:每个Agent都会打印详细的处理日志
-
使用AgentNetwork列出所有注册的Agent及其能力
八、总结与展望
通过本文的学习,你应该已经掌握了:
-
✅ A2A协议的核心概念(AgentSkill、AgentCard、Task、TaskState、Artifacts)
-
✅ 如何创建A2A Server和Client
-
✅ 串行协作和智能路由两种协作模式
-
✅ A2A与MCP的结合使用
-
✅ 构建完整的智能旅行助手系统
A2A协议的出现,标志着AI应用正在从"单兵作战"迈向"集团军协作"的新阶段。掌握A2A协议,就等于拿到了进入下一代AI应用开发的入场券。
未来,随着A2A生态的成熟,我们将看到:
-
更多标准化的Agent Skill市场
-
企业级Agent协作平台
-
跨组织的Agent联邦网络
现在,就开始动手实践吧!如果你在实践过程中遇到任何问题,欢迎在评论区留言交流。
📚 参考资料:
-
A2A协议官方文档
-
python-a2a库源码
-
MCP协议规范
🔗 相关阅读:
-
《MCP协议详解:让AI Agent拥有"动手能力"》
-
《多智能体系统的设计与实践》
