A2A vs. MCP全方位對比(附案例實操詳解)
前陣子有知識星球成員私信,想要我介紹下 Google 發布的 A2A 是啥?
我在具體研究 A2A 之前,刷到過幾個視頻號的博主介紹 A2A時說 A2A 完全是多此一舉,現有的 MCP(大模型上下文協議 )可以直接實現 agent 之間的標準化交互功能。
但初步測試下來發現,A2A并非這么簡單。
這篇試圖說清楚 A2A 的核心定義是啥, 其與 MCP 的主要區別,以及 A2A 官方 Demo 復現講解。
以下,enjoy:
1、A2A 到底是啥
這部分內容主要從公開信息整理而來,但當涉獵即可,看不下去的 feel free 劃到下一章節查看表格形式的與 MCP 核心特性對比。
根據 Google 的官方介紹,A2A (Agent-to-Agent) 是其和超過 50 家技術合作伙伴(如 Langchain, Salesforce, SAP 等)共同推出并支持的開放協議,核心目標是為 AI Agents 提供一個標準的通信方式,使它們能夠:
1.1互相發現和識別
通過“Agent Card”(一種 JSON 格式的文件,包含 Agent 的 ID、名稱、能力、版本、安全需求等信息),一個 Agent 可以找到并了解其他 Agent 的能力。
======= Agent Card ========
{"name":"Parse and Chat","description":"Parses a file and then chats with a user using the parsed content as context.","url":"http://localhost:10010/","version":"1.0.0","capabilities":{"streaming":true,"pushNotifications":true,"stateTransitionHistory":false},"defaultInputModes":["text","text/plain"],"defaultOutputModes":["text","text/plain"],"skills":[{"id":"parse_and_chat","name":"Parse and Chat","description":"Parses a file and then chats with a user using the parsed content as context.","tags":["parse","chat","file","llama_parse"],"examples":["What does this file talk about?"]}]}
========= starting a new task ========
這個被 ======= Agent Card ======== 包裹的 JSON 對象就是官方Demo中LlamaIndex Agent 的 Agent Card示例。里面包含了:
name: "Parse and Chat"
description: Agent 功能描述
url: Agent 的訪問地址
version: 版本號
capabilities: 支持的能力(流式、推送通知等)
defaultInputModes / defaultOutputModes: 支持的默認輸入輸出格式
skills: Agent 擁有的技能列表,每個技能有 ID、名稱、描述、標簽和示例。
1.2安全地交換信息
協議設計考慮了安全性,確保 Agent 之間交互的可靠性。
{
"jsonrpc": "2.0",
"id": 11, // 請求 ID
"method": "tasks/send", // A2A 方法
"params": { // 方法參數
"id": "129", // 任務 ID
"sessionId": "8f01f3d172cd4396a0e535ae8aec6687", // 會話 ID
"acceptedOutputModes": [
"text"
],
"message": { // 用戶消息
"role": "user",
"parts": [ // 消息內容部分
{
"type": "text",
"text": "How much is the exchange rate for 1 USD to INR?"
}
]
}
}
}
Input - 發送給 Agent 服務器的請求示例
// 第一個流式更新 (中間狀態)
data: {"jsonrpc":"2.0","id":12,"result":{"id":"131","status":{"state":"working","message":{"role":"agent","parts":[{"type":"text","text":"Looking up the exchange rates..."}]},"timestamp":"2025-04-02T16:59:34.578939"},"final":false}}
// 第二個流式更新 (中間狀態)
data: {"jsonrpc":"2.0","id":12,"result":{"id":"131","status":{"state":"working","message":{"role":"agent","parts":[{"type":"text","text":"Processing the exchange rates.."}]},"timestamp":"2025-04-02T16:59:34.737052"},"final":false}}
// 第三個流式更新 (推送結果片段)
data: {"jsonrpc":"2.0","id":12,"result":{"id":"131","artifact":{"parts":[{"type":"text","text":"Based on the current exchange rate, 1 USD is equivalent to 0.77252 GBP. Therefore, 100 USD would be approximately 77.252 GBP."}],"index":0,"append":false}}} // 注意這里是 artifact
// 第四個流式更新 (最終狀態)
data: {"jsonrpc":"2.0","id":12,"result":{"id":"131","status":{"state":"completed","timestamp":"2025-04-02T16:59:35.331844"},"final":true}}
流式通知示例
1.3協調行動
跨越不同的工具、服務和企業系統進行協作,完成更復雜的任務。
例如與LangGraph 貨幣兌換 Agent 交互時,這個 Agent 會調用外部的匯率 API 來獲取實時匯率。
2、A2A 與 MCP 的核心區別所在
2.1主要特性對比
下面通過一個表格給各位簡要的梳理下二者間的核心特性差別:
特性 | A2A | MCP |
核心目標 | 標準化 Agent 之間的通信和協作 | 標準化 Agent/應用與外部工具/數據源之間的上下文交互 |
交互層面 | Agent ? Agent (水平集成) | Agent/應用 ? 工具/數據源 (垂直集成) |
解決問題 | 如何讓不同來源、不同框架的 Agent 互相發現、對話、委托任務、協調工作流? | 如何讓一個 Agent/LLM 標準化、安全、高效地調用外部 API、訪問數據庫、獲取實時數據等“工具”? |
通信內容 | 任務指令、狀態更新、協作請求、結果工件、上下文共享、協商 | 傳遞給模型的結構化上下文、工具列表、工具調用請求、工具執行結果 |
設想類比 | Agent 之間的內部消息總線或協作框架 | AI 應用連接外部工具的“USB-C”接口 |
主要發起者 | Anthropic | |
典型場景 | 多 Agent 系統、復雜工作流自動化、跨平臺協作 | 單個 Agent 需要調用多種外部工具、增強 LLM 的上下文理解和執行能力 |
簡單來說:
MCP 關注的是 Agent 如何使用工具 (Agent-to-Tool/Context)。它讓 Agent 更方便地連接和使用各種外部資源(如 API、數據庫)。
A2A 關注的是 Agent 如何互相合作 (Agent-to-Agent)。它讓不同的 Agent 能夠像一個團隊一樣協同工作。
2.2A2A 相對 MCP 是否畫蛇添足
在給出這個問題答案之前,我們先來梳理下網上所謂的 MCP 實現 A2A 核心功能的主要邏輯所在。
MCP 如何實現 A2A 核心功能
封裝 Agent B 為 API/Tool:
將 Agent B 的核心功能(例如,特定的 RAG 檢索能力、數據分析能力、API 調用能力等)封裝在一個或多個 API 端點后面。
例如,創建一個 REST API,其中 /queryKnowledgeBase 端點接收查詢并返回 RAG 結果,/analyzeData 端點接收數據并返回分析報告。
這個 API 就成為了 Agent B 對外提供服務的接口。
為 API/Tool 創建 MCP 描述:
為 Agent B 的 API 創建一個符合 MCP 規范的描述文件(使用 OpenAPI Specification)。這個描述文件需要清晰地說明:
工具的名稱和描述(告訴 Agent A 這是什么工具,能做什么)。
可用的函數/端點(如 /queryKnowledgeBase)。
每個函數所需的輸入參數(名稱、類型、描述、是否必需)。
函數預期的輸出格式(結構化的數據模式)。
可能的認證或安全要求。
Agent A 通過 MCP 調用 Agent B:
Agent A(通常是一個基于 LLM 的 Agent)在其上下文中“看到”了 Agent B 這個工具及其描述。
當 Agent A 的 LLM 判斷需要 Agent B 的能力來完成當前任務時,它會生成一個符合 MCP 規范的“工具調用”(Tool Call)請求。
這個請求包含了要調用的 Agent B 的函數名(如 /queryKnowledgeBase)以及所需的輸入參數(如用戶的查詢)。
Agent A 的執行環境(或 MCP 處理器)接收到這個工具調用請求,實際調用 Agent B 的 API 端點。
Agent B 的 API 執行其內部邏輯(調用自己的 RAG 流程、分析數據等)。
Agent B 將執行結果按照 MCP 描述中定義的輸出格式返回。
Agent A 的執行環境接收到結果,并將其格式化為“工具結果”(Tool Result),反饋給 Agent A 的 LLM。
Agent A 的 LLM 結合這個工具結果,繼續處理任務或生成最終響應。
這種“MCP + Agent as Tool”的方式,實測確實可以實現基本的 Agent 任務委托和信息交換,尤其適用于相對簡單、明確的請求-響應式交互。
注:這部分大家可以參考我之前的文章,使用 Dify 的自定義 Tool 功能模擬 MCP 實現 Agent 協作,這里就不做贅述。
Dify+RAGFLow:基于占位符的圖片問答升級方案(最佳實踐)
However,雖然可以將 Agent 視為 MCP 工具來實現部分 A2A 功能,但這更多是一種“模擬”,實際不能充分發揮多 Agent 系統協作的潛力,也缺乏 A2A 提供的標準化協作框架。
當然,選擇哪種方式取決于各位具體應用場景的復雜度和對 Agent 間交互深度的要求。
3、A2A 官方 Demo 復現與講解
光說不練假把式,我們來使用 A2A 的 Github 官方實例來給大家做一個具體的復現講解。
建議感興趣的一定要實際上手操作下,再結合下方的日志解析應該可以對 A2A 有更加完整的理解。
3.1官方示例的選擇
git clone https://github.com/google/A2A.git
先把 A2A 的官方倉庫下載到本地,我們可以發現官方提供了多個 demo(以 python 為例)供選擇測試,這里先分析下其中主要幾個 demo 的內容和差別。
Google ADK (google_adk)
內容: 模擬一個填寫費用報銷單的 Agent。
主要特性:
使用 Google 的 Agent Development Kit (ADK) 構建。
展示多輪交互:當用戶提供的信息不完整時,Agent 會要求補充。
核心亮點: 演示如何通過 A2A 返回 Web 表單給客戶端(或用戶)填寫,并在客戶端提交表單后繼續處理任務。
LangGraph (langgraph)
內容: 一個可以進行貨幣兌換查詢的 Agent。
主要特性:
使用 LangGraph 框架和 ReAct 模式構建。
展示多輪交互:例如,詢問需要兌換的目標貨幣。
核心亮點: 演示 Agent 如何使用外部工具(調用 Frankfurter API 獲取匯率)以及如何通過 A2A 流式傳輸狀態更新(例如,“正在查詢匯率...”)。
CrewAI (crewai)
內容: 一個可以生成圖像的 Agent。
主要特性:
使用 CrewAI 框架構建。
展示多輪交互。
核心亮點: 演示如何通過 A2A 發送圖像數據作為任務結果。
LlamaIndex File Chat (llama_index_file_chat)
內容: 一個可以接收用戶上傳的文件,解析文件內容,然后根據文件內容與用戶進行問答的 Agent。
主要特性:
使用 LlamaIndex Workflows 構建。
展示多輪交互:在同一會話中基于文件內容進行連續問答。
核心亮點: 演示通過 A2A 處理文件上傳(用戶將文件附加到請求中)、文件解析(使用 LlamaParse),以及流式傳輸狀態更新和帶引用的結果(回答中會標注信息來源是文件的哪部分)。
示例 | 主要功能 | 核心 A2A 特性展示 | 使用框架 | 相對復雜度 |
Google ADK | 費用報銷 (模擬) | Web 表單交互 | Google ADK | 中等 |
LangGraph | 貨幣兌換 | 工具使用 (API 調用), 流式狀態更新 | LangGraph | 較低 |
CrewAI | 圖像生成 | 圖像數據傳輸 | CrewAI | 中等 |
LlamaIndex File Chat | 文件問答 | 文件上傳與解析, 流式更新, 引用 | LlamaIndex Workflows | 較高 |
經過初步測試,建議各位還是從 LangGraph (langgraph) 示例開始實踐,理解了 LangGraph 示例后,可以再嘗試其他示例,例如 ADK 示例來理解 Web 表單交互,或者 LlamaIndex 示例來理解文件處理。
3.2LangGraph 的配置
1. 導航至demo目錄:
```bash
cd samples/python/agents/langgraph
```
2. 創建虛擬環境并配置Google_API_Key:
```bash
echo "GOOGLE_API_KEY=your_api_key_here" > .env
```
3. 運行agent服務器:
```bash
# Basic run on default port 10000
uv run .
# On custom host/port
uv run . --host 0.0.0.0 --port 8080
```
4. 另起一個單獨的終端, 運行A2A客戶端:
```bash
cd samples/python/hosts/cli
uv run .
```
3.3測試目的與示例場景
測試目的
- A2A 協議集成: 確保 Agent 可以正確地通過 A2A 協議接收任務請求 (tasks/send, tasks/sendSubscribe) 并返回符合協議規范的響應。
- 多輪對話能力: 測試 Agent 在信息不充分時,能否主動向用戶請求額外信息(例如,只問了“1 美元換多少?”,Agent 會反問“換成哪種貨幣?”),并能利用后續用戶提供的信息完成任務。
- 流式響應 (Streaming): 測試 Agent 在處理耗時任務時,能否通過 A2A 協議實時發送中間狀態更新(例如,“正在查找匯率...”,“正在處理...”),而不是讓客戶端一直等待最終結果。
- 工具使用 (Tool Usage): 測試基于 ReAct 模式的 LangGraph Agent 能否在需要時正確調用外部工具(這里是 Frankfurter API)來獲取實時匯率數據。
- 會話管理 (Conversational Memory): 測試 Agent 能否在同一會話 (sessionId) 的多次交互中保持上下文記憶。
示例場景
簡單同步請求: 發送一個包含所有必要信息的請求,期望直接得到最終結果。
例子: "1 美元兌換多少印度盧比?" (How much is the exchange rate for 1 USD to INR?)
需要補充信息的多輪請求: 發送一個信息不完整的請求,測試 Agent 是否會要求補充信息,以及在收到補充信息后能否給出結果。
用戶: "1 美元能換多少?" (How much is the exchange rate for 1 USD?)
Agent: "你想換成哪種貨幣?" (Which currency do you want to convert to? )
用戶: "加元" (CAD)
Agent: (返回 1 美元兌換加元的匯率)
流式請求: 發送一個訂閱任務的請求 (tasks/sendSubscribe),測試服務器是否會逐步推送狀態更新和最終結果。
例子: "100 美元兌換多少英鎊?" (How much is 100 USD in GBP?),期望收到類似 "正在查找匯率...", "正在處理...", 然后是最終結果的消息流。
針對一次提問 ("How much is 100 USD in GBP?"),客戶端收到了三個以 stream event => 開頭的獨立消息。這就是流式輸出的核心——服務器不是一次性返回最終結果,而是分多次推送信息。
3.4日志解析
客戶端日志
samples/python/hosts/cli 目錄下的日志,這是最直接展示 A2A 交互的地方。
發起請求: 當在 CLI 中輸入問題(例如 "What is exchange rate between USD and GBP?"),CLI 工具會構建一個符合 A2A tasks/sendSubscribe 或 tasks/send 規范的 JSON RPC 請求,并通過 HTTP POST 發送給 Agent 服務器 (http://localhost:10000)。雖然日志沒有顯示發出的請求原文,但后續的響應證明了請求的發送 ( http://localhost:10000)。雖然日志沒有顯示發出的請求原文,但后續的響應證明了請求的發送 )。
接收響應 (流式事件): 日志中的 stream event => {...} 行就是 Agent 服務器按照 A2A 協議返回給 CLI 客戶端的實時響應。這些 JSON 數據結構完全遵循 A2A 規范:
jsonrpc: "2.0": 表明使用 JSON RPC 協議。
id: 對應請求的 ID。
result.id: A2A 任務的 ID。
result.status.state: 顯示任務狀態,如 working (處理中), input-required (需要輸入), completed (已完成)。這是 A2A 定義的標準狀態。
result.status.message: 當狀態是 working 或 input-required 時,這里包含 Agent 發來的中間消息或提問。
result.artifact: 當任務完成時,這里包含最終的結果。
final: false / true: 表明這個事件是否是該次請求的最終響應。false 代表后面還有更新,true 代表結束。
多輪交互體現: 當問 "How much is the exchange rate for 1 USD?" 時,收到的事件中 result.status.state 變為 input-required,并且 result.status.message 包含了 Agent 的提問 "What currency do you want to convert to?..."。隨后再輸入 "CAD",CLI 再次發送 A2A 請求,Agent 處理后返回最終結果。這清晰地展示了 A2A 對多輪對話的支持。
Agent 服務器日志
samples/python/agents/langgraph 目錄下的日志,這份日志展示了 Agent 服務器內部處理 A2A 請求的過程。
接收請求: INFO: 127.0.0.1:xxxxx - "POST / HTTP/1.1" 200 OK 表明服務器收到了來自 CLI 客戶端的 HTTP POST 請求 (這是承載 A2A 消息的方式)。
任務管理: INFO:common.server.task_manager:Upserting task ... 和 Getting task ... 顯示服務器內部對 A2A 任務狀態的管理。
調用外部工具: INFO:httpx:HTTP Request: GET https://api.frankfurter.app/ ( https://api.frankfurter.app/ )... 顯示 Agent 為了回答問題,調用了外部的匯率 API。這是 Agent 內部邏輯的一部分,由 A2A 請求觸發。
準備響應: 雖然日志沒有直接顯示服務器發送的 JSON 響應,但服務器的處理邏輯(調用 API、生成文本)最終會
構建成您在客戶端日志中看到的 stream event 內容,然后發送回客戶端。
Agent 發現: INFO: 127.0.0.1:xxxxx - "GET /.well-known/agent.json HTTP/1.1" 200 OK 是 CLI 客戶端啟動時,根據 A2A 規范去獲取 Agent 能力描述文件的記錄。
4、MCP 如何與 A2A 協同
注:這部分內容由 LLM 協助編寫
一個復雜的企業 RAG 系統,不僅僅是一個單一的問答機器人,而是一個由多個專業 agents 組成的協作網絡:
MCP 的角色(垂直整合 - Agent 與工具/數據):
核心 RAG Agent: 每個負責特定領域(如 HR、財務、產品技術文檔)的 RAG Agent,內部會使用 MCP 來標準化地調用其核心工具:
連接并查詢**向量數據庫**以檢索相關文檔片段。 訪問**結構化數據庫**(如 SQL 數據庫)以獲取精確數據。 調用**內部 API**(例如,查詢用戶權限、獲取實時庫存狀態)。 MCP 在這里確保了每個 RAG Agent 能夠高效、可靠地利用其所需的底層數據源和功能 API,就像給 Agent 插上了標準化的“眼睛”和“手臂”去感知和操作數據。
**A2A 的角色(水平協作 - Agent 與 Agent):
用戶交互與路由 Agent: 用戶首先接觸的是一個前端交互 Agent。該 Agent 理解用戶意圖后,利用 A2A 協議的發現機制找到最合適的下游專業 Agent。
任務委托與編排: 路由 Agent 通過 A2A 向選定的專業 RAG Agent(如 HR Agent 或 技術文檔 Agent)提交一個標準的 Task。如果任務復雜,需要跨領域知識(例如,“查詢新員工入職的技術設備配置流程和預算標準”),路由 Agent(或一個專門的編排 Agent)可以通過 A2A 協調技術文檔 Agent 和財務 Agent,管理各自子任務的狀態,最終匯總結果。A2A 的任務生命周期管理在此場景下至關重要。
多輪澄清與協作: 如果專業 RAG Agent 在處理任務時發現信息不足,可以通過 A2A 向路由 Agent(進而傳遞給用戶)發送需要輸入 (Needs Input) 的狀態和澄清消息,進行多輪交互,而不是簡單地失敗或返回模糊答案。
主動知識更新與同步: 一個監控 Agent 可以監測外部信息源(如法規更新網站、內部知識庫變更),發現重要更新后,通過 A2A 通知相關的 RAG Agent 進行知識庫更新(如重新索引)或觸發內容摘要任務。
5、寫在最后
總結來說,與側重于標準化 Agent/LLM 與外部工具/數據源交互的 MCP 相比,A2A 并非畫蛇添足。雖然通過將 Agent 封裝為 API 并使用 MCP 的“工具調用”模式,但缺乏 A2A 在任務生命周期管理、豐富消息傳遞、流式狀態更新和標準化協作原語方面的深度和靈活性。
A2A 剛推出不久,在實際生產場景中具體可以發揮多大的作用還有待各位一起探索,我計劃后續分享的項目實操案例中,會適當加入 A2A 的相關方法。Anyway,從實踐中來,到實踐中去。