又在重新發明 MCP。
Agent2Agent Protocol(簡稱 A2A)是一種用於獨立 AI agent 應用程式之間通訊的開放協定。它讓一個 agent 能夠探索另一個 agent 的能力、交付工作、持續多輪互動、追蹤長時間執行的工作,並在不知道遠端 agent 如何實作的情況下接收結構化結果。
A2A 由 Google 發起,之後捐贈給 Linux Foundation。它不受框架、模型、語言或供應商限制。使用 Java 建置的 A2A 用戶端,可以與使用不同模型及 agent 框架、以 Python 建置的遠端 agent 協作。
重要的邊界如下:
Agent A 知道 Agent B 提供什麼,以及如何與其通訊。
Agent A 不需要知道 Agent B 的提示、記憶、工具、模型或原始碼。本文說明已發布的 A2A v1.0 資料模型。規格仍在演進,因此正式環境實作應協商並驗證遠端 Agent Card 宣告的協定版本。
A2A 解決的問題 #
假設一般助理必須安排商務旅行。它可能需要與下列 agent 協作:
- 航班 agent;
- 飯店 agent;
- 雇主差旅政策 agent;
- 地面交通 agent;以及
- 費用管理 agent。
沒有共用協定時,每一對系統都需要自訂整合:
協調器 -> 航空公司供應商的私有 API
協調器 -> 飯店供應商的私有 API
協調器 -> 政策 agent 的自訂 WebSocket
協調器 -> 費用 agent 的訊息佇列每個整合都必須自行發明:
- 能力描述;
- 請求與回應結構描述;
- 驗證中繼資料;
- 進度事件;
- 取消行為;
- 檔案處理;
- 對話識別碼;
- 長時間執行工作的模型;以及
- 錯誤表示方式。
隨著獨立開發的 agent 數量增加,這些點對點介面卡的建置與治理成本會變高。
當遠端操作具有決定性且完整指定時,傳統 REST API 可以解決部分問題。但 agent 互動通常不那麼僵化:
用戶端:請依照公司政策安排差旅。
Agent:我需要員工 ID 與偏好的出發時間範圍。
用戶端:員工 E-1042,18:00 之後。
Agent:唯一符合政策的航班會在飯店入住時間之後抵達。可以申請例外嗎?
用戶端:可以;準備例外申請,但不要購買任何東西。工作具有狀態,可能需要釐清或授權,可能持續很長時間,也可能產生多個持續演進的成品。A2A 將這種互動外框標準化,同時將領域推理留給各個 agent。
從整合矩陣到單一協定 #
如果每個 agent 都有專屬介面,連接 \(N\) 個 agent 可能需要接近 \(N \times (N - 1)\) 個有方向的整合。使用 A2A 後,每個實作都以共用協定為目標:
Agent A --\
Agent B ----> A2A 資料模型與操作
Agent C --/這不會消除領域差異。航班預訂技能與安全性檢閱技能仍會接受不同資訊。A2A 標準化的是能力的宣告方式,以及工作、狀態、內容和結果的交換方式。
A2A 不是什麼 #
A2A 是:
- agent 應用程式之間的線路協定與互動模型;
- 適用於跨越程序、框架、團隊和組織邊界的情境;以及
- 為不透明且可能長時間執行的 agent 所設計。
A2A 不是:
- LLM;
- agent 框架;
- 協調演算法;
- 提示格式;
- 工作流程引擎;
- 模型路由系統;
- 身分提供者;
- 註冊表 API 標準;
- 保證已宣告的 agent 值得信任;或
- 定義良好的普通 API 的替代品。
如果遠端能力只是一個 getExchangeRate(from, to),普通 API 或工具協定可能更清楚。當遠端對象是能夠推理、協商、維護工作狀態、要求更多資訊並回傳複雜交付物的自主協作者時,A2A 才具有價值。
A2A 與 MCP #
A2A 與 Model Context Protocol 解決不同問題:
| 協定 | 關係 | 典型遠端能力 |
|---|---|---|
| MCP | agent 到工具或資源 | 查詢資料庫、讀取檔案、呼叫 API |
| A2A | agent 到 agent | 研究、協商、規劃、委派和交付結果 |
一個 agent 可以同時使用兩者:
差旅協調器
|
| A2A:「尋找符合政策的航班選項」
v
航班 Agent
|
| MCP:呼叫庫存與定價工具
v
航空公司系統MCP 向 agent 暴露相對受限的原語。A2A 將獨立 agent 暴露為不透明的協作者。將每個 agent 都包裝成一個大型工具,會隱藏有用的工作生命週期、釐清、成品和非同步行為;將每個簡單工具都視為 agent,則會增加不必要的自主性與複雜性。
三個協定層 #
A2A v1.0 分離三個層次:
- 規範資料模型: Agent Card、Message、Task、Part、Artifact、事件、安全宣告和擴充。
- 抽象操作: 傳送 Message、串流 Message、取得/列出或取消 Task、訂閱 Task 更新、管理推播通知設定,以及取得擴充 Agent Card。
- 繫結: 對應至 JSON-RPC、gRPC、HTTP+JSON 或受治理的自訂繫結。
規範的 Protocol Buffer 定義具有規範效力。繫結會以不同方式序列化相同概念。用戶端應使用持續維護的 SDK,而不應假設某個 JSON-RPC 範例描述所有繫結。
官方專案維護 Python、Go、Java、JavaScript、.NET 和 Rust 的 SDK,另有獨立的範例儲存庫。
參與者 #
一次互動包含三個概念上的參與者:
- 使用者: 其目標促成請求的人類或自動化系統。
- A2A 用戶端: 代表使用者啟動協定操作的應用程式或用戶端 agent。
- A2A 伺服器: 發布 A2A 介面並執行工作的遠端 agent。
同一個應用程式可以同時是伺服器和用戶端。差旅協調器在處理使用者請求的同時,也作為航班和飯店 agent 的用戶端。
使用者
-> A2A 伺服器:差旅協調器
-> A2A 用戶端:航班 Agent
-> A2A 用戶端:飯店 Agent
-> A2A 用戶端:政策 AgentA2A 不標準化協調器的規劃邏輯。它可以使用固定工作流程、規則引擎、LLM 規劃器或人工決策。
Agent 探索 #
A2A 伺服器透過 Agent Card 描述自己。Agent Card 是一份 JSON 文件,包含:
- agent 名稱、描述、提供者和版本;
- 一個或多個支援的介面和 A2A 協定版本;
- 支援的協定繫結;
- 預設輸入與輸出媒體類型;
- 可選的串流、推播通知和擴充卡片能力;
- 安全性配置與需求;
- 技能、描述、標籤、範例和媒體類型;以及
- 可選的簽章和擴充。
簡化的 v1.0 Agent Card 如下:
{
"name": "Corporate Travel Agent",
"description": "Plans policy-compliant business travel",
"version": "3.4.0",
"provider": {
"organization": "Example Travel",
"url": "https://travel.example"
},
"supportedInterfaces": [
{
"url": "https://agents.example/a2a/travel",
"protocolBinding": "HTTP+JSON",
"protocolVersion": "1.0"
}
],
"capabilities": {
"streaming": true,
"pushNotifications": true,
"extendedAgentCard": true
},
"defaultInputModes": [
"text/plain",
"application/json"
],
"defaultOutputModes": [
"text/plain",
"application/json"
],
"skills": [
{
"id": "plan-business-trip",
"name": "Plan a Business Trip",
"description": "Finds policy-compliant flight and hotel options",
"tags": ["travel", "flight", "hotel", "corporate-policy"],
"examples": [
"Plan a trip from Singapore to Helsinki for 12-16 October"
],
"inputModes": ["text/plain", "application/json"],
"outputModes": ["application/json"]
}
]
}確切的 JSON 欄位名稱源自 v1.0 規範模型。應透過 SDK 或產生的結構描述驗證卡片,而不是接受任意 JSON。
探索策略 #
對於以網域為基礎的探索,標準 well-known URL 是:
https://agent.example/.well-known/agent-card.json其他實用方法包括:
- 策展型註冊表: 企業目錄或市集依據技能、提供者、地理位置或信任政策回傳已核准的 Agent Card。
- 直接設定: 部署資訊清單為封閉的一組 agent 提供已知的卡片 URL。
- 已驗證的擴充卡片: 公開卡片宣告基本能力;已驗證的操作會回傳可供該呼叫者使用的敏感技能或介面。
A2A 標準化卡片,而不是集中式註冊表的 API。
應將探索結果視為政策輸入,而不是自動信任。在呼叫 agent 之前,用戶端可能需要檢查:
- 受信任的發行者或註冊表;
- 卡片簽章;
- 允許的網域和 TLS 身分;
- 協定版本;
- 所需的繫結;
- 支援的媒體類型;
- 核准的提供者;
- 資料駐留;
- 安全性配置;
- 合約關係;以及
- 該技能是否已獲得目前使用者授權。
Agent Card 的變更頻率低於 Task,應使用正常的 HTTP 快取,包括 Cache-Control、ETag 和條件式請求。
Agent Card 交換的時機 #
Agent Card 是探索期間使用的控制平面中繼資料,通常在第一次 A2A 操作之前取得:
用戶端 -> 探索或接收 Agent Card
用戶端 -> 驗證信任、版本、繫結、安全性與媒體類型
用戶端 -> 從 supportedInterfaces 選取介面 URL
用戶端 -> 將 A2A 操作傳送至該介面通常不會將卡片附加到每個 Message。用戶端可以快取卡片,並依照正常 HTTP 快取規則或本機政策更新。
A2A 伺服器 必須提供 Agent Card,但 v1.0 允許數種探索機制:標準 well-known URI、註冊表或目錄,以及直接設定的卡片 URL 或卡片內容。因此,/.well-known/agent-card.json 是慣用的可互通位置,但不是交換卡片的唯一合規方式。
如果公開卡片宣告 extendedAgentCard,已授權的用戶端稍後可以呼叫 Get Extended Agent Card。該已驗證卡片可以揭露呼叫者特定的技能或介面,而這些資訊不應在匿名探索時公開。
Message 與 Part #
Message 是一次通訊回合,包含:
- 由呼叫者產生的
messageId; ROLE_USER或ROLE_AGENT角色;- 一個或多個 Part;
- 可選的
contextId和taskId; - 可選的先前 Task 參照;
- 可選的中繼資料;以及
- 宣告的擴充。
Part 恰好包含一種內容表示:
| 內容 | 用途 |
|---|---|
text | 純文字內容 |
data | 結構化 JSON 值 |
url | 外部內容的參照 |
raw | 內嵌位元組,在 JSON 中以 Base64 表示 |
Part 也可以包含 MIME mediaType、檔名和中繼資料:
{
"messageId": "msg-01JZ8P...",
"role": "ROLE_USER",
"parts": [
{
"text": "Review the attached contract for renewal risk.",
"mediaType": "text/plain"
},
{
"url": "https://files.example/contracts/42",
"filename": "contract.pdf",
"mediaType": "application/pdf",
"metadata": {
"sha256": "..."
}
},
{
"data": {
"jurisdiction": "Singapore",
"riskTolerance": "low"
},
"mediaType": "application/json"
}
]
}對於大型檔案,應使用 URL,而不是在每一個協定跳轉中放入 Base64 資料。URL 應為短期有效、限制給預定 agent、經過完整性檢查,並防止混淆代理人存取。
媒體協商很重要。用戶端宣告其接受的輸出媒體類型,Agent Card 描述 agent 支援的媒體類型。當技能提供 application/json 時,機器協調器應要求結構化資料,而不是解析散文。
直接 Message 與具狀態 Task #
Send Message 操作可以回傳:
- 立即且自包含的回應 Message;或
- 用於具狀態或長時間執行工作的 Task。
例如,agent 可以直接回答能力問題:
用戶端:你能檢閱受新加坡法律管轄的合約嗎?
Agent:可以。檢閱一份 300 頁的合約應建立 Task,以便追蹤、中斷、取消,並與輸出 Artifact 建立關聯。
Task 模型 #
Task 包含:
- 伺服器產生的 Task ID;
- 伺服器產生的 context ID;
- 目前狀態和時間戳;
- 可選的狀態 Message;
- Message 歷史;
- 零個或多個 Artifact;以及
- 中繼資料。
生命週期狀態如下:
| 狀態 | 意義 |
|---|---|
TASK_STATE_SUBMITTED | 已接受,但尚未主動處理 |
TASK_STATE_WORKING | 處理中 |
TASK_STATE_INPUT_REQUIRED | 需要更多使用者或用戶端資訊 |
TASK_STATE_AUTH_REQUIRED | 需要額外的頻外驗證 |
TASK_STATE_COMPLETED | 成功的終端結果 |
TASK_STATE_FAILED | 終端處理失敗 |
TASK_STATE_CANCELED | 終端取消 |
TASK_STATE_REJECTED | Agent 拒絕工作 |
INPUT_REQUIRED 和 AUTH_REQUIRED 會中斷處理,但不是終端狀態。用戶端可以傳送與 Task 關聯的另一個 Message 來繼續工作。
終端 Task 是不可變的。修正或細化會在相同 context 中建立新的 Task,並參照先前的 Task:
context C
task T1:產生行程 -> completed -> artifact A1
task T2:更換上午航班 -> completed -> artifact A2
參照 T1這提供可稽核性:每個 Task 都是輸入、狀態和輸出的穩定單位。
Context 與 Task ID #
contextId 將相關的 Task 和 Message 分組。taskId 識別一個工作單位:
context:「規劃赫爾辛基旅行」
task:尋找航班
task:預訂飯店
task:申請政策例外不要將 context ID 與驗證、授權或租戶身分混淆。它是由伺服器指派的不透明關聯控制代碼。伺服器仍必須驗證已驗證的呼叫者是否可以存取每一個被參照的 context、task 和 artifact。
Artifact #
Artifact 是具體的 Task 輸出,而不是對話狀態 Message。範例包括:
- 行程;
- 安全性報告;
- 產生的原始碼;
- PDF 合約分析;
- 圖像;
- 結構化報價清單;或
- 部署資訊清單。
Artifact 具有在其 Task 內唯一的 ID、名稱、描述、Parts、中繼資料和可選的擴充:
{
"artifactId": "offers-v1",
"name": "flight-offers.json",
"description": "Policy-compliant flight options",
"parts": [
{
"mediaType": "application/json",
"data": {
"currency": "SGD",
"offers": [
{
"offerId": "F-812",
"price": 1420.30,
"refundable": true
}
]
}
}
],
"metadata": {
"expiresAt": "2026-07-20T10:15:00Z"
}
}Artifact 不會自動持久化,也不自動值得信任。用戶端必須驗證其結構描述、媒體類型、大小、完整性、來源、到期時間和業務意義。
核心操作 #
與繫結無關的 v1.0 操作包括:
| 操作 | 用途 |
|---|---|
| Send Message | 開始或繼續互動 |
| Send Streaming Message | 開始互動並接收增量事件 |
| Get Task | 取得目前 Task 狀態、歷史和 Artifacts |
| List Tasks | 以篩選器和分頁列出已授權的 Tasks |
| Cancel Task | 要求 agent 取消進行中的工作 |
| Subscribe to Task | 重新連線到作用中 Task 的更新 |
| Manage Task Push Notification Config | 建立、讀取、列出或刪除 webhook 設定 |
| Get Extended Agent Card | 取得呼叫者特定的 Agent Card 詳細資料 |
繫結與端點對應 #
Agent Card 中的介面 URL 和 protocolBinding 決定這些抽象操作如何在線路上呈現。
使用 JSON-RPC 時,宣告的介面 URL 是所有操作共用的一個 HTTP 端點。像 /a2a 這樣的 URL 只是實作選擇;A2A 規格不要求該路徑。用戶端傳送包含 JSON-RPC 本文的普通 HTTP 請求,並由 method 欄位選取 A2A 操作:
POST /a2a HTTP/1.1
Host: agents.example
Content-Type: application/json
{
"jsonrpc": "2.0",
"id": "request-17",
"method": "SendMessage",
"params": {
"message": {
"messageId": "msg-01JZ8P...",
"role": "ROLE_USER",
"parts": [{"text": "Hello"}]
}
}
}JSON-RPC 在此是疊加在 HTTP 上的協定慣例,不是 HTTP 的替代品。HTTP 提供傳輸、標頭、驗證和狀態碼;JSON-RPC 標準化本文欄位 method、params、id、result 和 error,以及請求關聯、通知和協定錯誤語意。其他協定也能在 WebSocket 或標準輸入輸出等傳輸上使用 JSON-RPC,但 A2A 的 JSON-RPC 繫結特別使用 HTTP(S),並以 Server-Sent Events 進行串流。
所有 JSON-RPC A2A 方法都傳送至同一個宣告的 URL:
| A2A 操作 | JSON-RPC 方法 |
|---|---|
| Send Message | SendMessage |
| Send Streaming Message | SendStreamingMessage |
| Get Task | GetTask |
| List Tasks | ListTasks |
| Cancel Task | CancelTask |
| Subscribe to Task | SubscribeToTask |
| 建立推播設定 | CreateTaskPushNotificationConfig |
| 取得推播設定 | GetTaskPushNotificationConfig |
| 列出推播設定 | ListTaskPushNotificationConfigs |
| 刪除推播設定 | DeleteTaskPushNotificationConfig |
| Get Extended Agent Card | GetExtendedAgentCard |
HTTP+JSON 繫結則使用相對於其宣告介面基底 URL 的不同資源導向路徑:
| HTTP 端點 | A2A 操作 |
|---|---|
POST /message:send | Send Message |
POST /message:stream | 使用 SSE 的 Send Streaming Message |
GET /tasks/{id} | Get Task |
GET /tasks | List Tasks |
POST /tasks/{id}:cancel | Cancel Task |
POST /tasks/{id}:subscribe | 使用 SSE 的 Subscribe to Task |
POST /tasks/{id}/pushNotificationConfigs | 建立推播設定 |
GET /tasks/{id}/pushNotificationConfigs/{configId} | 取得推播設定 |
GET /tasks/{id}/pushNotificationConfigs | 列出推播設定 |
DELETE /tasks/{id}/pushNotificationConfigs/{configId} | 刪除推播設定 |
GET /extendedAgentCard | Get Extended Agent Card |
這些路徑屬於 HTTP+JSON 繫結;JSON-RPC 實作不會為每個操作暴露一個 HTTP 路由。gRPC 繫結同樣暴露 RPC 方法,而不是這些 REST 路徑。
阻塞與非阻塞傳送 #
Send Message 設定控制呼叫是否等待:
returnImmediately為 false 或省略時,會等待 Task 到達終端或中斷狀態。returnImmediately為 true 時,會在建立 Task 後回傳;用戶端會輪詢、訂閱或等待推播通知。
簡化的 HTTP+JSON 請求如下:
POST /message:send HTTP/1.1
Host: agents.example
Authorization: Bearer eyJ...
Content-Type: application/json
{
"message": {
"messageId": "msg-01JZ8P...",
"role": "ROLE_USER",
"parts": [
{
"text": "Review repository example/payments for critical vulnerabilities",
"mediaType": "text/plain"
}
]
},
"configuration": {
"acceptedOutputModes": [
"application/json",
"text/markdown"
],
"historyLength": 10,
"returnImmediately": true
}
}立即回應可能包含:
{
"task": {
"id": "task-sec-2048",
"contextId": "ctx-release-91",
"status": {
"state": "TASK_STATE_SUBMITTED",
"timestamp": "2026-07-20T08:30:00Z"
}
}
}此範例針對 v1.0 HTTP+JSON 繫結。請使用 SDK 取得精確的請求與回應包裝格式。
串流與非同步工作 #
Agent 工作通常持續時間超過一般請求逾時。A2A 提供三種更新模式。
輪詢 #
用戶端傳送非阻塞請求,並定期呼叫 Get Task:
Send Message -> Task(submitted)
Get Task -> Task(working)
Get Task -> Task(completed, artifacts=[...])輪詢很簡單,且能夠在程序重新啟動後繼續。應使用指數退避、抖動和伺服器提示,而不是每幾毫秒輪詢一次。
串流 #
如果 Agent Card 宣告支援串流,Send Streaming Message 會回傳串流。依據繫結,HTTP 可以使用 Server-Sent Events,gRPC 可以使用伺服器串流。
Task 生命週期串流從 Task 開始,接著發出:
- 狀態變更或中間狀態 Message 的
TaskStatusUpdateEvent; - 新增或增量更新 Artifact 的
TaskArtifactUpdateEvent。
Task(submitted)
Status(working: "正在掃描相依性")
Artifact(report, append=true, chunk=1)
Status(working: "正在分析可到達的呼叫路徑")
Artifact(report, append=true, chunk=2, lastChunk=true)
Status(completed)Artifact 更新會標示資料是否附加到現有 Artifact,以及最後一個區塊是否已抵達。用戶端應依照 task 和 artifact ID 組合區塊、強制套用大小限制,並在重新連線時避免重複內容。
如果串流在 Task 仍為作用中時中斷,Subscribe to Task 可以恢復接收後續更新。在處理串流資料前持久化 Task ID,使復原仍然可行。
推播通知 #
對於持續數分鐘、數小時或數天的工作,如果 agent 宣告支援推播通知,用戶端可以註冊 HTTPS webhook:
用戶端 -> Agent:啟動 Task 並註冊回呼
用戶端中斷連線
Agent 執行工作
Agent -> 用戶端 webhook:Task 完成
用戶端 -> Agent:Get Task通知會告知用戶端狀態已變更;用戶端通常會在之後擷取具權威性的 Task。
Webhook 支援會引入嚴重風險:
- SSRF: 惡意呼叫者提供內部或雲端中繼資料 URL。
- 冒充: 攻擊者傳送偽造的完成事件。
- 重播: 有效的舊事件再次被處理。
- 放大: 伺服器被誘導向第三方大量傳送請求。
- 重複傳送: 網路重試造成同一事件被傳送多次。
伺服器應允許清單或驗證回呼擁有權,並限制輸出網路。接收端應驗證傳送者,檢查發行者、受眾、到期時間、task ID 和唯一事件 ID,拒絕過期事件,並以冪等方式處理通知。
輸入與驗證中斷 #
長時間執行的工作可能需要另一個使用者決策:
用戶端 -> Agent:「預訂最符合政策的選項」
Agent -> 用戶端:Task(INPUT_REQUIRED)
「兩個選項具有相同的政策評分。要優先較低價格還是可退款票價?」
用戶端 -> Agent:Message(taskId=T1,「優先可退款票價」)
Agent -> 用戶端:Task(WORKING)
Agent -> 用戶端:Task(COMPLETED, artifact=booking)AUTH_REQUIRED 表示工作期間需要額外授權。例如,差旅 agent 可能發現需要使用者授權航空公司帳戶。
用戶端應在頻外執行 OAuth 或同意流程,然後繼續該 Task。不要僅因為 agent 要求驗證,就將密碼、重新整理權杖或可重複使用的祕密作為普通 Message 文字傳送。
詳細範例:企業差旅 #
考慮一個協調由不同系統獨立營運之 agent 的公司助理。
參與者 #
差旅協調器
-> 政策 Agent
-> 航班 Agent
-> 飯店 Agent
-> 費用 Agent每個遠端系統都發布 Agent Card。協調器的核准註冊表包含受信任的卡片,以及各提供者的 OAuth audience。
流程 #
使用者提出請求:
text規劃 10 月 12 日至 16 日從新加坡前往赫爾辛基的差旅。 我需要在星期一 09:00 的會議前抵達。 暫時不要進行購買。協調器將員工等級、成本中心、航線和日期,以結構化 Parts 傳送給政策 Agent。
政策 Agent 回傳含有政策 Artifact 的已完成 Task:
json{ "cabin": "economy", "maxNightlyHotelRate": 240, "currency": "EUR", "approvalRequiredAbove": 1800 }協調器在自己的工作流程中平行啟動航班和飯店 Task。它只傳送每個 agent 所需的政策欄位。
航班 Agent 串流狀態:
textworking: 正在搜尋直飛航線 working: 直飛航線違反抵達限制 working: 正在搜尋一次轉機航線 completed: artifact flight-offers.json飯店 Agent 因為有兩個辦公地點而進入
INPUT_REQUIRED。協調器詢問使用者,並使用選定的辦公地點繼續同一個 Task。協調器合併兩個結構化 Artifact,計算完整的行程選項,並呈現給使用者。
使用者選取一個選項。這會在相同的協調 context 中建立新的預訂 Task,不會變更已完成的搜尋 Task。
由於總額超過政策門檻,費用 Agent 建立核准 Task 並設定推播通知。幾小時後,經理核准。
協調器接收已驗證的通知,取得 Task,確認核准金額和到期時間,然後才繼續預訂 Task。
A2A 的價值 #
航班和飯店提供者保留自己的模型、工具、定價系統和規劃邏輯。協調器看到的是已宣告的技能、Task 狀態、Messages 和 Artifacts。提供者可以替換內部框架,而不必改變協作契約。
A2A 不解決交易原子性。如果航班成功而飯店失敗,協調器仍需要補償邏輯、具有到期時間的預訂,或領域特定的交易工作流程。
詳細範例:軟體交付 #
版本發布協調器協調由不同工程團隊擁有的 agent:
編碼 Agent -> 測試 Agent -> 安全性 Agent -> 部署 Agent流程 #
編碼 Agent 完成 Task
T1並產生:- Git commit 參照;
- patch Artifact;
- change-summary Artifact;以及
- 預期的測試範圍。
協調器分別向測試 Agent 和安全性 Agent 傳送 Message。每個 Message 都參照
T1,但只包含經授權、可用於該儲存庫和操作的短期儲存庫認證資料。測試 Agent 串流:
textTask submitted 正在編譯 payments 模組 正在執行 1,842 個單元測試 正在執行 37 個整合測試 Artifact: junit-results.xml Task completed安全性 Agent 回傳
INPUT_REQUIRED:text此修補程式變更了授權行為。此端點是供服務身分、終端使用者,還是兩者使用?協調器從程式碼擁有者取得答案,並繼續相同的安全性 Task。
安全性 Agent 以結構化發現結果完成:
json{ "decision": "block", "findings": [ { "severity": "high", "file": "AuthorizationService.java", "line": 118, "summary": "Tenant constraint omitted" } ] }協調器不會呼叫部署。它為編碼 Agent 建立 refinement Task
T4,參照T1和安全性 Task,並要求修正。新的修補程式會取得新的測試和檢閱 Task。已完成的 Task 仍是不可變的稽核記錄。
是否允許部署,由決定性的版本發布政策決定,而不是由 LLM 的散文決定。
A2A 的價值 #
每個團隊都可以使用不同的框架建置自己的 agent。結果會是具型別的 Artifact,而不是從聊天內容擷取的文字。串流會為昂貴的測試套件提供進度;中斷的 Task 支援提問,而不必捨棄先前的工作。
協定不會使產生的程式碼變得安全。分支保護、授權、可重現建置、簽章、隔離執行和人工核准仍然是必要的。
詳細範例:保險理賠 #
理賠受理 agent 從行動應用程式接收文字、圖像和文件:
理賠受理 Agent
-> 損害評估 Agent
-> 承保範圍 Agent
-> 詐欺檢閱 Agent
-> 維修網路 Agent多模態交換 #
受理 Message 包含:
- 描述事故的文字;
- 透過受限 URL 參照的圖像 Part;
- PDF 警察報告;
- 結構化車輛和保單資料;以及
- 用於完整性驗證的雜湊。
損害評估 Agent 回傳:
- 人類可讀的摘要;
- 受損元件的結構化清單;
- 加註圖像 Artifact;以及
- 不確定性分數。
承保範圍 Agent 會看到保單條款,但不會看到不必要的事故圖像。詐欺 Agent 會收到符合其職責的遮罩證據。協調器在每次 A2A 呼叫前進行資料最小化。
Human in the Loop #
如果評估信心較低,Task 會進入 INPUT_REQUIRED:
請提供一張與地面高度相同的左後輪照片。行動使用者上傳另一張圖像,受理 agent 繼續相同的 Task。
如果估計損失超過門檻,工作流程會建立個別的人工作業員 Task。A2A 追蹤協作,但具有法律後果的決定仍由決定性的理賠政策和合格的人員作出。
A2A 的價值 #
Parts 支援在一次互動中傳送文字、結構化資料和檔案參照。Task 能夠跨越間歇性的行動網路連線持續存在。Artifacts 表示持久交付物,遠端專業 agent 仍保持不透明。
實作仍必須強制執行同意、保留、區域處理、醫療資料規則,並對每個 Artifact URL 實施嚴格授權。
詳細範例:採購與協商 #
採購 agent 需要從數個供應商 agent 取得 500 台筆記型電腦的報價。這說明 agent 不只是無狀態的價格工具。
流程 #
用戶端將必要規格、交貨地點、服務條款和回應期限傳送給三個核准的供應商 agent。
每個供應商建立一個 Task,並可能提出釐清問題。
供應商回傳包含價格、庫存、保固、到期時間和商業條款的報價 Artifact。
採購 agent 在新的 Task 中要求細化:
text保持相同的硬體和交貨日期。提供三年保固,並報價價格差額。每個細化都參照先前的 Task 和報價 Artifact。
用戶端追蹤報價版本,因為 Artifact 系譜和接受情況是用戶端的責任。
決定性政策引擎比較強制條款。模型可以摘要取捨,但不能免除要求。
人類核准選定的報價。
獨立的購買 Task 使用冪等性金鑰和狹窄授權執行訂單。
A2A 的價值 #
協商是多輪的,而且每個供應商都擁有自己的推理和庫存工具。Task 和 Artifact 提供一致的機制,而不會強迫所有供應商使用一個專有的 agent SDK。
A2A 不標準化報價結構描述。買方和供應商仍需要共用領域結構描述,或為可由機器比較的商業條款使用擴充。
安全性模型 #
A2A 重用標準 Web 安全性,而不是將認證資料放入協定 Message。
Agent Card 宣告支援的安全性配置和需求。用戶端在頻外取得認證資料,然後透過傳輸標頭傳送:
Authorization: Bearer eyJ...正式環境的 A2A 介面應使用 HTTPS 並驗證伺服器身分。跨組織部署通常使用 OAuth 2.0/OIDC、工作負載身分、mTLS 或其組合。
驗證回答呼叫者是誰。每個操作仍需要授權:
- 此呼叫者可以呼叫此技能嗎?
- 它可以存取此 task 和 context 嗎?
- 它可以參照此 artifact 嗎?
- 它可以要求此輸出模態嗎?
- 它可以取消此工作嗎?
- 遠端 agent 可以代表此終端使用者執行底層操作嗎?
不透明執行保護的是實作細節,而不是使用者。惡意或遭入侵的 agent 仍可能回傳有害內容、濫用委派的認證資料,或在工作未成功時宣稱工作成功。
委派 #
當一個 agent 跨越另一個 agent 的邊界代表使用者行動時,應保留:
- 政策要求時的終端使用者身分;
- 呼叫工作負載身分;
- 租戶;
- audience;
- 已授權的 scopes;
- 目的與同意;
- 權杖到期時間;以及
- trace context。
不要僅因為兩個 agent 在技術上都能接受,就轉送範圍寬泛的 bearer token。應將其交換為短期、綁定 audience 且只包含遠端技能所需 scopes 的 token。
不受信任的內容 #
每個 Message、Part、Artifact、Agent Card 和被參照的檔案都是不受信任的輸入。應套用:
- JSON 和媒體類型驗證;
- 位元組數、歷史和巢狀限制;
- 惡意軟體掃描;
- 解壓縮限制;
- URL 配置和目的地限制;
- 對轉譯輸出的內容安全性政策;
- prompt injection 防禦;
- 輸出結構描述驗證;以及
- 獨立於 agent 文字的網域授權。
不要直接在具特權的應用程式來源中轉譯 HTML Artifact。
可靠性與工作流程語意 #
A2A 提供 Task 狀態,但不是分散式交易協調器。用戶端和伺服器仍需要:
- 持久化 Task 儲存;
- 冪等的業務操作;
- 請求去重;
- 帶抖動的有界重試;
- 截止時間和到期時間;
- 取消傳播;
- 部分成功的補償;
- Artifact 完整性和保留;
- 背壓;
- 併發限制;以及
- 程序重新啟動後的復原。
已取消的 Task 不代表外部副作用已被復原。航班可能已經開票,或電子郵件已經寄出。應將取消與業務補償分開建模。
網路失敗會產生歧義:
用戶端傳送「購買」
伺服器執行購買
回應遺失
用戶端不知道購買是否已發生對具有重大後果的操作,使用領域冪等性金鑰和可查詢的業務參照。messageId 識別協定 Message,但除非實作明確定義並持久化該行為,否則不應將其作為唯一的業務保證。
Task 和 Artifact 需要保留政策。除非服務合約明確保證,否則用戶端不能假設可以永遠取得已完成的 Task。
可觀測性 #
在 A2A 呼叫之間傳播 W3C Trace Context 標頭。有用的 span 屬性和日誌包括:
- 遠端 agent 身分和版本;
- 協定和繫結版本;
- 操作;
- Task 和 context ID;
- 技能;
- 狀態轉換;
- 媒體類型;
- Artifact 大小;
- 重試次數;
- 延遲;以及
- 已驗證的用戶端應用程式。
不要將提示文字、文件內容、存取權杖或個人資料放入指標標籤。包含 Message 或 Artifact 的日誌需要遮罩、存取控制和保留限制。
重要指標包括:
- 按操作統計的請求和錯誤率;
- Task 佇列和執行延遲;
- 各狀態的 Task;
- 等待輸入或驗證所花費的時間;
- 串流中斷與重新訂閱率;
- 推播通知傳送失敗;
- 取消延遲;
- Artifact 位元組數;以及
- 下游模型和工具成本。
將具有後果的操作與診斷記錄分開稽核。
擴充 #
擴充可以在不變更核心協定的情況下增加行為或資料。Agent Card 會以穩定 URI、描述、參數及用戶端是否必須理解該擴充來宣告每個擴充。
當必要的擴充不受支援時,用戶端不得呼叫 agent。可選擴充應能正常降級。
當多個獨立實作需要可互通的語意時,才使用擴充,而不是只為了攜帶某個應用程式的私有中繼資料。供應商擴充可能重新造成 A2A 試圖降低的鎖定,因此應盡可能讓核心互動保持可用,並精確記錄相容性。
實作 A2A 伺服器 #
實際的伺服器實作可依下列步驟進行:
- 定義範圍狹窄的技能集合,以及其輸入/輸出媒體類型。
- 發布最小化的公開 Agent Card。
- 先選擇一個官方繫結和 SDK。
- 在 HTTP 或傳輸邊界執行驗證。
- 授權技能、Task、context 和 Artifact。
- 驗證 Message,並安全地解參照檔案。
- 決定何時回傳直接 Message,以及何時建立 Task。
- 在確認非阻塞工作前持久化 Task。
- 發出有效的狀態轉換和不可變的終端狀態。
- 以完整性與保留中繼資料儲存或參照 Artifact。
- 只有在中間更新具有價值時才加入串流。
- 只有在具備 SSRF 防護和已驗證傳遞時才加入推播通知。
- 傳播追蹤資訊並記錄稽核事件。
- 發布相容性與保留保證。
Agent 的內部實作可以使用 LLM、決定性工作流程、人工作業佇列、工具或其他 A2A agent。不要將思維鏈或內部認證資料暴露為狀態 Message。
實作 A2A 用戶端 #
健全的用戶端應:
- 從受信任的來源探索 Agent Card。
- 驗證並快取它。
- 選取雙方支援的協定版本、繫結和媒體類型。
- 強制執行本機信任和資料分享政策。
- 取得綁定 audience 的認證資料。
- 產生並持久化 Message 關聯資料。
- 傳送所需的最小 context。
- 立即持久化回傳的 Task 和 context ID。
- 處理直接 Message 與 Task 回應。
- 處理每一種 Task 狀態,包括拒絕和驗證。
- 以冪等方式重新連線、輪詢或處理推播通知。
- 在使用 Artifact 前驗證它。
- 在執行具有後果的後續操作前套用決定性政策。
- 記錄委派 Task 之間的追蹤和稽核關係。
不要讓 LLM 選擇任意 Agent Card URL,然後立即向它們傳送認證資料或私人資料。探索和呼叫都需要允許清單或信任政策。
何時使用 A2A #
在下列情況使用 A2A:
- 不同擁有者的 agent 必須互通;
- 遠端系統確實是 agent,而不是單一函式;
- 能力探索很有用;
- 互動可能需要釐清或協商;
- 工作是長時間執行或可恢復的;
- 需要豐富或增量式 Artifact;
- 內部 agent 實作必須保持不透明;或
- 多種語言和框架必須共用一份契約。
在下列情況,應優先使用普通 API、事件結構描述、工作流程活動或 MCP 工具:
- 輸入和輸出完全具有決定性;
- 一個短請求總是能完成操作;
- 沒有有意義的對話或 Task 生命週期;
- 雙方屬於一個緊密耦合的應用程式;
- 強靜態領域結構描述比 agent 的彈性更重要;或
- 加入自主行為會帶來風險,卻沒有使用者價值。
常見錯誤 #
- 將探索視為信任。 Agent Card 描述宣告;是否信任由政策決定。
- 將認證資料放進 Message。 使用傳輸層驗證和頻外授權。
- 使用 context ID 作為授權。 它只是個不透明的群組識別碼。
- 將所有使用者 context 傳送給每個 agent。 依委派技能最小化資料。
- 在有結構化輸出時解析散文。 協商適當的媒體類型。
- 重新啟動終端 Task。 在相同 context 中建立新的 Task,並參照先前的 Task。
- 假設取消會復原副作用。 實作領域補償。
- 信任任意推播 URL。 防止 SSRF 並驗證回呼。
- 假設串流具有持久性。 持久化 ID,並支援重新訂閱或輪詢。
- 混淆 A2A 與協調。 用戶端仍負責工作流程和失敗政策。
- 混淆 A2A 與 MCP。 Agent 透過 A2A 協作;Agent 透過 MCP 使用受限工具。
- 讓協調模型擁有最終權限。 決定性程式碼必須強制執行權限、預算和核准規則。
- 忽略協定協商。 Card 可以公開多種繫結和版本。
- 原封不動地使用 1.0 之前的舊範例。 v1.0 規範模型變更了欄位名稱、列舉和繫結結構。
A2A 的價值不在於 agent 可以互相傳送 JSON;普通 HTTP 已經能夠做到這一點。它的價值在於提供共享模型,用於探索不透明的 agent、委派具狀態的工作、協商模態、處理中斷,以及擷取增量或持久化結果。這個共用層讓跨框架協作成為可能,同時將業務結構描述、協調、信任與安全性留給理解這些問題的應用程式。
評論
在 GitHub 上閱讀或評論(發表評論需要登入)