> Discover all available pages from the documentation index: https://mastra.zisheng.pro/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 子 Agent 使用,或通过 JavaScript 客户端 SDK 调用 A2A 端点。 A2A 是一种开放协议,可跨网络、框架、供应商和编程语言边界将工作委派给 Agent。远程 Agent 会将自己的 Tool、提示词、Memory、Workflow 和基础设施保持为私有内容,同时公开一个可供其他系统发现和调用的协议端点。 ## 何时使用 A2A - 父 Agent 需要将工作委派给专门的远程 Agent。 - 远程 Agent 由其他服务、团队、供应商或运行时负责。 - 后端、浏览器应用或其他兼容 A2A 的系统需要以编程方式访问 Mastra Agent。 - 长时间运行的远程工作需要任务 ID、状态更新、制品、取消、重新订阅或推送通知。 ## A2A 的工作原理 A2A 使用 Agent Card 进行发现。Agent Card 是由约定 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、能力、安全元数据和 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` 请求标头用于选择传输协议: - 缺失、为空或值为 `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 协议类型和编解码器。现有的 `@mastra/core/a2a/client` 导出仍使用 v0.3。 ## 开始使用 在 Mastra 中,A2A 有两种常见使用方式: - 使用 `A2AAgent` 将远程 A2A Agent 作为 Mastra 子 Agent 使用。 - 使用 `MastraClient.getA2A()` 向 Mastra A2A 端点发送请求。 当另一个 Mastra Agent 需要将工作委派给远程 Agent 时,请使用 `A2AAgent`。当应用代码需要直接调用已启用 A2A 的 Mastra 端点时,请使用客户端 SDK。 ## 将 A2A Agent 作为子 Agent 使用 使用 `A2AAgent` 封装远程 A2A Agent,然后按照 [Supervisor Agent](https://mastra.zisheng.pro/docs/capabilities/subagents) 模式将其添加到父 Agent。当远程 Server 托管多个 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 Server,请使用域名 URL。对于多 Agent Server,请传入完整的 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 子 Agent 结果。 - 当远程任务需要后续输入或重新订阅时,支持 `resumeGenerate()` 和 `resumeStream()`。 如果远程 Agent Card 未声明支持流式传输,`A2AAgent.stream()` 会回退到非流式生成路径,并返回经过缓冲的流结果。 ## 使用客户端 SDK 发送请求 当应用代码需要调用已启用 A2A 的 Mastra Agent 时,请使用 `MastraClient.getA2A()`。通过 `baseUrl` 配置 Server 源站;如果 Server 的 `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 传输协议。协议包提供了编解码器,可根据 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()`。 ## 配置子 Agent 调用 `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`。 ## 人工介入 A2A 使用 `input-required` 任务状态对人工介入 (HITL) 工作进行建模。当任务暂停以等待输入时,客户端通过发送带有相同 `taskId` 的后续消息提供缺失的输入,Server 随后继续执行任务。 Mastra 会在两个方向上将自身的 Agent 挂起模型映射到此状态: - **作为 Server**:公开的 Agent 挂起时,任务会转换到 `input-required`。这包括由 [Tool 审批](https://mastra.zisheng.pro/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 Server 配置 Storage,以便跨请求还原挂起的运行状态。 > **备注:** A2A 任务记录存放在内存存储中,因此暂停的任务只能由将其挂起的同一个 Server 进程恢复。如果 Server 重启,或水平扩展部署未使用粘性路由,任务记录将会丢失,后续消息会因找不到任务而失败。 ## 推送通知 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、验证通知令牌,并避免将内部网络目标公开为推送通知目标。 推送通知配置存储在内存中,Server 重启后必须重新注册。 ## 签名并验证 Agent Card Mastra 支持签名的 A2A Agent Card,使客户端能够验证发现的 Agent Card 是否来自可信发布者,以及是否在传输过程中被更改。请在公开远程 Agent 的 Mastra Server 上配置签名: ```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 前强制使用可信密钥时,请使用客户端签名验证。 ## 验证子 Agent 的 Agent Card 当父 Agent 需要在委派工作前验证远程 Agent 时,请使用 `verifyAgentCard`。验证钩子会接收已获取的 Agent Card,以及有关获取位置和时间的上下文。 ```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 前,可使用此钩子强制要求预期的 Provider、端点、证书绑定身份、签名 Agent Card 或其他信任要求。 ## 相关内容 - [Agent Reference](https://mastra.zisheng.pro/reference/agents/agent) - [JavaScript 客户端 Agent Reference](https://mastra.zisheng.pro/reference/client-js/agents) - [A2A 核心概念](https://a2a-protocol.org/latest/topics/key-concepts/) - [A2A 发现指南](https://a2a-protocol.org/latest/topics/agent-discovery/) - 📹 [Mastra Agent-to-Agent Workshop](https://www.youtube.com/watch?v=LQDzyNGm-aw)