前言
前面学了 MCP,他解决的是 LLM 和物理世界的沟通问题。那么 AI 中 Agent 之间是怎么通讯的?
我们前面在学习 MAS 时了解了 多Agent的通信机制。今天再去了解另一种多 Agent 的通讯协议:A2A。
定义
A2A(Agent to Agent),是一个为 Agent 间通信与协作设计的新一代开放协议标准。
- 核心:定义了一套通用的 “语言”和交互契约,使得不同供应商、不同框架(如LangChain、CrewAI、AutoGPT)构建的智能体能够像人类团队一样直接对话与协作
- 本质:基于成熟的现代Web标准(如HTTP、JSON-RPC、Server-Sent Events)构建
-
同步请求/响应:用于即时查询和指令。
-
流式更新(SSE) :用于任务执行进度的实时反馈。
-
异步通知(Webhook) :用于长周期任务的最终结果回调。
-
和经典范式对比
| 维度 | ACL (如 FIPA-ACL) | CNP (合同网协议) | Blackboard (黑板模型) | A2A (Agent-to-Agent) |
|---|---|---|---|---|
| 核心思想 | 定义智能体间通信的语义语言(说什么,什么意思)。 | 基于招标 - 投标 - 中标的市场机制动态分配任务。 | 通过共享的中央数据空间(黑板)进行异步、间接的协作。 | 定义智能体间通信的开放网络协议(怎么连接,如何交互)。 |
| 交互模式 | 直接、结构化消息传递。 | 集中式拍卖(管理者 - 投标者)。 | 去中心化、通过共享内存读写。 | 对等、多模式(同步 / 异步 / 流式)。 |
| 耦合度 | 语义紧耦合:通信双方必须对消息内容有共同理解。 | 流程紧耦合:必须遵循固定的招标 - 投标流程。 | 数据空间耦合:所有智能体依赖同一黑板。 | 协议松耦合:只依赖标准协议接口,内部实现自由。 |
| 主要问题 | 过于复杂、学术化,难以在实际工程中大规模应用。 | 通信开销大,协商效率低,不适用于需要快速响应的场景。 | 黑板可能成为性能和单点故障瓶颈,状态一致性管理复杂。 | 生态初建:工具链、最佳实践仍在发展中。 |
| A2A 的先进性 | 工程友好:用现代 Web 标准替代复杂的学术语言,大幅降低落地门槛。 | 灵活高效:支持动态、即时的任务委托与结果流式返回,无需完整的拍卖流程,更适合现代 AI 智能体的交互特性。 | 去中心化对等:每个智能体都是独立服务,通过标准协议直接通信,避免了中央黑板带来的瓶颈和单点风险。 | 生态互操作性:核心突破在于打破框架和厂商壁垒,旨在构建开放的智能体互联网。 |
MCP + A2A
通常开发中,A2A 总是与 MCP 协同工作:
- A2A:智能体间水平协作
- MCP:智能体对工具的垂直调用
Coding
项目背景
我们通过一个加减法来简单看下 A2A 的应用。
- 加法:A2A server本地计算
- 减法:借助 MCP 获取
server
使用 FastAPI 构建服务。
app = FastAPI(title=__name__)
Agent Card
Agent Card(智能体卡片) 是 A2A(Agent-to-Agent)协议的核心元数据标准,是JSON 格式的 “数字名片” ,由 A2A 服务端(Server/Agent)发布,用于自描述身份、能力、接入地址、认证方式、支持技能,让 A2A 客户端 / 其他 Agent 自动发现、理解并正确调用该服务,彻底替代 “写死配置“。
- 核心作用:能力发现、自动适配、标准化交互、动态协作
capabilities
"capabilities": {
"streaming": true, // 支持流式响应 "pushNotifications": false, // 不支持推送
"stateTransitionHistory": true,
"supportsMCP": true // 集成MCP外部工具(对应你之前的场景)
}
authentication
"authentication": {
"schemes": ["Bearer"],
"scopes": ["weather:read",
"weather:forecast"]
}
# A2A核心:Agent Card(服务说明书)A2A Server计算实现
AGENT_CARD = {
# 基础身份信息(是谁)
"agent_id": "math_mixed_orchestrator_v1",
"name": "混合运算编排智能体",
"description": "支持本地加法和MCP减法运算",
"endpoint": "http://localhost:8888/a2a",
# 能力支持(能做什么特性)
"capabilities": [
{
"method": "add", # 本地加法方法
"params": ["a", "b"],
"returns": "sum"
},
{
"method": "minus", # MCP减法方法
"params": ["a", "b"],
"returns": "difference"
}
]
}
route
用 FastAPI 为每个 API 设置路由。
@app.get("/agent_card")
async def get_agent_card(request: Request):
return AGENT_CARD
@app.post("/a2a")
async def handle_a2a_request(request: Request):
# 解析A2A标准请求(JSON-RPC简化版)
try:
# ✅ 正确:在异步函数内用 await 调用 request.json()
req_data = await request.json()
except Exception as e:
return JSONResponse(
content={"error": f"解析请求失败: {str(e)}", "id": None},
status_code=400
)
method = req_data.get("method")
params = req_data.get("params", {})
req_id = req_data.get("id")
# A2A 服务端自行计算
if method == "add":
# 本地直接计算加法(无需MCP)
try:
a, b = params["a"], params["b"]
result = a + b
return {
"jsonrpc": "2.0",
"result": {"sum": result},
"id": req_id
}
except KeyError:
return {"error": "Missing 'a' or 'b' parameter", "id": req_id}, 400
client
def call_a2a_agent(agent_card_url, method, params):
"""
按A2A协议调用智能体
"""
# 1. 发现:获取Agent Card(可选,这里假设已知端点)
agent_card = requests.get(agent_card_url).json()
# 2. 构造A2A请求(JSON-RPC格式)
a2a_request = {
"jsonrpc": "2.0",
"method": method,
"params": params,
"id": 1 # 请求ID,用于匹配响应
}
# 3. 发送请求到服务端点
endpoint = agent_card["endpoint"] # 从Agent Card中获取
# endpoint = "http://localhost:8888/a2a"
response = requests.post(endpoint, json=a2a_request)
return response.json()
if __name__ == "__main__":
# 调用加法服务:计算1+2
result = call_a2a_agent(
agent_card_url="http://localhost:8888/agent_card", # Agent Card地址
method="add",
params={"a": 1, "b": 2}
)
print(f"A2A调用结果:{result['result']['sum']}") # 输出:3
A2A + MCP
a2a_server
a2a路由:
elif method == "minus":
# 调用MCP工具(减法计算)
try:
difference = await call_mcp_minus_tool(
tool_name="calculate_minus",
tool_params={"a": params["a"], "b": params["b"]},
mcp_server_cmd=["python", "mcp_minus_server.py"] # 启动MCP服务端
)
return {
"jsonrpc": "2.0",
"result": {"difference": difference},
"id": req_id
}
except Exception as e:
return {"error": f"MCP调用失败: {str(e)}", "id": req_id}, 500
MCP 调用代码:
# MCP客户端封装:调用减法工具(stdio传输)
# ------------------------------
async def call_mcp_minus_tool(tool_name: str, tool_params: dict, mcp_server_cmd: list) -> int:
"""
用MCP客户端连接stdio服务端,调用工具并返回结果
"""
# 1. 启动MCP服务端进程,用stdio_client创建流(连接stdin/stdout)
async with stdio_client(mcp_server_cmd) as (read_stream, write_stream):
# 2. 初始化MCP会话(完成协议握手)
async with ClientSession(read_stream, write_stream) as session:
await session.initialize() # 必须:握手确认
# 3. 调用MCP工具(calculate_minus)
result = await session.call_tool(tool_name, tool_params)
# 4. 提取结果(根据fastmcp返回结构调整,此处假设result.output是工具返回值)
# 若返回结构是{"output": 66},则改为result["output"]
return result.output
mcp_server
和之前学的 MCP 基础是一样的。
# 创建一个MCP服务器
mcp = FastMCP("减法计算工具")
# 使用装饰器定义一个工具(Tool)
@mcp.tool()
# 原有工具:计算BMI
def calculate_minus(a: int, b: int) -> int:
"""
计算两个数的减法
"""
return a - b
if __name__ == "__main__":
# 启动 MCP 服务,使用标准输入输出方式
mcp.run(transport='stdio')
Running
uv run mcp_minus_server.py
uv run a2a_server.py
uv run a2a_client.py