> Discover all available pages from the documentation index: https://mastra.zisheng.pro/zh-HK/llms.txt # A2A (Agent-to-Agent) Mastra 支援 0.3.0 版的 [Agent-to-Agent (A2A) 協議](https://a2a-protocol.org/latest/),可用於跨平台的多 Agent 系統。你可以使用 A2A 將 Mastra Agent 公開為遠端 Agent、將遠端 A2A Agent 作為 Mastra subagent 使用,或透過 JavaScript 用戶端 SDK 呼叫 A2A 端點。 A2A 是一套開放協議,用於跨越網絡、框架、供應商及程式語言的界限,將工作委派給 Agent。遠端 Agent 會將本身的 Tool、提示、記憶、Workflow 及基礎架構保密,同時公開協議端點,讓其他系統可以探索及呼叫。 ## 何時使用 A2A - 父 Agent 應將工作委派給專門的遠端 Agent。 - 遠端 Agent 由另一項服務、團隊、供應商或執行環境擁有。 - 後端、瀏覽器應用程式或另一個兼容 A2A 的系統需要以程式方式存取 Mastra Agent。 - 長時間執行的遠端工作需要任務 ID、狀態更新、產出物、取消、重新訂閱或推送通知。 ## A2A 的運作方式 A2A 使用 Agent card 進行探索。Agent card 是由 well-known URL 提供的 JSON 文件,當中描述遠端 Agent,並包含接受 A2A JSON-RPC 請求的執行 URL。 使用 Mastra Server 預設的 `apiPrefix`(即 `/api`)時,註冊為 `weather-agent` 的 Agent 會公開: - Agent card:`/api/.well-known/weather-agent/agent-card.json` - 執行端點:`/api/a2a/weather-agent` Agent card 包含 Agent 名稱、描述、端點 URL、Provider、功能、安全性 metadata 及 Skill 等欄位: ```json { "protocolVersion": "0.3.0", "name": "Weather Agent", "description": "Provides weather information.", "url": "https://agent.example.com/api/a2a/weather-agent", "version": "1.0", "provider": { "organization": "Acme", "url": "https://acme.example.com" }, "capabilities": { "streaming": true, "pushNotifications": true, "stateTransitionHistory": false }, "defaultInputModes": ["text/plain"], "defaultOutputModes": ["text/plain"], "skills": [ { "id": "weather", "name": "weather", "description": "Gets weather conditions for a location.", "tags": ["tool"] } ] } ``` A2A 以訊息和任務表示工作。訊息可攜帶文字、檔案或結構化資料部分。 任務是具備 ID 及生命週期狀態的有狀態工作單位。用戶端可以追蹤長時間執行的工作,並傳送後續輪次,也可以取消工作,或在連線中斷後重新訂閱。 ## 協議版本 Mastra 在相同的 Agent card 及執行 URL 上支援 A2A Protocol v0.3 和 v1.0。`A2A-Version` 請求標頭會選擇 wire protocol: - 缺少、留空或設為 `0.3`:使用現有的 v0.3 API。 - `1.0`:使用 v1.0 API。 - 任何其他值:傳回 `VersionNotSupported` 協議錯誤。 現有的 `A2AAgent` 和 `MastraClient.getA2A()` 整合會繼續使用 v0.3。若要傳送 v1.0 請求,請使用 `MastraClient.getA2AV1()`。v1 用戶端會自動傳送 `A2A-Version: 1.0`,並加入 `tasks/list` 操作。 從 `@mastra/core/a2a/v1` 匯入 v1.0 協議類型及 codec。現有的 `@mastra/core/a2a/client` export 仍然使用 v0.3。 ## 開始使用 A2A 在 Mastra 中通常有兩種使用方式: - 使用 `A2AAgent`,將遠端 A2A Agent 作為 Mastra subagent 使用。 - 使用 `MastraClient.getA2A()`,向 Mastra A2A 端點傳送請求。 當另一個 Mastra Agent 應將工作委派給遠端 Agent 時,請使用 `A2AAgent`。當應用程式碼需要直接呼叫已啟用 A2A 的 Mastra 端點時,請使用用戶端 SDK。 ## 將 A2A Agent 作為 subagent 使用 使用 `A2AAgent` 包裝遠端 A2A Agent,然後透過 [supervisor Agent](https://mastra.zisheng.pro/zh-HK/docs/capabilities/subagents) 模式將其加入父 Agent。當遠端伺服器託管多個 Agent 或使用自訂 well-known 路徑時,請明確傳入 Agent card URL。 ```typescript import { Agent } from '@mastra/core/agent' import { A2AAgent } from '@mastra/core/a2a' const remoteWeatherAgent = new A2AAgent({ url: 'https://weather.example.com/api/.well-known/weather-agent/agent-card.json', headers: { Authorization: `Bearer ${process.env.WEATHER_AGENT_TOKEN}`, }, }) export const supportAgent = new Agent({ id: 'support-agent', name: 'Support Agent', instructions: 'Answer user questions and delegate weather questions when needed.', model: 'openai/gpt-5.6-sol', agents: { remoteWeatherAgent, }, }) ``` 如果 `url` 指向網域,`A2AAgent` 會從 `/.well-known/agent-card.json` 擷取 Agent card。對於遵循此探索路徑的單一 Agent 伺服器,請使用網域 URL。對於多 Agent 伺服器,請傳入完整的 Agent card URL,例如 `https://agent.example.com/api/.well-known/weather-agent/agent-card.json`。 執行期間,`A2AAgent` 會: - 擷取並快取遠端 Agent card。 - 從 Agent card 讀取執行 URL 及功能。 - 非串流執行時呼叫 `message/send`,支援串流時則呼叫 `message/stream`。 - 將遠端訊息、任務、產出物及狀態更新轉換為 Mastra subagent 結果。 - 當遠端任務需要後續輸入或重新訂閱時,支援 `resumeGenerate()` 及 `resumeStream()`。 如果遠端 Agent card 未表明支援串流,`A2AAgent.stream()` 會改用非串流 generate 路徑,並傳回已緩衝的串流結果。 ## 使用用戶端 SDK 傳送請求 如要由應用程式碼呼叫已啟用 A2A 的 Mastra Agent,請使用 `MastraClient.getA2A()`。請為伺服器來源設定 `baseUrl`;如果伺服器並非使用預設的 `apiPrefix`(即 `/api`),亦要設定該選項。 ```typescript import { MastraClient } from '@mastra/client-js' const client = new MastraClient({ baseUrl: 'https://agent.example.com', headers: { Authorization: `Bearer ${process.env.AGENT_API_TOKEN}`, }, }) const a2a = client.getA2A('weather-agent') const card = await a2a.getAgentCard() console.log(card.name, card.capabilities) ``` 使用 `sendMessageStream()` 傳送訊息,並透過 Server-Sent Events (SSE) 接收任務狀態及產出物更新: ```typescript const stream = a2a.sendMessageStream({ message: { kind: 'message', role: 'user', messageId: crypto.randomUUID(), parts: [{ kind: 'text', text: "What's the weather in Prague?" }], }, }) for await (const event of stream) { if (event.kind === 'artifact-update') { console.log(event.artifact.parts) } } ``` 如果串流在任務仍然執行期間中斷,請使用 `resubscribeTask()` 接收進行中任務的即時更新: ```typescript const updates = a2a.resubscribeTask({ id: 'task-123', }) for await (const event of updates) { console.log(event) } ``` ### 使用 v1.0 用戶端 使用 `getA2AV1()` 選用 A2A v1.0 wire protocol。協議套件提供 codec,可從 JSON 形狀的輸入建立 v1 請求值: ```typescript import { ListTasksRequest } from '@mastra/core/a2a/v1' import { MastraClient } from '@mastra/client-js' const client = new MastraClient({ baseUrl: 'https://agent.example.com', }) const a2a = client.getA2AV1('weather-agent') const response = await a2a.listTasks( ListTasksRequest.fromJSON({ contextId: 'customer-support', pageSize: 20, }), ) for (const task of response.tasks) { console.log(task.id, task.status) } ``` v1.0 用戶端支援 `getAgentCard()`、`sendMessage()`、`sendMessageStream()`、`getTask()`、`listTasks()`、`cancelTask()` 及 `resubscribeTask()`。 ## 設定 subagent 呼叫 `A2AAgent` 接受請求選項,以配合需要驗證或受限制的環境: ```typescript import { A2AAgent } from '@mastra/core/a2a' const remoteWeatherAgent = new A2AAgent({ url: 'https://weather.example.com/api/.well-known/weather-agent/agent-card.json', headers: { Authorization: `Bearer ${process.env.WEATHER_AGENT_TOKEN}`, }, retries: 2, backoffMs: 250, maxBackoffMs: 1000, timeoutMs: 30_000, }) ``` 當執行環境需要自訂 fetch 行為或取消請求時,你亦可以傳入 `credentials`、`fetch` 及 `abortSignal`。 ## Human-in-the-loop A2A 使用 `input-required` 任務狀態來表示 human-in-the-loop (HITL) 工作。當任務暫停以等待輸入時,用戶端會傳送包含相同 `taskId` 的後續訊息,以提供缺少的輸入,然後伺服器會繼續執行任務。 Mastra 會雙向將其 Agent 暫停模型對應至此狀態: - **作為伺服器**:當公開的 Agent 暫停時,任務會轉為 `input-required`。這包括由 [Tool 批准](https://mastra.zisheng.pro/zh-HK/docs/agents/agent-approval) 或呼叫 `suspend()` 的 Tool 所導致的暫停。任務狀態訊息包含文字提示,以及帶有結構化 `suspendPayload` 和 `resumeSchema` 的資料部分。後續的 `message/send` 或 `message/stream` 請求若包含相同的 `taskId`,便會使用所提供的輸入恢復已暫停的執行。 - **作為用戶端**:當遠端任務進入 `input-required` 或 `auth-required` 時,`A2AAgent` 會傳回帶有 `finishReason: 'suspended'` 及 `suspendPayload` 的暫停結果。呼叫 `resumeGenerate()` 或 `resumeStream()`,會使用原本的 `taskId` 將輸入或憑證傳回遠端任務。 ```typescript import { A2AAgent } from '@mastra/core/a2a' const agent = new A2AAgent({ url: 'https://agent.example.com/api/.well-known/booking-agent/agent-card.json', }) const result = await agent.generate('Book a flight to Paris', { runId: 'run-1' }) if (result.finishReason === 'suspended') { // Inspect result.suspendPayload, collect input from a human, // then resume the remote task. const resumed = await agent.resumeGenerate({ approved: true }, { runId: 'run-1' }) console.log(resumed.text) } ``` `input-required` 任務的後續訊息可以透過結構化資料部分攜帶恢復資料,亦可以透過文字部分中的 JSON 或純文字攜帶。 當恢復後的執行需要額外輸入時,任務會回到 `input-required`,並重複此流程。要恢復已暫停的執行,Mastra 伺服器必須已設定儲存空間,才能在不同請求之間還原已暫停的執行狀態。 > **備註:** A2A 任務記錄存放於記憶體內的儲存區,因此已暫停的任務只能由暫停該任務的同一個伺服器程序恢復。伺服器重新啟動,或水平擴展的部署未有使用粘性路由,都會令任務記錄遺失,而後續訊息會因找不到任務而失敗。 ## 推送通知 Mastra 支援向表明 `capabilities.pushNotifications` 的遠端 Agent 傳送 A2A 推送通知。當用戶端無法維持串流連線,或長時間執行的任務應在原始請求結束後更新回調 URL 時,請使用推送通知。 用戶端取得任務 ID 後,可以為該任務註冊回調 URL: ```typescript await a2a.setTaskPushNotificationConfig({ taskId: 'task-123', pushNotificationConfig: { url: 'https://app.example.com/a2a/tasks', token: process.env.A2A_WEBHOOK_TOKEN, }, }) ``` 當任務進入 `completed`、`failed`、`canceled`、`rejected`、`input-required` 或 `auth-required` 狀態時,Mastra Server 會將目前的任務快照傳送至已註冊的回調。推送通知會盡力傳送,但不保證送達。請保護回調 URL、驗證通知權杖,並避免公開內部網絡目標作為推送通知目的地。 推送通知設定會儲存在記憶體中,伺服器重新啟動後必須再次註冊。 ## 簽署及驗證 Agent card Mastra 支援已簽署的 A2A Agent card,讓用戶端可以驗證探索到的 Agent card 是否來自受信任的發佈者,以及是否在傳輸期間被修改。請在公開遠端 Agent 的 Mastra 伺服器上設定簽署: ```typescript import { Mastra } from '@mastra/core/mastra' export const mastra = new Mastra({ server: { a2a: { agentCardSigning: { privateKey: process.env.A2A_AGENT_CARD_PRIVATE_KEY!, protectedHeader: { alg: 'ES256', kid: 'agent-card-key', }, }, }, }, }) ``` 設定簽署後,Mastra 會在 Agent card 中加入 `signatures` 陣列。用戶端驗證屬於選用功能,而未簽署的 Agent card 仍會原樣傳回。 使用 `MastraClient.getA2A()` 驗證已簽署的 Agent card: ```typescript const card = await a2a.getAgentCard({ verifySignature: { algorithms: ['ES256'], keyProvider: async ({ kid, jku }) => { return fetchTrustedPublicJwk({ kid, jku }) }, }, }) if (!card.signatures?.length) { throw new Error('Expected a signed A2A agent card.') } ``` 當用戶端必須在呼叫遠端 Agent 前強制使用受信任的金鑰,請使用用戶端簽署驗證。 ## 驗證 subagent Agent card 當父 Agent 應在委派工作前驗證遠端 Agent,請使用 `verifyAgentCard`。驗證 hook 會接收已擷取的 Agent card,以及有關擷取位置和時間的 context。 ```typescript import { A2AAgent } from '@mastra/core/a2a' const remoteWeatherAgent = new A2AAgent({ url: 'https://weather.example.com/api/.well-known/weather-agent/agent-card.json', verifyAgentCard: { verify: async (card, context) => { if (card.provider?.organization !== 'Weather Inc') { throw new Error(`Unexpected provider for ${context.cardUrl}`) } }, }, }) ``` 父 Agent 將工作委派給遠端 Agent 前,可使用此 hook 強制執行預期 Provider、預期端點、憑證綁定身分、已簽署 Agent card 或其他信任要求。 ## 相關內容 - [Agent 參考資料](https://mastra.zisheng.pro/zh-HK/reference/agents/agent) - [JavaScript 用戶端 Agent 參考資料](https://mastra.zisheng.pro/zh-HK/reference/client-js/agents) - [A2A 核心概念](https://a2a-protocol.org/latest/topics/key-concepts/) - [A2A 探索指南](https://a2a-protocol.org/latest/topics/agent-discovery/) - 📹 [Agent-to-agent with Mastra 工作坊](https://www.youtube.com/watch?v=LQDzyNGm-aw)