Agent2Agent (A2A) 协议官方规范¶
版本: 0.3.0
有关版本间更改的详细信息,请参见发行说明。
1. 介绍¶
Agent2Agent (A2A) 协议是一个开放标准,旨在促进独立的、可能不透明的 AI 智能体系统之间的通信和互操作性。在智能体可能使用不同框架、语言或由不同供应商构建的生态系统中,A2A 提供了一种通用语言和交互模型。
本文档提供了 A2A 协议的详细技术规范。其主要目标是使智能体能够:
- 发现彼此的能力。
- 协商交互模式(文本、文件、结构化数据)。
- 管理协作任务。
- 安全地交换信息以实现用户目标而无需访问彼此的内部状态、内存或工具。
1.1. A2A 的关键目标¶
- 互操作性: 弥合不同智能体系统之间的通信差距。
- 协作: 使智能体能够委派任务、交换上下文并共同处理复杂的用户请求。
- 发现: 允许智能体动态发现和理解其他智能体的能力。
- 灵活性: 支持各种交互模式,包括同步请求/响应、用于实时更新的流式传输以及用于长时间运行任务的异步推送通知。
- 安全性: 促进适合企业环境的安全通信模式,依赖于标准的 Web 安全实践。
- 异步性: 原生支持长时间运行的任务和可能涉及人工参与的交互。
1.2. 指导原则¶
- 简单: 重用现有的、广为人知的标准(HTTP、JSON-RPC 2.0、服务器发送事件)。
- 企业就绪: 通过与既定的企业实践保持一致来解决身份验证、授权、安全性、隐私性、跟踪和监控问题。
- 异步优先: 为(可能非常)长时间运行的任务和人工参与的交互而设计。
- 模态无关: 支持交换各种内容类型,包括文本、音视频(通过文件引用)、结构化数据/表单,以及可能嵌入的 UI 组件(例如,在部分中引用的 iframe)。
- 不透明执行: 智能体基于声明的能力和交换的信息进行协作,而无需共享其内部想法、计划或工具实现。
有关 A2A 目的和优势的更广泛理解,请参见什么是 A2A?。
2. 核心概念摘要¶
A2A 围绕几个关键概念展开。有关详细解释,请参阅关键概念指南。
- A2A 客户端: 代表用户或其他系统向 A2A 服务器发起请求的应用程序或智能体。
- A2A 服务器(远程智能体): 暴露符合 A2A 标准的 HTTP 端点的智能体或智能体系统,处理任务并提供响应。
- Agent Card: 由 A2A 服务器发布的 JSON 元数据文档,描述其身份、能力、技能、服务端点和身份验证要求。
- 消息: 客户端和远程智能体之间的一次通信,具有
role("user" 或 "agent")并包含一个或多个Parts。 - 任务: 由 A2A 管理的工作的基本单元,由唯一 ID 标识。任务是有状态的,并通过定义的生命周期进行。
- 部分: 消息或工件中的最小内容单元(例如,
TextPart、FilePart、DataPart)。 - 工件: 智能体作为任务结果生成的有形输出(例如,文档、图像、结构化数据),由
Parts组成。 - 流式传输(SSE): 通过服务器发送事件传递的任务实时增量更新(状态更改、工件块)。
- 推送通知: 通过服务器发起的 HTTP POST 请求向客户端提供的 webhook URL 传递的异步任务更新,适用于长时间运行或断开连接的场景。
- 上下文: 可选的、服务器生成的标识符,用于逻辑上分组相关任务。
- 扩展: 智能体提供超出核心 A2A 规范的附加功能或数据的机制。
3. 传输和格式¶
3.1. 传输层要求¶
A2A 支持多种传输协议,所有协议都在 HTTP(S) 上运行。智能体在选择要实现的传输协议时具有灵活性,基于其特定要求和用例:
- A2A 通信 必须 通过 HTTP(S) 进行。
- A2A 服务器在其
AgentCard中定义的一个或多个 URL 上暴露其服务。 - 智能体 必须 至少实现本规范中定义的三种核心传输协议之一。
- 所有支持的传输协议在状态和能力上都被视为相等。
3.2. 支持的传输协议¶
A2A 定义了三种核心传输协议。符合 A2A 标准的智能体应该实现至少一种这些传输协议。它们可以通过实现3.2.4中定义的传输扩展来合规。 所有三种协议在状态上都被视为相等,智能体可以根据其要求选择实现它们的任何组合。
3.2.1. JSON-RPC 2.0 传输¶
智能体 可以 支持 JSON-RPC 2.0 传输。如果实现,它 必须 符合这些要求:
- 主要数据格式是 JSON-RPC 2.0 用于所有请求和响应(不包括 SSE 流包装器)。
- 客户端请求和服务器响应 必须 遵循 JSON-RPC 2.0 规范。
- 包含 JSON-RPC 载荷的 HTTP 请求和响应的
Content-Type头 必须 是application/json。 - 方法名称遵循
{category}/{action}模式(例如,"message/send"、"tasks/get")。
3.2.2. gRPC 传输¶
智能体 可以 支持 gRPC 传输。如果实现,它 必须 符合这些要求:
- 协议定义:必须 使用
specification/grpc/a2a.proto中的规范协议缓冲区定义。 - 消息序列化:必须 使用协议缓冲区版本 3 进行消息序列化。
- 服务定义:必须 实现 proto 文件中定义的
A2AServicegRPC 服务。 - 方法覆盖:必须 提供与其它支持的传输功能等效的所有方法。
- 字段映射:必须 使用
json_name注解以实现 HTTP/JSON 转码兼容性。 - 错误处理:必须 将 A2A 错误代码映射到 proto 注解中定义的适当 gRPC 状态代码。
- 传输安全:必须 支持 TLS 加密(带 TLS 的 HTTP/2 上的 gRPC)。
3.2.3. HTTP+JSON/REST 传输¶
智能体 可以 支持 REST 风格的 HTTP+JSON 传输。如果实现,它 必须 符合这些要求:
- HTTP 方法:必须 使用适当的 HTTP 动词(GET 用于查询,POST 用于操作,PUT 用于更新,DELETE 用于删除)。
- URL 模式:必须 遵循每个方法部分中记录的 URL 模式(例如,
/v1/message:send、/v1/tasks/{id})。 - 内容类型:必须 对请求和响应体使用
application/json。 - HTTP 状态代码:必须 使用适当的 HTTP 状态代码(200、400、401、403、404、500 等),这些代码对应于 A2A 错误类型。
- 请求/响应格式:必须 使用在结构上等效于核心 A2A 数据结构的 JSON 对象。
- 方法覆盖:必须 提供与其它支持的传输功能等效的所有方法。
- 错误格式:必须 以一致的 JSON 格式返回错误响应,该格式映射到 A2A 错误类型。
3.2.4. 传输扩展¶
可以 将附加传输协议定义为核心 A2A 规范的扩展。此类扩展:
- 必须 保持与核心传输的功能等效性
- 必须 使用清晰的命名空间标识符以避免冲突
- 必须 得到清晰的文档和规范
- 应该 提供从核心传输的迁移路径
3.3. 流式传输(服务器发送事件)¶
流式传输能力是 传输特定的:
3.3.1. JSON-RPC 2.0 流式传输¶
当流式传输用于 message/stream 或 tasks/resubscribe 等方法时:
- 服务器响应 HTTP
200 OK状态和Content-Type头为text/event-stream。 - 此 HTTP 响应的正文包含 服务器发送事件 (SSE) 流,如 W3C 所定义。
- 每个 SSE
data字段包含一个完整的 JSON-RPC 2.0 响应对象(具体来说是SendStreamingMessageResponse)。
3.3.2. gRPC 流式传输¶
gRPC 传输使用 服务器流式 RPC 进行流式操作,如协议缓冲区规范中所定义。
3.3.3. HTTP+JSON/REST 流式传输¶
如果支持 REST 传输,它 必须 使用类似于 JSON-RPC 的服务器发送事件实现流式传输。
3.4. 传输合规性和互操作性¶
3.4.1. 功能等效性要求¶
当智能体支持多种传输时,所有支持的传输 必须:
- 相同功能:提供相同的操作和能力集。
- 一致行为:对相同请求返回语义上等效的结果。
- 相同错误处理:使用第 8 节中定义的错误代码在传输间一致地映射错误。
- 等效身份验证:支持
AgentCard中声明的相同身份验证方案。
3.4.2. 传输选择和协商¶
- 智能体声明:智能体 必须 在其
AgentCard中使用preferredTransport和additionalInterfaces字段声明所有支持的传输。 - 客户端选择:客户端 可以 选择智能体声明的任何传输。
- 无传输协商:A2A 不定义动态传输协商协议。客户端基于静态
AgentCard信息选择传输。 - 回退行为:客户端 应该 实现回退逻辑,如果首选传输失败,则尝试替代传输。具体的回退策略取决于实现。
3.4.3. 传输特定扩展¶
传输 可以 提供不损害功能等效性的传输特定优化或扩展:
- gRPC:可以利用 gRPC 特定功能,如双向流、元数据或自定义状态代码。
- REST:可以提供附加的 HTTP 缓存头或支持 HTTP 条件请求。
- JSON-RPC:可以在不与核心规范冲突的 JSON-RPC 请求/响应对象中包含附加字段。
此类扩展 必须 向后兼容,不得 破坏不支持扩展的客户端的互操作性。
3.5. 方法映射和命名约定¶
为确保跨不同传输的一致性和可预测性,A2A 定义了规范方法映射规则。
3.5.1. JSON-RPC 方法命名¶
JSON-RPC 方法 必须 遵循模式:{category}/{action},其中:
category表示资源类型(例如,"message"、"tasks"、"agent")action表示操作(例如,"send"、"get"、"cancel")- 嵌套操作使用正斜杠(例如,"tasks/pushNotificationConfig/set")
3.5.2. gRPC 方法命名¶
gRPC 方法 必须 遵循使用 PascalCase 的协议缓冲区服务约定:
- 将 JSON-RPC 类别/操作转换为 PascalCase 复合词
- 使用标准 gRPC 方法前缀(Get、Set、List、Create、Delete、Cancel)
3.5.3. HTTP+JSON/REST 方法命名¶
REST 端点 必须 遵循带有适当 HTTP 动词的 RESTful URL 模式:
- 使用基于资源的 URL:
/v1/{resource}[/{id}][:{action}] - 使用与 REST 语义对齐的标准 HTTP 方法
- 使用冒号表示法表示非 CRUD 操作
3.5.4. 方法映射合规性¶
实现多种传输时,智能体 必须:
- 使用标准映射:遵循 3.5.2 和 3.5.3 节中定义的方法映射。
- 保持功能等效性:每个传输特定方法 必须 在所有支持的传输中提供相同的功能。
- 一致参数:在传输间使用等效参数结构(考虑传输特定序列化差异)。
- 等效响应:对相同操作在所有传输中返回语义上等效的响应。
3.5.5. 扩展方法命名¶
对于核心 A2A 规范中未定义的自定义或扩展方法:
- JSON-RPC:遵循
{category}/{action}模式,带有清晰的命名空间(例如,myorg.extension/action) - gRPC:使用遵循协议缓冲区约定的适当服务和方法名称
- REST:使用带有适当 HTTP 方法的清晰基于资源的 URL
扩展方法 必须 得到清晰的文档,不得 与核心 A2A 方法名称或语义冲突。
3.5.6. 方法映射参考表¶
为快速参考,下表总结了所有传输间的方法映射:
| JSON-RPC 方法 | gRPC 方法 | REST 端点 | 描述 |
|---|---|---|---|
message/send |
SendMessage |
POST /v1/message:send |
向智能体发送消息 |
message/stream |
SendStreamingMessage |
POST /v1/message:stream |
发送带流式传输的消息 |
tasks/get |
GetTask |
GET /v1/tasks/{id} |
获取任务状态 |
tasks/list |
ListTask |
GET /v1/tasks |
列出任务(仅 gRPC/REST) |
tasks/cancel |
CancelTask |
POST /v1/tasks/{id}:cancel |
取消任务 |
tasks/resubscribe |
TaskSubscription |
POST /v1/tasks/{id}:subscribe |
恢复任务流式传输 |
tasks/pushNotificationConfig/set |
CreateTaskPushNotification |
POST /v1/tasks/{id}/pushNotificationConfigs |
设置推送通知配置 |
tasks/pushNotificationConfig/get |
GetTaskPushNotification |
GET /v1/tasks/{id}/pushNotificationConfigs/{configId} |
获取推送通知配置 |
tasks/pushNotificationConfig/list |
ListTaskPushNotification |
GET /v1/tasks/{id}/pushNotificationConfigs |
列出推送通知配置 |
tasks/pushNotificationConfig/delete |
DeleteTaskPushNotification |
DELETE /v1/tasks/{id}/pushNotificationConfigs/{configId} |
删除推送通知配置 |
agent/getAuthenticatedExtendedCard |
GetAgentCard |
GET /v1/card |
获取经过身份验证的 Agent Card |
4. 认证和授权¶
A2A 将智能体视为标准企业应用程序,依赖于既定的 Web 安全实践。身份信息 不 在 A2A JSON-RPC 载荷中传输;它在 HTTP 传输层处理。
有关企业安全方面的综合指南,请参见企业就绪功能。
4.1. 传输安全¶
如第 3.1 节所述,生产部署 必须 使用 HTTPS。实现 应该 使用现代 TLS 配置(推荐 TLS 1.3+)和强密码套件。
4.2. 服务器身份验证¶
A2A 客户端 应该 通过在 TLS 握手期间验证其 TLS 证书与受信任的证书颁发机构 (CA) 来验证 A2A 服务器的身份。
4.3. 客户端/用户身份和认证过程¶
- 发现要求:客户端通过
AgentCard中的authentication字段发现服务器所需的认证方案。方案名称通常与 OpenAPI 认证方法 对齐(例如,"Bearer" 表示 OAuth 2.0 令牌,"Basic" 表示基本认证,"ApiKey" 表示 API 密钥)。 - 凭据获取(带外):客户端通过特定于所需认证方案和身份提供者的 带外过程 获取必要的凭据(例如,API 密钥、OAuth 令牌、JWT)。此过程超出了 A2A 协议本身的范围。
- 凭据传输:客户端在发送到服务器的每个 A2A 请求的适当 HTTP 头 中包含这些凭据(例如,
Authorization: Bearer <token>、X-API-Key: <value>)。
4.4. 服务器认证责任¶
A2A 服务器:
- 必须 基于提供的 HTTP 凭据和其从其 Agent Card 声明的认证要求对每个传入请求进行认证。
- 应该 使用标准 HTTP 状态代码如
401 Unauthorized或403 Forbidden进行认证挑战或拒绝。 - 应该 在
401 Unauthorized响应中包含相关 HTTP 头(例如,WWW-Authenticate)以指示所需的认证方案,指导客户端。 - 应该 通过在 TLS 握手期间验证其 TLS 证书与受信任的证书颁发机构 (CA) 来验证客户端 webhook 服务器的身份。
4.5. 任务内认证(次要凭据)¶
如果智能体在执行任务期间需要 附加 凭据来访问 不同 系统或资源(例如,代表需要自己认证的用户访问特定工具):
- 它 应该 将 A2A 任务转换为
auth-required状态(参见TaskState)。 - 附带的
TaskStatus.message(通常是DataPart)应该 提供有关所需次要认证的详细信息,可能使用类似PushNotificationAuthenticationInfo的结构来描述需求。 - A2A 客户端然后通过带外获取这些新凭据,并在后续
message/send或message/stream请求中提供它们。这些凭据的使用方式(例如,如果智能体正在代理,则作为数据在 A2A 消息中传递,或由客户端直接与次要系统交互)取决于具体场景。
4.6. 授权¶
客户端通过认证后,A2A 服务器负责基于经过认证的客户端/用户身份及其自己的策略对请求进行授权。授权逻辑是实现特定的,可能基于以下内容进行强制:
- 请求的特定技能(例如,通过 Agent Card 中的
AgentSkill.id识别)。 - 任务内尝试的操作。
- 与智能体管理的资源相关的数据访问策略。
- 如果适用,与呈现令牌关联的 OAuth 范围。
服务器应实施最小权限原则。
5. 智能体发现:Agent Card¶
5.1. 目的¶
A2A 服务器 必须 提供 Agent Card。Agent Card 是一个 JSON 文档,描述服务器的身份、能力、技能、服务端点 URL 以及客户端应该如何认证和与之交互。客户端使用此信息来发现合适的智能体并配置其交互。
有关发现策略的更多信息,请参见智能体发现指南。
5.2. 发现机制¶
客户端可以通过各种方法找到 Agent Card,包括但不限于:
- 已知 URI:访问智能体域上的预定义路径(参见第 5.3 节)。
- 注册表/目录:查询智能体的策划目录或注册表(可能是企业特定的、公共的或领域特定的)。
- 直接配置:客户端可能预配置了 Agent Card URL 或卡片内容本身。
5.3. 推荐位置¶
如果使用已知 URI 策略,Agent Card 的推荐位置是:
https://{server_domain}/.well-known/agent-card.json
这遵循 RFC 8615 关于已知 URI 的原则。
5.4. Agent Card 的安全性¶
Agent Card 本身可能包含被视为敏感的信息。
- 如果 Agent Card 包含敏感信息,提供卡片的端点 必须 受到适当访问控制的保护(例如,mTLS、网络限制、获取卡片需要认证)。
- 通常 不建议 直接在 Agent Card 中包含明文机密(如静态 API 密钥)。优先选择客户端带外获取动态凭据的认证方案。
5.5. AgentCard 对象结构¶
/**
* The AgentCard is a self-describing manifest for an agent. It provides essential
* metadata including the agent's identity, capabilities, skills, supported
* communication methods, and security requirements.
*/
export interface AgentCard {
/**
* The version of the A2A protocol this agent supports.
* @default "0.3.0"
*/
protocolVersion: string;
/**
* A human-readable name for the agent.
*
* @TJS-examples ["Recipe Agent"]
*/
name: string;
/**
* A human-readable description of the agent, assisting users and other agents
* in understanding its purpose.
*
* @TJS-examples ["Agent that helps users with recipes and cooking."]
*/
description: string;
/**
* The preferred endpoint URL for interacting with the agent.
* This URL MUST support the transport specified by 'preferredTransport'.
*
* @TJS-examples ["https://api.example.com/a2a/v1"]
*/
url: string;
/**
* The transport protocol for the preferred endpoint (the main 'url' field).
* If not specified, defaults to 'JSONRPC'.
*
* IMPORTANT: The transport specified here MUST be available at the main 'url'.
* This creates a binding between the main URL and its supported transport protocol.
* Clients should prefer this transport and URL combination when both are supported.
*
* @default "JSONRPC"
* @TJS-examples ["JSONRPC", "GRPC", "HTTP+JSON"]
*/
preferredTransport?: TransportProtocol | string;
/**
* A list of additional supported interfaces (transport and URL combinations).
* This allows agents to expose multiple transports, potentially at different URLs.
*
* Best practices:
* - SHOULD include all supported transports for completeness
* - SHOULD include an entry matching the main 'url' and 'preferredTransport'
* - MAY reuse URLs if multiple transports are available at the same endpoint
* - MUST accurately declare the transport available at each URL
*
* Clients can select any interface from this list based on their transport capabilities
* and preferences. This enables transport negotiation and fallback scenarios.
*/
additionalInterfaces?: AgentInterface[];
/** An optional URL to an icon for the agent. */
iconUrl?: string;
/** Information about the agent's service provider. */
provider?: AgentProvider;
/**
* The agent's own version number. The format is defined by the provider.
*
* @TJS-examples ["1.0.0"]
*/
version: string;
/** An optional URL to the agent's documentation. */
documentationUrl?: string;
/** A declaration of optional capabilities supported by the agent. */
capabilities: AgentCapabilities;
/**
* A declaration of the security schemes available to authorize requests. The key is the
* scheme name. Follows the OpenAPI 3.0 Security Scheme Object.
*/
securitySchemes?: { [scheme: string]: SecurityScheme };
/**
* A list of security requirement objects that apply to all agent interactions. Each object
* lists security schemes that can be used. Follows the OpenAPI 3.0 Security Requirement Object.
* This list can be seen as an OR of ANDs. Each object in the list describes one possible
* set of security requirements that must be present on a request. This allows specifying,
* for example, "callers must either use OAuth OR an API Key AND mTLS."
*
* @TJS-examples [[{"oauth": ["read"]}, {"api-key": [], "mtls": []}]]
*/
security?: { [scheme: string]: string[] }[];
/**
* Default set of supported input MIME types for all skills, which can be
* overridden on a per-skill basis.
*/
defaultInputModes: string[];
/**
* Default set of supported output MIME types for all skills, which can be
* overridden on a per-skill basis.
*/
defaultOutputModes: string[];
/** The set of skills, or distinct capabilities, that the agent can perform. */
skills: AgentSkill[];
/**
* If true, the agent can provide an extended agent card with additional details
* to authenticated users. Defaults to false.
*/
supportsAuthenticatedExtendedCard?: boolean;
/** JSON Web Signatures computed for this AgentCard. */
signatures?: AgentCardSignature[];
}
// AgentCard conveys key information:
// - Overall details (version, name, description, uses)
// - Skills; a set of actions/solutions the agent can perform
// - Default modalities/content types supported by the agent.
// - Authentication requirements
// Next ID: 19
message AgentCard {
// The version of the A2A protocol this agent supports.
string protocol_version = 16;
// A human readable name for the agent.
// Example: "Recipe Agent"
string name = 1;
// A description of the agent's domain of action/solution space.
// Example: "Agent that helps users with recipes and cooking."
string description = 2;
// A URL to the address the agent is hosted at. This represents the
// preferred endpoint as declared by the agent.
string url = 3;
// The transport of the preferred endpoint. If empty, defaults to JSONRPC.
string preferred_transport = 14;
// Announcement of additional supported transports. Client can use any of
// the supported transports.
repeated AgentInterface additional_interfaces = 15;
// The service provider of the agent.
AgentProvider provider = 4;
// The version of the agent.
// Example: "1.0.0"
string version = 5;
// A url to provide additional documentation about the agent.
string documentation_url = 6;
// A2A Capability set supported by the agent.
AgentCapabilities capabilities = 7;
// The security scheme details used for authenticating with this agent.
map<string, SecurityScheme> security_schemes = 8;
// protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
// Security requirements for contacting the agent.
// This list can be seen as an OR of ANDs. Each object in the list describes
// one possible set of security requirements that must be present on a
// request. This allows specifying, for example, "callers must either use
// OAuth OR an API Key AND mTLS."
// Example:
// security {
// schemes { key: "oauth" value { list: ["read"] } }
// }
// security {
// schemes { key: "api-key" }
// schemes { key: "mtls" }
// }
repeated Security security = 9;
// protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
// The set of interaction modes that the agent supports across all skills.
// This can be overridden per skill. Defined as mime types.
repeated string default_input_modes = 10;
// The mime types supported as outputs from this agent.
repeated string default_output_modes = 11;
// Skills represent a unit of ability an agent can perform. This may
// somewhat abstract but represents a more focused set of actions that the
// agent is highly likely to succeed at.
repeated AgentSkill skills = 12;
// Whether the agent supports providing an extended agent card when
// the user is authenticated, i.e. is the card from .well-known
// different than the card from GetAgentCard.
bool supports_authenticated_extended_card = 13;
// JSON Web Signatures computed for this AgentCard.
repeated AgentCardSignature signatures = 17;
// An optional URL to an icon for the agent.
string icon_url = 18;
}
5.5.1. AgentProvider 对象¶
有关提供智能体的组织或实体的信息。
/**
* Represents the service provider of an agent.
*
* @TJS-examples [{ "organization": "Google", "url": "https://ai.google.dev" }]
*/
export interface AgentProvider {
/** The name of the agent provider's organization. */
organization: string;
/** A URL for the agent provider's website or relevant documentation. */
url: string;
}
5.5.2. AgentCapabilities 对象¶
指定智能体支持的可选 A2A 协议功能。
/**
* Defines optional capabilities supported by an agent.
*/
export interface AgentCapabilities {
/** Indicates if the agent supports Server-Sent Events (SSE) for streaming responses. */
streaming?: boolean;
/** Indicates if the agent supports sending push notifications for asynchronous task updates. */
pushNotifications?: boolean;
/** Indicates if the agent provides a history of state transitions for a task. */
stateTransitionHistory?: boolean;
/** A list of protocol extensions supported by the agent. */
extensions?: AgentExtension[];
}
// Defines the A2A feature set supported by the agent
message AgentCapabilities {
// If the agent will support streaming responses
bool streaming = 1;
// If the agent can send push notifications to the clients webhook
bool push_notifications = 2;
// Extensions supported by this agent.
repeated AgentExtension extensions = 3;
}
5.5.2.1. AgentExtension 对象¶
指定智能体支持的 A2A 协议扩展。
/**
* A declaration of a protocol extension supported by an Agent.
*
* @TJS-examples [{"uri": "https://developers.google.com/identity/protocols/oauth2", "description": "Google OAuth 2.0 authentication", "required": false}]
*/
export interface AgentExtension {
/** The unique URI identifying the extension. */
uri: string;
/** A human-readable description of how this agent uses the extension. */
description?: string;
/**
* If true, the client must understand and comply with the extension's requirements
* to interact with the agent.
*/
required?: boolean;
/** Optional, extension-specific configuration parameters. */
params?: { [key: string]: any };
}
// A declaration of an extension supported by an Agent.
message AgentExtension {
// The URI of the extension.
// Example: "https://developers.google.com/identity/protocols/oauth2"
string uri = 1;
// A description of how this agent uses this extension.
// Example: "Google OAuth 2.0 authentication"
string description = 2;
// Whether the client must follow specific requirements of the extension.
// Example: false
bool required = 3;
// Optional configuration for the extension.
google.protobuf.Struct params = 4;
}
5.5.3. SecurityScheme 对象¶
描述访问智能体 url 端点的认证要求。有关示例,请参见示例 Agent Card。
/**
* Defines a security scheme that can be used to secure an agent's endpoints.
* This is a discriminated union type based on the OpenAPI 3.0 Security Scheme Object.
*
* @see {@link https://swagger.io/specification/#security-scheme-object}
*/
export type SecurityScheme =
| APIKeySecurityScheme
| HTTPAuthSecurityScheme
| OAuth2SecurityScheme
| OpenIdConnectSecurityScheme
| MutualTLSSecurityScheme;
message SecurityScheme {
oneof scheme {
APIKeySecurityScheme api_key_security_scheme = 1;
HTTPAuthSecurityScheme http_auth_security_scheme = 2;
OAuth2SecurityScheme oauth2_security_scheme = 3;
OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4;
MutualTlsSecurityScheme mtls_security_scheme = 5;
}
}
5.5.4. AgentSkill 对象¶
描述智能体可以执行或解决的特定能力、功能或专业领域。
/**
* Represents a distinct capability or function that an agent can perform.
*/
export interface AgentSkill {
/** A unique identifier for the agent's skill. */
id: string;
/** A human-readable name for the skill. */
name: string;
/**
* A detailed description of the skill, intended to help clients or users
* understand its purpose and functionality.
*/
description: string;
/**
* A set of keywords describing the skill's capabilities.
*
* @TJS-examples [["cooking", "customer support", "billing"]]
*/
tags: string[];
/**
* Example prompts or scenarios that this skill can handle. Provides a hint to
* the client on how to use the skill.
*
* @TJS-examples [["I need a recipe for bread"]]
*/
examples?: string[];
/**
* The set of supported input MIME types for this skill, overriding the agent's defaults.
*/
inputModes?: string[];
/**
* The set of supported output MIME types for this skill, overriding the agent's defaults.
*/
outputModes?: string[];
/**
* Security schemes necessary for the agent to leverage this skill.
* As in the overall AgentCard.security, this list represents a logical OR of security
* requirement objects. Each object is a set of security schemes that must be used together
* (a logical AND).
*
* @TJS-examples [[{"google": ["oidc"]}]]
*/
security?: { [scheme: string]: string[] }[];
}
// AgentSkill represents a unit of action/solution that the agent can perform.
// One can think of this as a type of highly reliable solution that an agent
// can be tasked to provide. Agents have the autonomy to choose how and when
// to use specific skills, but clients should have confidence that if the
// skill is defined that unit of action can be reliably performed.
message AgentSkill {
// Unique identifier of the skill within this agent.
string id = 1;
// A human readable name for the skill.
string name = 2;
// A human (or llm) readable description of the skill
// details and behaviors.
string description = 3;
// A set of tags for the skill to enhance categorization/utilization.
// Example: ["cooking", "customer support", "billing"]
repeated string tags = 4;
// A set of example queries that this skill is designed to address.
// These examples should help the caller to understand how to craft requests
// to the agent to achieve specific goals.
// Example: ["I need a recipe for bread"]
repeated string examples = 5;
// Possible input modalities supported.
repeated string input_modes = 6;
// Possible output modalities produced
repeated string output_modes = 7;
// protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
// Security schemes necessary for the agent to leverage this skill.
// As in the overall AgentCard.security, this list represents a logical OR of
// security requirement objects. Each object is a set of security schemes
// that must be used together (a logical AND).
repeated Security security = 8;
// protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
}
5.5.5. AgentInterface 对象¶
提供目标 URL 和支持的传输组合的声明,用于与智能体交互。这使智能体能够通过多种传输协议暴露相同的功能。
/**
* Supported A2A transport protocols.
*/
export enum TransportProtocol {
JSONRPC = "JSONRPC", // JSON-RPC 2.0 over HTTP (mandatory)
GRPC = "GRPC", // gRPC over HTTP/2 (optional)
HTTP_JSON = "HTTP+JSON", // REST-style HTTP with JSON (optional)
}
/**
* Declares a combination of a target URL and a transport protocol for interacting with the agent.
* This allows agents to expose the same functionality over multiple transport mechanisms.
*/
export interface AgentInterface {
/**
* The URL where this interface is available. Must be a valid absolute HTTPS URL in production.
* @TJS-examples ["https://api.example.com/a2a/v1", "https://grpc.example.com/a2a", "https://rest.example.com/v1"]
*/
url: string;
/**
* The transport protocol supported at this URL.
*
* @TJS-examples ["JSONRPC", "GRPC", "HTTP+JSON"]
*/
transport: TransportProtocol | string;
}
// Defines additional transport information for the agent.
message AgentInterface {
// The url this interface is found at.
string url = 1;
// The transport supported this url. This is an open form string, to be
// easily extended for many transport protocols. The core ones officially
// supported are JSONRPC, GRPC and HTTP+JSON.
string transport = 2;
}
transport 字段 应该 使用核心 A2A 传输协议值之一:
"JSONRPC": HTTP 上的 JSON-RPC 2.0"GRPC": HTTP/2 上的 gRPC"HTTP+JSON": REST 风格的 HTTP 与 JSON
可以 使用附加传输值用于未来扩展,但此类扩展 不得 与核心 A2A 协议功能冲突。
5.5.6. AgentCardSignature 对象¶
表示用于验证 AgentCard 完整性的 JSON Web 签名 (JWS)。
/**
* AgentCardSignature represents a JWS signature of an AgentCard.
* This follows the JSON format of an RFC 7515 JSON Web Signature (JWS).
*/
export interface AgentCardSignature {
/**
* The protected JWS header for the signature. This is a Base64url-encoded
* JSON object, as per RFC 7515.
*/
protected: string;
/** The computed signature, Base64url-encoded. */
signature: string;
/** The unprotected JWS header values. */
header?: { [key: string]: any };
}
// AgentCardSignature represents a JWS signature of an AgentCard.
// This follows the JSON format of an RFC 7515 JSON Web Signature (JWS).
message AgentCardSignature {
// The protected JWS header for the signature. This is always a
// base64url-encoded JSON object. Required.
string protected = 1 [(google.api.field_behavior) = REQUIRED];
// The computed signature, base64url-encoded. Required.
string signature = 2 [(google.api.field_behavior) = REQUIRED];
// The unprotected JWS header values.
google.protobuf.Struct header = 3;
}
5.6. 传输声明和 URL 关系¶
AgentCard 必须 正确声明 URL 和传输协议之间的关系:
5.6.1. 主 URL 和首选传输¶
- 主 URL 要求:
url字段 必须 指定智能体的主要端点。 - 传输对应关系:主
url处可用的传输协议 必须 与preferredTransport字段匹配。 - 必需声明:
preferredTransport字段是 必需的,必须 存在于每个AgentCard中。 - 传输可用性:主
url必须 支持在preferredTransport中声明的传输协议。
5.6.2. 附加接口¶
- URL 唯一性:
additionalInterfaces中的每个AgentInterface应该 指定不同的 URL 以确保清晰度,但如果多个传输协议在相同端点可用,则 可以 重用 URL。 - 传输声明:每个
AgentInterface必须 准确声明其指定 URL 处可用的传输协议。 - 完整性:
additionalInterfaces数组 应该 包括所有支持的传输,包括主 URL 的传输以确保完整性。
5.6.3. 客户端传输选择规则¶
客户端 必须 遵循选择传输时的这些规则:
- 解析传输声明:从主
url/preferredTransport组合和所有additionalInterfaces中提取可用传输。 - 首选声明偏好:如果客户端支持
preferredTransport,它 应该 使用主url。 - 回退选择:如果首选传输不受客户端支持,它 可以 从
additionalInterfaces中选择任何支持的传输。 - 优雅降级:客户端 应该 实现回退逻辑,如果首选传输失败,则尝试替代传输。
- URL-传输匹配:客户端 必须 使用 AgentCard 中声明的所选传输协议的正确 URL。
5.6.4. 验证要求¶
AgentCard 必须 满足这些验证要求:
- 传输一致性:
preferredTransport值 必须 存在,必须 在主url处可用。 - 接口完整性:如果提供了
additionalInterfaces,它 应该 包括与主url和preferredTransport对应的条目。 - 无冲突:同一 URL 不得 在不同接口声明中声明冲突的传输协议。
- 最小传输要求:智能体 必须 通过主
url/preferredTransport组合或additionalInterfaces声明至少一个支持的传输协议。
5.7. 示例 Agent Card¶
{
"protocolVersion": "0.2.9",
"name": "GeoSpatial Route Planner Agent",
"description": "Provides advanced route planning, traffic analysis, and custom map generation services. This agent can calculate optimal routes, estimate travel times considering real-time traffic, and create personalized maps with points of interest.",
"url": "https://georoute-agent.example.com/a2a/v1",
"preferredTransport": "JSONRPC",
"additionalInterfaces" : [
{"url": "https://georoute-agent.example.com/a2a/v1", "transport": "JSONRPC"},
{"url": "https://georoute-agent.example.com/a2a/grpc", "transport": "GRPC"},
{"url": "https://georoute-agent.example.com/a2a/json", "transport": "HTTP+JSON"}
],
"provider": {
"organization": "Example Geo Services Inc.",
"url": "https://www.examplegeoservices.com"
},
"iconUrl": "https://georoute-agent.example.com/icon.png",
"version": "1.2.0",
"documentationUrl": "https://docs.examplegeoservices.com/georoute-agent/api",
"capabilities": {
"streaming": true,
"pushNotifications": true,
"stateTransitionHistory": false
},
"securitySchemes": {
"google": {
"type": "openIdConnect",
"openIdConnectUrl": "https://accounts.google.com/.well-known/openid-configuration"
}
},
"security": [{ "google": ["openid", "profile", "email"] }],
"defaultInputModes": ["application/json", "text/plain"],
"defaultOutputModes": ["application/json", "image/png"],
"skills": [
{
"id": "route-optimizer-traffic",
"name": "Traffic-Aware Route Optimizer",
"description": "Calculates the optimal driving route between two or more locations, taking into account real-time traffic conditions, road closures, and user preferences (e.g., avoid tolls, prefer highways).",
"tags": ["maps", "routing", "navigation", "directions", "traffic"],
"examples": [
"Plan a route from '1600 Amphitheatre Parkway, Mountain View, CA' to 'San Francisco International Airport' avoiding tolls.",
"{\"origin\": {\"lat\": 37.422, \"lng\": -122.084}, \"destination\": {\"lat\": 37.7749, \"lng\": -122.4194}, \"preferences\": [\"avoid_ferries\"]}"
],
"inputModes": ["application/json", "text/plain"],
"outputModes": [
"application/json",
"application/vnd.geo+json",
"text/html"
]
},
{
"id": "custom-map-generator",
"name": "Personalized Map Generator",
"description": "Creates custom map images or interactive map views based on user-defined points of interest, routes, and style preferences. Can overlay data layers.",
"tags": ["maps", "customization", "visualization", "cartography"],
"examples": [
"Generate a map of my upcoming road trip with all planned stops highlighted.",
"Show me a map visualizing all coffee shops within a 1-mile radius of my current location."
],
"inputModes": ["application/json"],
"outputModes": [
"image/png",
"image/jpeg",
"application/json",
"text/html"
]
}
],
"supportsAuthenticatedExtendedCard": true,
"signatures": [
{
"protected": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpPU0UiLCJraWQiOiJrZXktMSIsImprdSI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYWdlbnQvandrcy5qc29uIn0",
"signature": "QFdkNLNszlGj3z3u0YQGt_T9LixY3qtdQpZmsTdDHDe3fXV9y9-B3m2-XgCpzuhiLt8E0tV6HXoZKHv4GtHgKQ"
}
]
}
6. 协议数据对象¶
这些对象定义了 A2A 协议的 JSON-RPC 方法中交换的数据结构。
6.1. Task 对象¶
表示 A2A 服务器为 A2A 客户端处理的工作的有状态单元。任务封装了与特定目标或请求相关的整个交互。已达到终止状态(completed、canceled、rejected 或 failed)的任务无法重启。处于完成状态的任务 应该 使用工件向客户端返回生成的输出。有关更多信息,请参阅任务生命周期指南。
/**
* Represents a single, stateful operation or conversation between a client and an agent.
*/
export interface Task {
/** A unique identifier (e.g. UUID) for the task, generated by the server for a new task. */
id: string;
/**
* A server-generated unique identifier (e.g. UUID) for maintaining context across multiple related tasks or interactions.
*/
contextId: string;
/** The current status of the task, including its state and a descriptive message. */
status: TaskStatus;
/** An array of messages exchanged during the task, representing the conversation history. */
history?: Message[];
/** A collection of artifacts generated by the agent during the execution of the task. */
artifacts?: Artifact[];
/** Optional metadata for extensions. The key is an extension-specific identifier. */
metadata?: {
[key: string]: any;
};
/** The type of this object, used as a discriminator. Always 'task' for a Task. */
readonly kind: "task";
}
// Task is the core unit of action for A2A. It has a current status
// and when results are created for the task they are stored in the
// artifact. If there are multiple turns for a task, these are stored in
// history.
message Task {
// Unique identifier (e.g. UUID) for the task, generated by the server for a
// new task.
string id = 1;
// Unique identifier (e.g. UUID) for the contextual collection of interactions
// (tasks and messages). Created by the A2A server.
string context_id = 2;
// The current status of a Task, including state and a message.
TaskStatus status = 3;
// A set of output artifacts for a Task.
repeated Artifact artifacts = 4;
// protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
// The history of interactions from a task.
repeated Message history = 5;
// protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
// A key/value object to store custom metadata about a task.
google.protobuf.Struct metadata = 6;
}
6.2. TaskStatus 对象¶
表示 Task 的当前状态和相关上下文(例如,来自智能体的消息)。
/**
* Represents the status of a task at a specific point in time.
*/
export interface TaskStatus {
/** The current state of the task's lifecycle. */
state: TaskState;
/** An optional, human-readable message providing more details about the current status. */
message?: Message;
/**
* An ISO 8601 datetime string indicating when this status was recorded.
*
* @TJS-examples ["2023-10-27T10:00:00Z"]
*/
timestamp?: string;
}
// A container for the status of a task
message TaskStatus {
// The current state of this task
TaskState state = 1;
// A message associated with the status.
Message update = 2 [json_name = "message"];
// Timestamp when the status was recorded.
// Example: "2023-10-27T10:00:00Z"
google.protobuf.Timestamp timestamp = 3;
}
6.3. TaskState 枚举¶
定义 Task 的可能生命周期状态。
/**
* Defines the lifecycle states of a Task.
*/
export enum TaskState {
/** The task has been submitted and is awaiting execution. */
Submitted = "submitted",
/** The agent is actively working on the task. */
Working = "working",
/** The task is paused and waiting for input from the user. */
InputRequired = "input-required",
/** The task has been successfully completed. */
Completed = "completed",
/** The task has been canceled by the user. */
Canceled = "canceled",
/** The task failed due to an error during execution. */
Failed = "failed",
/** The task was rejected by the agent and was not started. */
Rejected = "rejected",
/** The task requires authentication to proceed. */
AuthRequired = "auth-required",
/** The task is in an unknown or indeterminate state. */
Unknown = "unknown",
}
// The set of states a Task can be in.
enum TaskState {
TASK_STATE_UNSPECIFIED = 0;
// Represents the status that acknowledges a task is created
TASK_STATE_SUBMITTED = 1;
// Represents the status that a task is actively being processed
TASK_STATE_WORKING = 2;
// Represents the status a task is finished. This is a terminal state
TASK_STATE_COMPLETED = 3;
// Represents the status a task is done but failed. This is a terminal state
TASK_STATE_FAILED = 4;
// Represents the status a task was cancelled before it finished.
// This is a terminal state.
TASK_STATE_CANCELLED = 5;
// Represents the status that the task requires information to complete.
// This is an interrupted state.
TASK_STATE_INPUT_REQUIRED = 6;
// Represents the status that the agent has decided to not perform the task.
// This may be done during initial task creation or later once an agent
// has determined it can't or won't proceed. This is a terminal state.
TASK_STATE_REJECTED = 7;
// Represents the state that some authentication is needed from the upstream
// client. Authentication is expected to come out-of-band thus this is not
// an interrupted or terminal state.
TASK_STATE_AUTH_REQUIRED = 8;
}
6.4. Message 对象¶
表示客户端和智能体之间的一次通信或一段上下文信息。消息用于指令、提示、回复和状态更新。
/**
* Represents a single message in the conversation between a user and an agent.
*/
export interface Message {
/** Identifies the sender of the message. `user` for the client, `agent` for the service. */
readonly role: "user" | "agent";
/**
* An array of content parts that form the message body. A message can be
* composed of multiple parts of different types (e.g., text and files).
*/
parts: Part[];
/** Optional metadata for extensions. The key is an extension-specific identifier. */
metadata?: {
[key: string]: any;
};
/** The URIs of extensions that are relevant to this message. */
extensions?: string[];
/**
* A list of other task IDs that this message references for additional context.
*/
referenceTaskIds?: string[];
/**
* A unique identifier for the message, typically a UUID, generated by the sender.
*/
messageId: string;
/**
* The ID of the task this message is part of. Can be omitted for the first message of a new task.
*/
taskId?: string;
/**
* The context ID for this message, used to group related interactions.
*/
contextId?: string;
/** The type of this object, used as a discriminator. Always 'message' for a Message. */
readonly kind: "message";
}
// Message is one unit of communication between client and server. It is
// associated with a context and optionally a task. Since the server is
// responsible for the context definition, it must always provide a context_id
// in its messages. The client can optionally provide the context_id if it
// knows the context to associate the message to. Similarly for task_id,
// except the server decides if a task is created and whether to include the
// task_id.
message Message {
// The unique identifier (e.g. UUID)of the message. This is required and
// created by the message creator.
string message_id = 1;
// The context id of the message. This is optional and if set, the message
// will be associated with the given context.
string context_id = 2;
// The task id of the message. This is optional and if set, the message
// will be associated with the given task.
string task_id = 3;
// A role for the message.
Role role = 4;
// protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
// Content is the container of the message content.
repeated Part content = 5;
// protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
// Any optional metadata to provide along with the message.
google.protobuf.Struct metadata = 6;
// The URIs of extensions that are present or contributed to this Message.
repeated string extensions = 7;
}
6.5. Part 联合类型¶
表示 Message 或 Artifact 中的不同内容片段。Part 是一个联合类型,表示可导出的内容,可以是 TextPart、FilePart 或 DataPart。所有 Part 类型还包括一个可选的 metadata 字段(Record<string, any>),用于部分特定的元数据。
// Part represents a container for a section of communication content.
// Parts can be purely textual, some sort of file (image, video, etc) or
// a structured data blob (i.e. JSON).
message Part {
oneof part {
string text = 1;
FilePart file = 2;
DataPart data = 3;
}
// Optional metadata associated with this part.
google.protobuf.Struct metadata = 4;
}
/**
* Defines base properties common to all message or artifact parts.
*/
export interface PartBase {
/** Optional metadata associated with this part. */
metadata?: {
[key: string]: any;
};
}
它 必须 是以下之一:
6.5.1. TextPart 对象¶
用于传达纯文本内容。
/**
* Represents a text segment within a message or artifact.
*/
export interface TextPart extends PartBase {
/** The type of this part, used as a discriminator. Always 'text'. */
readonly kind: "text";
/** The string content of the text part. */
text: string;
}
6.5.2. FilePart 对象¶
用于传达基于文件的内容。
/**
* Represents a file segment within a message or artifact. The file content can be
* provided either directly as bytes or as a URI.
*/
export interface FilePart extends PartBase {
/** The type of this part, used as a discriminator. Always 'file'. */
readonly kind: "file";
/** The file content, represented as either a URI or as base64-encoded bytes. */
file: FileWithBytes | FileWithUri;
}
// FilePart represents the different ways files can be provided. If files are
// small, directly feeding the bytes is supported via file_with_bytes. If the
// file is large, the agent should read the content as appropriate directly
// from the file_with_uri source.
message FilePart {
oneof file {
string file_with_uri = 1;
bytes file_with_bytes = 2;
}
string mime_type = 3;
string name = 4;
}
6.5.3. DataPart 对象¶
用于传达结构化 JSON 数据。对于表单、参数或任何机器可读信息很有用。
6.6 FileBase 对象¶
文件内容的基础实体。
/**
* Defines base properties for a file.
*/
export interface FileBase {
/** An optional name for the file (e.g., "document.pdf"). */
name?: string;
/** The MIME type of the file (e.g., "application/pdf"). */
mimeType?: string;
}
6.6.1 FileWithBytes 对象¶
表示文件的数据,用于 FilePart 中。
/**
* Represents a file with its content provided directly as a base64-encoded string.
*/
export interface FileWithBytes extends FileBase {
/** The base64-encoded content of the file. */
bytes: string;
/** The `uri` property must be absent when `bytes` is present. */
uri?: never;
}
6.6.2 FileWithUri 对象¶
表示文件的 URI,用于 FilePart 中。
/**
* Represents a file with its content located at a specific URI.
*/
export interface FileWithUri extends FileBase {
/** A URL pointing to the file's content. */
uri: string;
/** The `bytes` property must be absent when `uri` is present. */
bytes?: never;
}
6.7. Artifact 对象¶
表示智能体在任务期间生成的有形输出。工件是智能体工作的结果或产品。
/**
* Represents a file, data structure, or other resource generated by an agent during a task.
*/
export interface Artifact {
/**
* A unique identifier (e.g. UUID) for the artifact within the scope of the task.
*/
artifactId: string;
/** An optional, human-readable name for the artifact. */
name?: string;
/** An optional, human-readable description of the artifact. */
description?: string;
/** An array of content parts that make up the artifact. */
parts: Part[];
/** Optional metadata for extensions. The key is an extension-specific identifier. */
metadata?: {
[key: string]: any;
};
/** The URIs of extensions that are relevant to this artifact. */
extensions?: string[];
}
// Artifacts are the container for task completed results. These are similar
// to Messages but are intended to be the product of a task, as opposed to
// point-to-point communication.
message Artifact {
// Unique identifier (e.g. UUID) for the artifact. It must be at least unique
// within a task.
string artifact_id = 1;
// A human readable name for the artifact.
string name = 3;
// A human readable description of the artifact, optional.
string description = 4;
// The content of the artifact.
repeated Part parts = 5;
// Optional metadata included with the artifact.
google.protobuf.Struct metadata = 6;
// The URIs of extensions that are present or contributed to this Artifact.
repeated string extensions = 7;
}
6.8. PushNotificationConfig 对象¶
客户端提供给服务器的配置,用于发送关于任务更新的异步推送通知。
/**
* Defines the configuration for setting up push notifications for task updates.
*/
export interface PushNotificationConfig {
/**
* A unique identifier (e.g. UUID) for the push notification configuration, set by the client
* to support multiple notification callbacks.
*/
id?: string;
/** The callback URL where the agent should send push notifications. */
url: string;
/** A unique token for this task or session to validate incoming push notifications. */
token?: string;
/** Optional authentication details for the agent to use when calling the notification URL. */
authentication?: PushNotificationAuthenticationInfo;
}
// Configuration for setting up push notifications for task updates.
message PushNotificationConfig {
// A unique identifier (e.g. UUID) for this push notification.
string id = 1;
// Url to send the notification too
string url = 2;
// Token unique for this task/session
string token = 3;
// Information about the authentication to sent with the notification
AuthenticationInfo authentication = 4;
}
6.9. PushNotificationAuthenticationInfo 对象¶
指定认证要求的通用结构,通常在 PushNotificationConfig 中使用,以描述 A2A 服务器应如何向客户端的 webhook 进行认证。
/**
* Defines authentication details for a push notification endpoint.
*/
export interface PushNotificationAuthenticationInfo {
/** A list of supported authentication schemes (e.g., 'Basic', 'Bearer'). */
schemes: string[];
/** Optional credentials required by the push notification endpoint. */
credentials?: string;
}
6.10. TaskPushNotificationConfig 对象¶
用作 tasks/pushNotificationConfig/set 方法的 params 对象和 tasks/pushNotificationConfig/get 方法的 result 对象。
/**
* A container associating a push notification configuration with a specific task.
*/
export interface TaskPushNotificationConfig {
/**
* The unique identifier (e.g. UUID) of the task.
*/
taskId: string;
/** The push notification configuration for this task. */
pushNotificationConfig: PushNotificationConfig;
}
6.11. JSON-RPC 结构¶
A2A 遵循标准的 JSON-RPC 2.0 结构用于请求和响应。
6.11.1. JSONRPCRequest 对象¶
所有 A2A 方法调用都封装在 JSON-RPC 请求对象中。
jsonrpc:指定 JSON-RPC 协议版本的字符串。必须 恰好是"2.0"。method:包含要调用的方法名称的字符串(例如,"message/send"、"tasks/get")。params:包含在调用方法期间使用的参数值的结构化值。如果方法不需要参数,此成员 可以 省略。A2A 方法通常对params使用object。id:由客户端建立的标识符,如果包含,必须 包含字符串、数字或NULL值。如果不包含,则假定为通知。对于期望响应的请求,该值 不应 为NULL,数字 不应 包含小数部分。如果包含,服务器 必须 在响应对象中使用相同的值。此成员用于关联两个对象之间的上下文。A2A 方法通常期望响应或流,因此id通常存在且非空。
6.11.2. JSONRPCResponse 对象¶
来自 A2A 服务器的响应封装在 JSON-RPC 响应对象中。
jsonrpc:指定 JSON-RPC 协议版本的字符串。必须 恰好是"2.0"。id:此成员是 必需的。它 必须 与请求对象中id成员的值相同。如果在请求对象中检测id时出现错误(例如,解析错误/无效请求),它 必须 为null。- 或者
result:此成员在成功时是 必需的。如果调用方法时出现错误,则 不得 存在。此成员的值由服务器上调用的方法确定。 - 或者
error:此成员在失败时是 必需的。如果调用期间未触发错误,则 不得 存在。此成员的值 必须 是JSONRPCError对象。 - 成员
result和error是互斥的:一个 必须 存在,另一个 必须 不存在。
6.12. JSONRPCError 对象¶
当 JSON-RPC 调用遇到错误时,响应对象将包含一个值为此结构的 error 成员。
/**
* Represents a JSON-RPC 2.0 Error object, included in an error response.
*/
export interface JSONRPCError {
/**
* A number that indicates the error type that occurred.
*/
code: number;
/**
* A string providing a short description of the error.
*/
message: string;
/**
* A primitive or structured value containing additional information about the error.
* This may be omitted.
*/
data?: any;
}
7. 协议 RPC 方法¶
所有 A2A RPC 方法都通过向 A2A 服务器的 url(如其 AgentCard 中指定)发送 HTTP POST 请求由 A2A 客户端调用。HTTP POST 请求的正文 必须 是 JSONRPCRequest 对象,Content-Type 头 必须 是 application/json。
A2A 服务器的 HTTP 响应正文 必须 是 JSONRPCResponse 对象(或者,对于流式方法,是 SSE 流,其中每个事件的数据是 JSONRPCResponse)。JSON-RPC 响应的 Content-Type 是 application/json。对于 SSE 流,它是 text/event-stream。
7.1. message/send¶
向智能体发送消息以启动新交互或继续现有交互。此方法适用于同步请求/响应交互,或者当客户端轮询(使用 tasks/get)监视长时间运行的任务时可接受。已达到终止状态(completed、canceled、rejected 或 failed)的任务无法重启。向此类任务发送消息将导致错误。有关更多信息,请参阅任务生命周期指南。
- URL:
message/send - HTTP 方法:
POST - 载荷:
MessageSendParams - 响应:
Task|Message(消息对象或处理消息后任务的当前或最终状态)。
- URL:
SendMessage - HTTP 方法:
POST - 载荷:
- 响应:
所有传输在失败时的 error 响应是 JSONRPCError 或等效对象。
7.1.1. MessageSendParams 对象¶
/**
* Defines the parameters for a request to send a message to an agent. This can be used
* to create a new task, continue an existing one, or restart a task.
*/
export interface MessageSendParams {
/** The message object being sent to the agent. */
message: Message;
/** Optional configuration for the send request. */
configuration?: MessageSendConfiguration;
/** Optional metadata for extensions. */
metadata?: {
[key: string]: any;
};
}
message SendMessageRequest {
// The message to send to the agent.
Message request = 1
[(google.api.field_behavior) = REQUIRED, json_name = "message"];
// Configuration for the send request.
SendMessageConfiguration configuration = 2;
// Optional metadata for the request.
google.protobuf.Struct metadata = 3;
}
/**
* Defines configuration options for a `message/send` or `message/stream` request.
*/
export interface MessageSendConfiguration {
/** A list of output MIME types the client is prepared to accept in the response. */
acceptedOutputModes?: string[];
/** The number of most recent messages from the task's history to retrieve in the response. */
historyLength?: number;
/** Configuration for the agent to send push notifications for updates after the initial response. */
pushNotificationConfig?: PushNotificationConfig;
/** If true, the client will wait for the task to complete. The server may reject this if the task is long-running. */
blocking?: boolean;
}
// Configuration of a send message request.
message SendMessageConfiguration {
// The output modes that the agent is expected to respond with.
repeated string accepted_output_modes = 1;
// A configuration of a webhook that can be used to receive updates
PushNotificationConfig push_notification = 2;
// The maximum number of messages to include in the history. if 0, the
// history will be unlimited.
int32 history_length = 3;
// If true, the message will be blocking until the task is completed. If
// false, the message will be non-blocking and the task will be returned
// immediately. It is the caller's responsibility to check for any task
// updates.
bool blocking = 4;
}
7.2. message/stream¶
向智能体发送消息以启动/继续任务 并 订阅客户端通过服务器发送事件 (SSE) 实时更新该任务。此方法要求服务器具有 AgentCard.capabilities.streaming: true。就像 message/send 一样,已达到终止状态(completed、canceled、rejected 或 failed)的任务无法重启。向此类任务发送消息将导致错误。有关更多信息,请参阅任务生命周期指南。
- URL:
message/stream - HTTP 方法:
POST - 载荷:
MessageSendParams(与message/send相同) - 响应: 服务器发送事件流。每个 SSE
data字段包含SendStreamingMessageResponse
- URL:
SendStreamingMessage - HTTP 方法:
POST - 载荷:
- 响应:
7.2.1. SendStreamingMessageResponse 对象¶
这是在 message/stream 请求或 tasks/resubscribe 请求中服务器发送的每个服务器发送事件的 data 字段中找到的 JSON 对象的结构。
/**
* Represents a JSON-RPC response for the `message/stream` method.
*/
export type SendStreamingMessageResponse =
| SendStreamingMessageSuccessResponse
| JSONRPCErrorResponse;
/**
* Represents a successful JSON-RPC response for the `message/stream` method.
* The server may send multiple response objects for a single request.
*/
export interface SendStreamingMessageSuccessResponse
extends JSONRPCSuccessResponse {
/** The result, which can be a Message, Task, or a streaming update event. */
result: Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent;
}
// The stream response for a message. The stream should be one of the following
// sequences:
// If the response is a message, the stream should contain one, and only one,
// message and then close
// If the response is a task lifecycle, the first response should be a Task
// object followed by zero or more TaskStatusUpdateEvents and
// TaskArtifactUpdateEvents. The stream should complete when the Task
// if in an interrupted or terminal state. A stream that ends before these
// conditions are met are
message StreamResponse {
oneof payload {
Task task = 1;
Message msg = 2 [json_name = "message"];
TaskStatusUpdateEvent status_update = 3;
TaskArtifactUpdateEvent artifact_update = 4;
}
}
7.2.2. TaskStatusUpdateEvent 对象¶
在流式传输过程中携带任务状态更改的信息。这是 SendStreamingMessageSuccessResponse 中 result 类型之一。
/**
* An event sent by the agent to notify the client of a change in a task's status.
* This is typically used in streaming or subscription models.
*/
export interface TaskStatusUpdateEvent {
/**
* The ID of the task that was updated.
*/
taskId: string;
/**
* The context ID associated with the task.
*/
contextId: string;
/** The type of this event, used as a discriminator. Always 'status-update'. */
readonly kind: "status-update";
/** The new status of the task. */
status: TaskStatus;
/** If true, this is the final event in the stream for this interaction. */
final: boolean;
/** Optional metadata for extensions. */
metadata?: {
[key: string]: any;
};
}
// TaskStatusUpdateEvent is a delta even on a task indicating that a task
// has changed.
message TaskStatusUpdateEvent {
// The id of the task that is changed
string task_id = 1;
// The id of the context that the task belongs to
string context_id = 2;
// The new status of the task.
TaskStatus status = 3;
// Whether this is the last status update expected for this task.
bool final = 4;
// Optional metadata to associate with the task update.
google.protobuf.Struct metadata = 5;
}
7.2.3. TaskArtifactUpdateEvent 对象¶
在流式传输过程中携带任务生成的新工件或更新工件(或工件块)。这是 SendTaskStreamingResponse 中 result 类型之一。
/**
* An event sent by the agent to notify the client that an artifact has been
* generated or updated. This is typically used in streaming models.
*/
export interface TaskArtifactUpdateEvent {
/**
* The ID of the task this artifact belongs to.
*/
taskId: string;
/**
* The context ID associated with the task.
*/
contextId: string;
/** The type of this event, used as a discriminator. Always 'artifact-update'. */
readonly kind: "artifact-update";
/** The artifact that was generated or updated. */
artifact: Artifact;
/** If true, the content of this artifact should be appended to a previously sent artifact with the same ID. */
append?: boolean;
/** If true, this is the final chunk of the artifact. */
lastChunk?: boolean;
/** Optional metadata for extensions. */
metadata?: {
[key: string]: any;
};
}
// TaskArtifactUpdateEvent represents a task delta where an artifact has
// been generated.
message TaskArtifactUpdateEvent {
// The id of the task for this artifact
string task_id = 1;
// The id of the context that this task belongs too
string context_id = 2;
// The artifact itself
Artifact artifact = 3;
// Whether this should be appended to a prior one produced
bool append = 4;
// Whether this represents the last part of an artifact
bool last_chunk = 5;
// Optional metadata associated with the artifact update.
google.protobuf.Struct metadata = 6;
}
7.3. tasks/get¶
检索先前启动任务的当前状态(包括状态、工件和可选的历史记录)。这通常用于轮询通过 message/send 启动的任务状态,或在通过推送通知通知或 SSE 流结束后获取任务的最终状态。
- URL:
tasks/get - HTTP 方法:
POST - 载荷:
TaskQueryParams - 响应:
Task
- URL:
GetTask - HTTP 方法:
POST - 载荷:
- 响应:
Task
- URL:
v1/tasks/{id}?historyLength={historyLength} - HTTP 方法:
GET - 载荷: 无
- 响应:
Task
7.3.1. TaskQueryParams 对象¶
7.4. tasks/cancel¶
请求取消正在进行的任务。服务器将尝试取消任务,但成功不保证(例如,任务可能已经完成或失败,或者在当前阶段可能不支持取消)。
- URL:
tasks/cancel - HTTP 方法:
POST - 载荷:
TaskIdParams - 响应:
Task
- URL:
CancelTask - HTTP 方法:
POST - 载荷:
- 响应:
Task
7.4.1. TaskIdParams 对象(用于 tasks/cancel 和 tasks/pushNotificationConfig/get)¶
仅包含任务 ID 和可选元数据的简单对象。
7.5. tasks/pushNotificationConfig/set¶
为指定任务设置或更新推送通知配置。这允许客户端告诉服务器在哪里以及如何发送任务的异步更新。要求服务器具有 AgentCard.capabilities.pushNotifications: true。
- URL:
tasks/pushNotificationConfig/set - HTTP 方法:
POST - 载荷:
TaskPushNotificationConfig - 响应:
TaskPushNotificationConfig
- URL:
CreateTaskPushNotification - HTTP 方法:
POST - 载荷:
- 响应:
TaskPushNotificationConfig
7.6. tasks/pushNotificationConfig/get¶
检索指定任务的当前推送通知配置。要求服务器具有 AgentCard.capabilities.pushNotifications: true。
- URL:
tasks/pushNotificationConfig/get - HTTP 方法:
POST - 载荷:
GetTaskPushNotificationConfigParams - 响应:
TaskPushNotificationConfig
- URL:
GetTaskPushNotification - HTTP 方法:
POST - 载荷:
- 响应:
TaskPushNotificationConfig
- URL:
/v1/tasks/{taskId}/pushNotificationConfigs/{configId} - HTTP 方法:
GET - 载荷: 无
- 响应:
TaskPushNotificationConfig
响应 error 类型(失败时): JSONRPCError(例如,PushNotificationNotSupportedError、TaskNotFoundError)。
7.6.1. GetTaskPushNotificationConfigParams 对象(tasks/pushNotificationConfig/get)¶
用于获取任务推送通知配置的对象。
7.7. tasks/pushNotificationConfig/list¶
检索指定任务的相关推送通知配置。要求服务器具有 AgentCard.capabilities.pushNotifications: true。
- URL:
tasks/pushNotificationConfig/list - HTTP 方法:
POST - 载荷:
ListTaskPushNotificationConfigParams - 响应:
TaskPushNotificationConfig[]
- URL:
ListTaskPushNotification - HTTP 方法:
POST - 载荷:
- 响应:
repeated TaskPushNotificationConfig
- URL:
/v1/tasks/{id}/pushNotificationConfigs - HTTP 方法:
GET - 载荷::无
- 响应:
[TaskPushNotificationConfig]
7.7.1. ListTaskPushNotificationConfigParams 对象(tasks/pushNotificationConfig/list)¶
用于获取任务推送通知配置的对象。
7.8. tasks/pushNotificationConfig/delete¶
删除任务的相关推送通知配置。要求服务器具有 AgentCard.capabilities.pushNotifications: true。
- 请求
params类型:DeleteTaskPushNotificationConfigParams - 响应
result类型(成功时):[null] - 响应
error类型(失败时):JSONRPCError(例如,PushNotificationNotSupportedError、TaskNotFoundError)。
7.8.1. DeleteTaskPushNotificationConfigParams 对象(tasks/pushNotificationConfig/delete)¶
用于删除任务的相关推送通知配置的对象。
7.9. tasks/resubscribe¶
允许客户端在先前连接(来自 message/stream 或较早的 tasks/resubscribe)中断后重新连接到正在进行任务的 SSE 流。要求服务器具有 AgentCard.capabilities.streaming: true。
其目的是恢复接收 后续 更新。服务器关于断开连接期间错过的事件的行为(例如,是否尝试回填一些错过的事件或仅从重新订阅点发送新事件)取决于实现,并未被此规范严格定义。
- URL:
tasks/resubscribe - HTTP 方法:
POST - 载荷:
TaskIdParams - 响应: 服务器发送事件流。每个 SSE
data字段包含SendStreamingMessageResponse
- URL:
TaskSubscription - HTTP 方法:
POST - 载荷:
- 响应:
7.10. agent/getAuthenticatedExtendedCard¶
在客户端认证后检索可能更详细的 Agent Card 版本。仅当 AgentCard.supportsAuthenticatedExtendedCard 为 true 时才可使用此端点。
- 认证:客户端 必须 使用公共
AgentCard.securitySchemes和AgentCard.security字段中声明的方案之一对请求进行认证。 - 响应
result类型(成功时):AgentCard(完整的 Agent Card 对象,可能包含公共卡中不存在的附加详细信息或技能)。 - 响应
error类型(失败时):标准 HTTP 错误代码。401 Unauthorized:认证失败(缺少或无效凭据)。服务器 应该 包含WWW-Authenticate头。
- URL:
agent/getAuthenticatedExtendedCard - HTTP 方法:
POST - 载荷: 无
- 响应:
AgentCard
- URL:
GetAgentCard - HTTP 方法:
POST - 载荷: 无
- 响应:
AgentCard
- URL:
/v1/card - HTTP 方法:
GET - 载荷: 无
- 响应:
AgentCard
获取此认证卡的客户端 应该 在其认证会话期间或直到卡版本更改时,用从此端点接收的内容替换其缓存的公共 Agent Card。
/**
* Represents a successful JSON-RPC response for the `agent/getAuthenticatedExtendedCard` method.
*/
export interface GetAuthenticatedExtendedCardSuccessResponse
extends JSONRPCSuccessResponse {
/** The result is an Agent Card object. */
result: AgentCard;
}
8. 错误处理¶
A2A 使用标准的 JSON-RPC 2.0 错误代码和结构 来报告错误。错误在 JSONRPCErrorResponse 对象的 error 成员中返回。请参见 JSONRPCError 对象定义。
8.1. 标准 JSON-RPC 错误¶
这些是由 JSON-RPC 2.0 规范定义的标准代码。
| 代码 | JSON-RPC 规范含义 | 典型的 A2A message |
描述 |
|---|---|---|---|
-32700 |
解析错误 | 无效的 JSON 载荷 | 服务器接收到格式不正确的 JSON。 |
-32600 |
无效请求 | 无效的 JSON-RPC 请求 | JSON 载荷是有效的 JSON,但不是有效的 JSON-RPC 请求对象。 |
-32601 |
方法未找到 | 方法未找到 | 请求的 A2A RPC method(例如,"tasks/foo")不存在或不受支持。 |
-32602 |
无效参数 | 无效的方法参数 | 为方法提供的 params 无效(例如,错误的类型,缺少必需字段)。 |
-32603 |
内部错误 | 内部服务器错误 | 处理过程中服务器上发生意外错误。 |
-32000 到 -32099 |
服务器错误 | (服务器定义) | 为实现定义的服务器错误保留。A2A 特定错误使用此范围。 |
8.2. A2A 特定错误¶
这些是在 JSON-RPC 服务器错误范围(-32000 到 -32099)内定义的自定义错误代码,以提供有关 A2A 相关问题的更具体反馈。服务器在适用时 应该 使用这些代码。
| 代码 | 错误名称(概念性) | 典型的 message 字符串 |
描述 |
|---|---|---|---|
-32001 |
TaskNotFoundError |
任务未找到 | 指定的任务 id 不对应于现有或活动任务。它可能是无效的、过期的或已完成并清除的。 |
-32002 |
TaskNotCancelableError |
任务无法取消 | 尝试取消处于不可取消状态的任务(例如,它已达到终端状态如 completed、failed 或 canceled)。 |
-32003 |
PushNotificationNotSupportedError |
不支持推送通知 | 客户端尝试使用推送通知功能(例如,tasks/pushNotificationConfig/set),但服务器智能体不支持它们(即,AgentCard.capabilities.pushNotifications 为 false)。 |
-32004 |
UnsupportedOperationError |
此操作不受支持 | 请求的操作或其特定方面(可能由参数暗示)不被此服务器智能体实现支持。比方法未找到更广泛。 |
-32005 |
ContentTypeNotSupportedError |
不兼容的内容类型 | 请求的 message.parts 中提供的 媒体类型(或工件隐含的)不被智能体或调用的特定技能支持。 |
-32006 |
InvalidAgentResponseError |
无效的智能体响应类型 | 智能体为请求的方法生成了无效响应 |
-32007 |
AuthenticatedExtendedCardNotConfiguredError |
未配置认证扩展卡 | 智能体未配置认证扩展卡。 |
服务器可以在 -32000 到 -32099 范围内定义附加错误代码,用于未在上述内容中涵盖的更具体场景,但它们 应该 清晰地记录这些代码。JSONRPCError 对象的 data 字段可用于为任何错误提供更结构化的详细信息。
9. 常见工作流和示例¶
本节提供了常见 A2A 交互的说明性 JSON 示例。时间戳、上下文 ID 和请求/响应 ID 仅供演示目的。为简洁起见,如果某些可选字段不是示例的核心,则可能会省略。
9.1. 获取认证扩展 Agent Card¶
场景: 客户端发现一个公共 Agent Card,表明支持认证扩展卡,并希望获取完整详细信息。
- 客户端获取公共 Agent Card:
服务器响应公共 Agent Card(如第 5.6 节中的示例),包括 supportsAuthenticatedExtendedCard: true(在根级别)和 securitySchemes。
-
客户端从公共卡中识别所需的认证。
-
客户端通过带外获取必要的凭据(例如,使用 Google 执行 OAuth 2.0 流程,生成访问令牌)。
-
客户端使用
agent/getAuthenticatedExtendedCard请求获取认证扩展 Agent Card:
-
服务器认证和授权请求。
-
服务器响应完整的 Agent Card 作为 JSON-RPC 结果:
9.2. 基本执行(同步/轮询风格)¶
场景: 客户端提出一个简单问题,智能体快速响应一个任务
- 客户端使用
message/send发送消息:
{
"jsonrpc": "2.0",
"id": 1,
"method": "message/send",
"params": {
"message": {
"role": "user",
"parts": [
{
"kind": "text",
"text": "tell me a joke"
}
],
"messageId": "9229e770-767c-417b-a0b0-f0741243c589"
},
"metadata": {}
}
}
- 服务器处理请求,创建任务并响应(任务快速完成)
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"id": "363422be-b0f9-4692-a24d-278670e7c7f1",
"contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4",
"status": {
"state": "completed"
},
"artifacts": [
{
"artifactId": "9b6934dd-37e3-4eb1-8766-962efaab63a1",
"name": "joke",
"parts": [
{
"kind": "text",
"text": "Why did the chicken cross the road? To get to the other side!"
}
]
}
],
"history": [
{
"role": "user",
"parts": [
{
"kind": "text",
"text": "tell me a joke"
}
],
"messageId": "9229e770-767c-417b-a0b0-f0741243c589",
"taskId": "363422be-b0f9-4692-a24d-278670e7c7f1",
"contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4"
}
],
"kind": "task",
"metadata": {}
}
}
如果任务是长时间运行的,服务器可能最初响应 status.state: "working"。然后客户端会定期调用 tasks/get,参数为:{"id": "363422be-b0f9-4692-a24d-278670e7c7f1"},直到任务达到终端状态。
场景: 客户端提出一个简单问题,智能体快速响应而无需任务
- 客户端使用
message/send发送消息:
{
"jsonrpc": "2.0",
"id": 1,
"method": "message/send",
"params": {
"message": {
"role": "user",
"parts": [
{
"kind": "text",
"text": "tell me a joke"
}
],
"messageId": "9229e770-767c-417b-a0b0-f0741243c589"
},
"metadata": {}
}
}
- 服务器处理请求,快速响应而无需任务
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"messageId": "363422be-b0f9-4692-a24d-278670e7c7f1",
"contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4",
"parts": [
{
"kind": "text",
"text": "Why did the chicken cross the road? To get to the other side!"
}
],
"kind": "message",
"metadata": {}
}
}
9.3. 流式任务执行(SSE)¶
场景: 客户端要求智能体写一篇描述附加图片的长论文。
- 客户端发送消息并使用
message/stream订阅:
{
"jsonrpc": "2.0",
"id": 1,
"method": "message/stream",
"params": {
"message": {
"role": "user",
"parts": [
{
"kind": "text",
"text": "write a long paper describing the attached pictures"
},
{
"kind": "file",
"file": {
"mimeType": "image/png",
"data": "<base64-encoded-content>"
}
}
],
"messageId": "bbb7dee1-cf5c-4683-8a6f-4114529da5eb"
},
"metadata": {}
}
}
- 服务器响应 HTTP 200 OK,
Content-Type: text/event-stream,并开始发送 SSE 事件:
事件 1:任务状态更新 - 工作中
data: {
"jsonrpc": "2.0",
"id": 1,
"result": {
"id": "225d6247-06ba-4cda-a08b-33ae35c8dcfa",
"contextId": "05217e44-7e9f-473e-ab4f-2c2dde50a2b1",
"status": {
"state": "submitted",
"timestamp":"2025-04-02T16:59:25.331844"
},
"history": [
{
"role": "user",
"parts": [
{
"kind": "text",
"text": "write a long paper describing the attached pictures"
},
{
"kind": "file",
"file": {
"mimeType": "image/png",
"data": "<base64-encoded-content>"
}
}
],
"messageId": "bbb7dee1-cf5c-4683-8a6f-4114529da5eb",
"taskId": "225d6247-06ba-4cda-a08b-33ae35c8dcfa",
"contextId": "05217e44-7e9f-473e-ab4f-2c2dde50a2b1"
}
],
"kind": "task",
"metadata": {}
}
}
data: {
"jsonrpc": "2.0",
"id": 1,
"result": {
"taskId": "225d6247-06ba-4cda-a08b-33ae35c8dcfa",
"contextId": "05217e44-7e9f-473e-ab4f-2c2dde50a2b1",
"artifact": {
"artifactId": "9b6934dd-37e3-4eb1-8766-962efaab63a1",
"parts": [
{"kind":"text", "text": "<section 1...>"}
]
},
"append": false,
"lastChunk": false,
"kind":"artifact-update"
}
}
data: {
"jsonrpc": "2.0",
"id": 1,
"result": {
"taskId": "225d6247-06ba-4cda-a08b-33ae35c8dcfa",
"contextId": "05217e44-7e9f-473e-ab4f-2c2dde50a2b1",
"artifact": {
"artifactId": "9b6934dd-37e3-4eb1-8766-962efaab63a1",
"parts": [
{"kind":"text", "text": "<section 2...>"}
],
},
"append": true,
"lastChunk": false,
"kind":"artifact-update"
}
}
data: {
"jsonrpc": "2.0",
"id": 1,
"result": {
"taskId": "225d6247-06ba-4cda-a08b-33ae35c8dcfa",
"contextId": "05217e44-7e9f-473e-ab4f-2c2dde50a2b1",
"artifact": {
"artifactId": "9b6934dd-37e3-4eb1-8766-962efaab63a1",
"parts": [
{"kind":"text", "text": "<section 3...>"}
]
},
"append": true,
"lastChunk": true,
"kind":"artifact-update"
}
}
data: {
"jsonrpc": "2.0",
"id": 1,
"result": {
"taskId": "225d6247-06ba-4cda-a08b-33ae35c8dcfa",
"contextId": "05217e44-7e9f-473e-ab4f-2c2dde50a2b1",
"status": {
"state": "completed",
"timestamp":"2025-04-02T16:59:35.331844"
},
"final": true,
"kind":"status-update"
}
}
(服务器在 final:true 事件后关闭 SSE 连接)。
9.4. 多轮交互(需要输入)¶
场景: 客户端想要预订航班,智能体需要更多信息。
- 客户端使用
message/send发送消息:
{
"jsonrpc": "2.0",
"id": "req-003",
"method": "message/send",
"params": {
"message": {
"role": "user",
"parts": [{ "kind": "text", "text": "I'd like to book a flight." }]
},
"messageId": "c53ba666-3f97-433c-a87b-6084276babe2"
}
}
- 服务器响应,任务状态为
input-required:
{
"jsonrpc": "2.0",
"id": "req-003",
"result": {
"id": "3f36680c-7f37-4a5f-945e-d78981fafd36",
"contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4",
"status": {
"state": "input-required",
"message": {
"role": "agent",
"parts": [
{
"kind": "text",
"text": "Sure, I can help with that! Where would you like to fly to, and from where? Also, what are your preferred travel dates?"
}
],
"messageId": "c2e1b2dd-f200-4b04-bc22-1b0c65a1aad2",
"taskId": "3f36680c-7f37-4a5f-945e-d78981fafd36",
"contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4"
},
"timestamp": "2024-03-15T10:10:00Z"
},
"history": [
{
"role": "user",
"parts": [
{
"kind": "text",
"text": "I'd like to book a flight."
}
],
"messageId": "c53ba666-3f97-433c-a87b-6084276babe2",
"taskId": "3f36680c-7f37-4a5f-945e-d78981fafd36",
"contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4"
}
],
"kind": "task"
}
}
- 客户端
message/send(提供所需输入,使用 相同 任务 ID):
{
"jsonrpc": "2.0",
"id": "req-004",
"method": "message/send",
"params": {
"message": {
"role": "user",
"parts": [
{
"kind": "text",
"text": "I want to fly from New York (JFK) to London (LHR) around October 10th, returning October 17th."
}
],
"contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4",
"taskId": "3f36680c-7f37-4a5f-945e-d78981fafd36",
"messageId": "0db1d6c4-3976-40ed-b9b8-0043ea7a03d3"
},
"configuration": {
"blocking": true
}
}
}
- 服务器处理新输入并响应(例如,任务完成或需要更多输入):
{
"jsonrpc": "2.0",
"id": "req-004",
"result": {
"id": "3f36680c-7f37-4a5f-945e-d78981fafd36",
"contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4",
"status": {
"state": "completed",
"message": {
"role": "agent",
"parts": [
{
"kind": "text",
"text": "Okay, I've found a flight for you. Confirmation XYZ123. Details are in the artifact."
}
]
}
},
"artifacts": [
{
"artifactId": "9b6934dd-37e3-4eb1-8766-962efaab63a1",
"name": "FlightItinerary.json",
"parts": [
{
"kind": "data",
"data": {
"confirmationId": "XYZ123",
"from": "JFK",
"to": "LHR",
"departure": "2024-10-10T18:00:00Z",
"arrival": "2024-10-11T06:00:00Z",
"returnDeparture": "..."
}
}
]
}
],
"history": [
{
"role": "user",
"parts": [
{
"kind": "text",
"text": "I'd like to book a flight."
}
],
"messageId": "c53ba666-3f97-433c-a87b-6084276babe2",
"taskId": "3f36680c-7f37-4a5f-945e-d78981fafd36",
"contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4"
},
{
"role": "agent",
"parts": [
{
"kind": "text",
"text": "Sure, I can help with that! Where would you like to fly to, and from where? Also, what are your preferred travel dates?"
}
],
"messageId": "c2e1b2dd-f200-4b04-bc22-1b0c65a1aad2",
"taskId": "3f36680c-7f37-4a5f-945e-d78981fafd36",
"contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4"
},
{
"role": "user",
"parts": [
{
"kind": "text",
"text": "I want to fly from New York (JFK) to London (LHR) around October 10th, returning October 17th."
}
],
"contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4",
"taskId": "3f36680c-7f37-4a5f-945e-d78981fafd36",
"messageId": "0db1d6c4-3976-40ed-b9b8-0043ea7a03d3"
}
],
"kind": "task",
"metadata": {}
}
}
9.5. 推送通知设置和使用¶
场景: 客户端请求生成长时间运行的报告,并希望在准备就绪时通过 webhook 通知它。
- 客户端
message/send与pushNotification配置:
{
"jsonrpc": "2.0",
"id": "req-005",
"method": "message/send",
"params": {
"message": {
"role": "user",
"parts": [
{
"kind": "text",
"text": "Generate the Q1 sales report. This usually takes a while. Notify me when it's ready."
}
],
"messageId": "6dbc13b5-bd57-4c2b-b503-24e381b6c8d6"
},
"configuration": {
"pushNotificationConfig": {
"url": "https://client.example.com/webhook/a2a-notifications",
"token": "secure-client-token-for-task-aaa",
"authentication": {
"schemes": ["Bearer"]
// 假设服务器知道如何获取用于此 webhook 受众的 Bearer 令牌,
// 或者这暗示 webhook 是公共的/使用 'token' 进行认证。
// 'credentials' 可以在服务器需要时提供更多细节。
}
}
}
}
}
- 服务器确认任务(例如,状态
submitted或working):
{
"jsonrpc": "2.0",
"id": "req-005",
"result": {
"id": "43667960-d455-4453-b0cf-1bae4955270d",
"contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4",
"status": { "state": "submitted", "timestamp": "2024-03-15T11:00:00Z" }
// ... 其他字段 ...
}
}
-
(稍后)A2A 服务器完成任务并向
https://client.example.com/webhook/a2a-notifications发送 POST 通知: -
HTTP 头可能包括:
Authorization: Bearer <server_jwt_for_webhook_audience>(如果服务器向 webhook 进行认证)Content-Type: application/jsonX-A2A-Notification-Token: secure-client-token-for-task-aaa
- HTTP 正文(任务对象作为 JSON 载荷发送):
{
"id": "43667960-d455-4453-b0cf-1bae4955270d",
"contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4",
"status": { "state": "completed", "timestamp": "2024-03-15T18:30:00Z" },
"kind": "task"
// ... 其他字段 ...
}
-
客户端的 Webhook 服务:
-
接收 POST。
- 验证
Authorization头(如果适用)。 - 验证
X-A2A-Notification-Token。 - 内部处理通知(例如,更新应用程序状态,通知最终用户)。
9.6. 文件交换(上传和下载)¶
场景: 客户端发送图像进行分析,智能体返回修改后的图像。
- 客户端
message/send与FilePart(上传图像字节):
{
"jsonrpc": "2.0",
"id": "req-007",
"method": "message/send",
"params": {
"message": {
"role": "user",
"parts": [
{
"kind": "text",
"text": "Analyze this image and highlight any faces."
},
{
"kind": "file",
"file": {
"name": "input_image.png",
"mimeType": "image/png",
"bytes": "iVBORw0KGgoAAAANSUhEUgAAAAUA..." // Base64 编码的图像数据
}
}
],
"messageId": "6dbc13b5-bd57-4c2b-b503-24e381b6c8d6"
}
}
}
- 服务器处理图像并响应
FilePart中的工件(例如,提供修改图像的 URI):
{
"jsonrpc": "2.0",
"id": "req-007",
"result": {
"id": "43667960-d455-4453-b0cf-1bae4955270d",
"contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4",
"status": { "state": "completed", "timestamp": "2024-03-15T12:05:00Z" },
"artifacts": [
{
"artifactId": "9b6934dd-37e3-4eb1-8766-962efaab63a1",
"name": "processed_image_with_faces.png",
"parts": [
{
"kind": "file",
"file": {
"name": "output.png",
"mimeType": "image/png",
// 服务器可能提供临时存储位置的 URI
"uri": "https://storage.example.com/processed/task-bbb/output.png?token=xyz"
// 或者,或者返回字节:
// "bytes": "ASEDGhw0KGgoAAAANSUhEUgAA..."
}
}
]
}
],
"kind": "task"
}
}
9.7. 结构化数据交换(请求和提供 JSON)¶
场景: 客户端请求特定 JSON 格式的开放支持工单列表。
- 客户端
message/send,Part.metadata暗示所需的输出模式/媒体类型: (注意:A2A 在 v0.2.0 中没有正式标准化模式协商,但可以按客户端/服务器之间的约定使用metadata进行此类暗示)。
{
"jsonrpc": "2.0",
"id": 9,
"method": "message/send",
"params": {
"message": {
"role": "user",
"parts": [
{
"kind": "text",
"text": "Show me a list of my open IT tickets",
"metadata": {
"mimeType": "application/json",
"schema": {
"type": "array",
"items": {
"type": "object",
"properties": {
"ticketNumber": { "type": "string" },
"description": { "type": "string" }
}
}
}
}
}
],
"messageId": "85b26db5-ffbb-4278-a5da-a7b09dea1b47"
},
"metadata": {}
}
}
- 服务器响应结构化 JSON 数据:
{
"jsonrpc": "2.0",
"id": 9,
"result": {
"id": "d8c6243f-5f7a-4f6f-821d-957ce51e856c",
"contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4",
"status": {
"state": "completed",
"timestamp": "2025-04-17T17:47:09.680794"
},
"artifacts": [
{
"artifactId": "c5e0382f-b57f-4da7-87d8-b85171fad17c",
"parts": [
{
"kind": "text",
"text": "[{\"ticketNumber\":\"REQ12312\",\"description\":\"request for VPN access\"},{\"ticketNumber\":\"REQ23422\",\"description\":\"Add to DL - team-gcp-onboarding\"}]"
}
]
}
],
"kind": "task"
}
}
这些示例说明了 A2A 在处理各种交互模式和数据类型方面的灵活性。实现者应参考详细对象定义以了解所有字段和约束。
10. 附录¶
10.1. 与 MCP(模型上下文协议)的关系¶
A2A 和 MCP 是为智能体系统的不同方面设计的互补协议:
- 模型上下文协议 (MCP): 专注于标准化 AI 模型和智能体如何连接并与 工具、API、数据源和其他外部资源 交互。它定义了描述工具能力的结构化方式(如 LLM 中的函数调用),传递输入并接收结构化输出。将 MCP 视为智能体 使用 特定能力或访问资源的"操作方法"。
- Agent2Agent 协议 (A2A): 专注于标准化独立的、通常不透明的 AI 智能体如何作为对等方相互通信和协作。A2A 提供应用程序级协议,使智能体能够发现彼此、协商交互模式、管理共享任务并交换对话上下文或复杂结果。这是关于智能体如何 合作 或 委派 工作。
它们如何协同工作: A2A 客户端智能体可能请求 A2A 服务器智能体执行复杂任务。服务器智能体反过来可能使用 MCP 与几个底层工具、API 或数据源交互,以收集信息或执行完成 A2A 任务所需的行动。
有关更详细的比较,请参见 A2A 和 MCP 指南。
10.2. 安全考虑摘要¶
安全性是 A2A 中的首要考虑因素。关键考虑因素包括:
- 传输安全: 在生产环境中始终使用带有强 TLS 配置的 HTTPS。
- 认证:
- 通过标准 HTTP 机制处理(例如,带有 Bearer 令牌、API 密钥的
Authorization头)。 - 要求在
AgentCard中声明。 - 凭据必须由客户端带外获取。
- A2A 服务器必须对每个请求进行认证。
- 通过标准 HTTP 机制处理(例如,带有 Bearer 令牌、API 密钥的
- 授权:
- 基于认证身份的服务器端责任。
- 实施最小权限原则。
- 可以基于技能、操作或数据进行细化。
- 推送通知安全:
- Webhook URL 验证(由发送通知的 A2A 服务器)至关重要,以防止 SSRF。
- A2A 服务器向客户端 webhook 的认证是必不可少的。
- 客户端 webhook 接收方验证通知(验证它来自合法的 A2A 服务器且相关)是关键的。
- 有关推送通知安全的详细信息,请参见流式传输和异步操作指南。
- 输入验证: 服务器必须严格验证所有 RPC 参数和
Message和Artifact部分中数据的内容/结构,以防止注入攻击或处理错误。 - 资源管理: 实施速率限制、并发控制和资源限制,以保护智能体免受滥用或过载。
- 数据隐私: 遵守
Message和Artifact部分中交换数据的所有适用隐私法规。最小化敏感数据传输。
有关全面讨论,请参阅企业就绪功能指南。
11. A2A 合规要求¶
本节定义了 A2A 合规实现的规范要求。
11.1. 智能体合规性¶
对于被认为是 A2A 合规 的智能体,它 必须:
11.1.1. 传输支持要求¶
- 支持至少一种传输:智能体 必须 实现第 3.2 节中定义的至少一种传输协议。
- 暴露 Agent Card:必须 提供有效的
AgentCard文档,如第 5 节中定义。 - 声明传输能力:必须 在
AgentCard中准确声明所有支持的传输,使用preferredTransport和additionalInterfaces字段,遵循第 5.6 节中的要求。
11.1.2. 核心方法实现¶
必须 通过至少一种支持的传输实现以下所有核心方法:
message/send- 发送消息和启动任务tasks/get- 检索任务状态和结果tasks/cancel- 请求任务取消
11.1.3. 可选方法实现¶
可以 实现以下可选方法:
message/stream- 流式消息交互(需要capabilities.streaming: true)tasks/resubscribe- 恢复现有任务的流式传输(需要capabilities.streaming: true)tasks/pushNotificationConfig/set- 配置推送通知(需要capabilities.pushNotifications: true)tasks/pushNotificationConfig/get- 检索推送通知配置(需要capabilities.pushNotifications: true)tasks/pushNotificationConfig/list- 列出推送通知配置(需要capabilities.pushNotifications: true)tasks/pushNotificationConfig/delete- 删除推送通知配置(需要capabilities.pushNotifications: true)agent/authenticatedExtendedCard- 检索认证扩展 Agent Card(需要supportsAuthenticatedExtendedCard: true)
11.1.4. 多传输合规性¶
如果智能体支持附加传输(gRPC、HTTP+JSON),它 必须:
- 功能等效性:在所有支持的传输中提供相同的功能。
- 一致行为:对相同操作返回语义上等效的结果。
- 传输特定要求:符合第 3.2 节中为每个支持的传输定义的所有要求。
- 方法映射合规性:使用第 3.5 节中定义的标准方法映射用于所有支持的传输。
11.1.5. 数据格式合规性¶
- JSON-RPC 结构:必须 使用第 6.11 节中定义的有效 JSON-RPC 2.0 请求/响应对象。
- A2A 数据对象:必须 使用第 6 节中定义的数据结构用于所有协议实体。
- 错误处理:必须 使用第 8 节中定义的错误代码。
11.2. 客户端合规性¶
对于被认为是 A2A 合规 的客户端,它 必须:
11.2.1. 传输支持¶
- 多传输能力:必须 能够与使用至少一种传输协议的智能体通信。
- Agent Card 处理:必须 能够解析和解释
AgentCard文档。 - 传输选择:必须 能够从智能体声明的能力中选择适当的传输,遵循第 5.6.3 节中定义的规则。
11.2.2. 协议实现¶
- 核心方法使用:必须 正确构造至少
message/send和tasks/get方法的请求。 - 错误处理:必须 正确处理第 8.2 节中定义的所有 A2A 错误代码。
- 认证:必须 在与需要认证的智能体交互时支持至少一种认证方法。
11.2.3. 可选客户端功能¶
客户端 可以 实现:
- 多传输支持:支持 gRPC 和/或 HTTP+JSON 传输。
- 流式支持:处理流式方法和服务器发送事件。
- 推送通知处理:作为推送通知的 webhook 端点。
- 扩展 Agent Card:检索和使用认证扩展 Agent Card。
11.3. 合规测试¶
实现 应该 通过以下方式验证合规性:
- 传输互操作性:测试与使用不同传输实现的智能体通信。
- 方法映射验证:验证所有支持的传输使用第 3.5 节中定义的正确方法名称和 URL 模式。
- 错误处理:验证对所有定义的错误条件的正确处理。
- 数据格式验证:确保 JSON 模式与
types/src/types.ts中的 TypeScript 类型定义匹配。 - 多传输一致性:对于多传输智能体,验证所有支持的传输之间的功能等效性。