跳到内容

Agent2Agent (A2A) 协议规范 (草案 v1.0)

最新发布版本 0.3.0

以前的版本

有关版本之间的更改,请参阅发布说明

1. 简介

Agent2Agent (A2A) 协议是一个开放标准,旨在促进独立、可能不透明的 AI 代理系统之间的通信和互操作性。在一个代理可能使用不同框架、语言或由不同供应商构建的生态系统中,A2A 提供了一种通用的语言和交互模型。

本文档提供了 A2A 协议的详细技术规范。其主要目标是使代理能够

  • 发现彼此的能力。
  • 协商交互方式(文本、文件、结构化数据)。
  • 管理协作任务。
  • 安全地交换信息以实现用户目标,而无需访问彼此的内部状态、内存或工具。

1.1. A2A 的主要目标

  • 互操作性: 弥合不同代理系统之间的通信鸿沟。
  • 协作: 使代理能够委派任务、交换上下文并共同处理复杂的用户请求。
  • 发现: 允许代理动态发现和理解其他代理的能力。
  • 灵活性: 支持各种交互模式,包括同步请求/响应、用于实时更新的流式传输以及用于长时间运行任务的异步推送通知。
  • 安全性: 促进适用于企业环境的安全通信模式,依赖于标准网络安全实践。
  • 异步性: 原生支持长时间运行的任务和可能涉及人工介入场景的交互。

1.2. 指导原则

  • 简单: 重用现有、易于理解的标准(HTTP、JSON-RPC 2.0、Server-Sent Events)。
  • 企业就绪: 通过与既定的企业实践保持一致来解决身份验证、授权、安全性、隐私、跟踪和监控问题。
  • 异步优先: 专为(可能非常)长时间运行的任务和人工介入交互而设计。
  • 模式无关: 支持交换各种内容类型,包括文本、音频/视频(通过文件引用)、结构化数据/表单,以及可能嵌入的 UI 组件(例如,部分中引用的 iframe)。
  • 不透明执行: 代理基于声明的能力和交换的信息进行协作,而无需共享其内部思想、计划或工具实现。

要更广泛地了解 A2A 的目的和优势,请参阅什么是 A2A?

1.3. 规范结构

本规范分为三个不同的层,它们协同工作以提供完整的协议定义

graph TB
    subgraph L1 ["A2A Data Model"]
        direction LR
        A[Task] ~~~ B[Message] ~~~ C[AgentCard] ~~~ D[Part] ~~~ E[Artifact] ~~~ F[Extension]
    end

    subgraph L2 ["A2A Operations"]
        direction LR
        G[Send Message] ~~~ H[Stream Message] ~~~ I[Get Task] ~~~ J[List Tasks] ~~~ K[Cancel Task] ~~~ L[Get Agent Card]
    end

    subgraph L3 ["Protocol Bindings"]
        direction LR
        M[JSON-RPC Methods] ~~~ N[gRPC RPCs] ~~~ O[HTTP/REST Endpoints] ~~~ P[Custom Bindings]
    end

    %% Dependencies between layers
    L1 --> L2
    L2 --> L3


    style A fill:#e1f5fe
    style B fill:#e1f5fe
    style C fill:#e1f5fe
    style D fill:#e1f5fe
    style E fill:#e1f5fe
    style F fill:#e1f5fe

    style G fill:#f3e5f5
    style H fill:#f3e5f5
    style I fill:#f3e5f5
    style J fill:#f3e5f5
    style K fill:#f3e5f5
    style L fill:#f3e5f5

    style M fill:#e8f5e8
    style N fill:#e8f5e8
    style O fill:#e8f5e8

    style L1 fill:#f0f8ff,stroke:#333,stroke-width:2px
    style L2 fill:#faf0ff,stroke:#333,stroke-width:2px
    style L3 fill:#f0fff0,stroke:#333,stroke-width:2px

第 1 层:规范数据模型 定义了所有 A2A 实现必须理解的核心数据结构和消息格式。这些是表示为协议缓冲区消息的协议无关定义。

第 2 层:抽象操作 描述了 A2A 代理必须支持的基本能力和行为,而与它们如何通过特定协议公开无关。

第 3 层:协议绑定 提供了抽象操作和数据结构到特定协议绑定(JSON-RPC、gRPC、HTTP/REST)的具体映射,包括方法名称、端点模式和协议特定行为。

这种分层方法确保了

  • 核心语义在所有协议绑定中保持一致
  • 可以添加新的协议绑定,而无需更改基本数据模型
  • 开发人员可以独立于绑定问题来推断 A2A 操作
  • 通过对规范数据模型的共同理解来维护互操作性

1.4 规范性内容

除了本文档中定义的协议要求外,文件spec/a2a.proto是所有协议数据对象和请求/响应消息的唯一权威规范性定义。生成的 JSON 工件(spec/a2a.json,在构建时生成且未提交)可以为了方便工具和网站而发布,但它是一个非规范的构建工件。SDK 语言绑定、模式和任何其他派生形式必须从 proto(直接或通过代码生成)重新生成,而不是手动编辑。

变更控制和弃用生命周期

  • 引入:当 proto 消息或字段重命名时,新名称被添加,而现有已发布名称仍然可用,但标记为已弃用,直到下一个主要版本发布。
  • 文档:本规范必须包含一个迁移附录(附录 A),其中列举了旧版→当前名称映射以及计划的移除版本。
  • 锚点:旧版文档锚点必须保留(作为隐藏的 HTML 锚点),以避免破坏入站链接。
  • SDK/模式别名:SDK 和 JSON 模式提供已弃用的别名类型/定义以保持向后兼容性。
  • 移除:已弃用的名称不应在其替代项引入的下一个主要版本之前移除。

自动生成

文档构建会动态生成specification/json/a2a.json(该文件未在源代码控制中跟踪)。未来的改进可能会发布 OpenAPI v3 + JSON Schema 包以增强工具。

基本原理

以 proto 文件作为规范源确保了协议中立性,减少了规范偏差,并为生态系统提供了确定性的演进路径。

2. 术语

2.1. 需求语言

本文档中的关键词“必须”、“不得”、“必需”、“应”、“不应”、“建议”、“不建议”、“推荐”、“可以”和“可选”应根据RFC 2119中的描述进行解释。

2.2. 核心概念

A2A 围绕几个核心概念展开。有关详细解释,请参阅核心概念指南

  • A2A 客户端: 代表用户或另一个系统向 A2A 服务器发起请求的应用程序或代理。
  • A2A 服务器(远程代理): 公开符合 A2A 规范的端点,处理任务并提供响应的代理或代理系统。
  • 代理卡: 由 A2A 服务器发布的 JSON 元数据文档,描述其身份、能力、技能、服务终点和身份验证要求。
  • 消息: 客户端和远程代理之间的一次通信回合,具有 role (“用户”或“代理”)并包含一个或多个 Parts
  • 任务: A2A 管理的基本工作单元,由唯一 ID 标识。任务是有状态的,并经过定义的生命周期。
  • 部分: 消息或工件中内容的最小单位(例如,TextPartFilePartDataPart)。
  • 工件: 代理作为任务结果生成的一个输出(例如,文档、图像、结构化数据),由 Parts 组成。
  • 流式传输: 通过协议特定流式传输机制提供的任务实时增量更新(状态更改、工件块)。
  • 推送通知: 通过服务器发起的 HTTP POST 请求发送到客户端提供的 webhook URL 的异步任务更新,用于长时间运行或断开连接的场景。
  • 上下文: 一个可选的、服务器生成的标识符,用于逻辑上将相关任务和消息分组。
  • 扩展: 代理提供超出核心 A2A 规范的附加功能或数据的机制。

3. A2A 协议操作

本节以独立于绑定的方式描述 A2A 协议的核心操作。这些操作定义了所有 A2A 实现必须支持的基本能力,无论底层绑定机制如何。

3.1. 核心操作

以下操作定义了所有 A2A 实现必须支持的基本能力,无论使用何种特定协议绑定。有关这些操作与协议特定方法名称和端点的快速参考映射,请参阅第 5.3 节(方法映射参考)。有关详细的协议特定实现细节,请参阅

3.1.1. 发送消息

用于启动代理交互的主要操作。客户端向代理发送消息,并收到跟踪处理的任务或直接响应消息。

输入

输出

  • Task:表示消息处理的任务对象,或者
  • Message:直接响应消息(用于不需要任务跟踪的简单交互)

错误

行为

代理可以创建一个新的 Task 来异步处理提供的消息,或者可以为简单交互返回直接 Message 响应。操作必须立即返回任务信息或响应消息。当返回 Task 时,任务处理可以异步继续。

3.1.2. 发送流式消息

类似于发送消息,但在处理过程中实时流式传输更新。

输入

输出

错误

行为

操作必须建立流式连接以进行实时更新。流必须遵循以下模式之一

  1. 仅消息流: 如果代理返回 Message,则流必须包含一个 Message 对象,然后立即关闭。不提供任务跟踪或更新。

  2. 任务生命周期流: 如果代理返回 Task,则流必须以 Task 对象开始,后跟零个或多个 TaskStatusUpdateEventTaskArtifactUpdateEvent 对象。当任务达到终止状态(例如,已完成、失败、已取消、已拒绝)时,流必须关闭。

代理可以返回 Task 用于复杂处理(带状态/工件更新),也可以返回 Message 用于直接流式响应,而无需任务开销。实现必须提供关于进度和中间结果的即时反馈。

3.1.3. 获取任务

检索先前启动任务的当前状态(包括状态、工件,以及可选的历史记录)。这通常用于轮询通过 message/send 启动的任务状态,或在通过推送通知或流结束后获取任务的最终状态。

输入

表示对 tasks/get 方法的请求。

字段 类型 必填 描述
tenant 字符串 可选租户,作为路径参数提供。
name 字符串 任务的资源名称。格式:tasks/{task_id}
historyLength 整数 可选 历史记录中包含的最大消息数。

有关 historyLength 的详细信息,请参阅历史长度语义

输出

  • Task:请求任务的当前状态和工件

错误

3.1.4. 列出任务

检索任务列表,并具有可选的筛选和分页功能。此方法允许客户端发现和管理跨不同上下文或具有特定状态标准的多个任务。

输入

列出任务的参数,具有可选的筛选条件。

字段 类型 必填 描述
tenant 字符串 可选租户,作为路径参数提供。
contextId 字符串 按上下文 ID 筛选任务,以获取特定对话或会话中的任务。
status TaskState 按其当前状态筛选任务。
pageSize 整数 可选 要返回的最大任务数。必须介于 1 到 100 之间。如果未指定,默认为 50。
pageToken 字符串 用于分页的令牌。使用来自上一个 ListTasksResponse 的 next_page_token。
historyLength 整数 可选 每个任务历史记录中包含的最大消息数。
statusTimestampAfter 时间戳 筛选在 ISO 8601 格式(例如,“2023-10-27T10:00:00Z”)提供的此时间戳之后更新状态的任务。只有状态时间戳大于或等于此值的任务才会被返回。
includeArtifacts 布尔值 可选 是否在返回的任务中包含工件。默认为 false 以减少有效载荷大小。

includeArtifacts 为 false(默认值)时,响应中每个 Task 对象的 artifacts 字段必须完全省略。该字段不应以空数组或 null 值存在。当 includeArtifacts 为 true 时,artifacts 字段应包含其实际内容(如果任务没有工件,则可能为空数组)。

输出

任务/列表方法的返回对象,包含任务数组和分页信息。

字段 类型 必填 描述
tasks Task 数组 符合指定条件的任务数组。
nextPageToken 字符串 用于检索下一页的令牌。如果没有更多结果,则为空字符串。
pageSize 整数 请求的页面大小。
totalSize 整数 可用任务总数(分页前)。

关于 nextPageToken 的注意事项:nextPageToken 字段必须始终存在于响应中。当没有更多结果可检索时(即,这是最后一页),该字段必须设置为空字符串 ("")。客户端应检查空字符串以确定是否有更多页面可用。

错误

除了标准协议错误之外,没有特定于此操作的错误。

行为

操作必须仅返回对已验证客户端可见的任务,并且必须使用基于游标的分页以提高性能和一致性。任务必须按上次更新时间降序排序。实现必须实施适当的授权范围,以确保客户端只能访问授权的任务。有关详细的安全要求,请参阅第 13.1 节 数据访问和授权范围

分页策略

此方法使用基于游标的分页(通过 pageToken/nextPageToken),而不是基于偏移量的分页,以获得更好的性能和一致性,尤其是在大型数据集的情况下。基于游标的分页避免了“深分页问题”,即跳过大量记录对于数据库来说效率低下。此方法与 gRPC 规范一致,gRPC 规范也使用基于游标的分页 (page_token/next_page_token)。

排序

实现必须按状态时间戳降序返回任务(最近更新的任务在前)。这确保了一致的分页,并允许客户端有效监控最近的任务活动。

3.1.5. 取消任务

请求取消正在进行的任务。服务器将尝试取消任务,但成功不保证(例如,任务可能已完成或失败,或者在其当前阶段可能不支持取消)。

输入

表示对 tasks/cancel 方法的请求。

字段 类型 必填 描述
tenant 字符串 可选租户,作为路径参数提供。
name 字符串 要取消的任务的资源名称。格式:tasks/{task_id}

输出

  • 已更新的Task,包含取消状态

错误

行为

操作尝试取消指定任务并返回其更新状态。

3.1.6. 订阅任务

建立流式连接以接收现有任务的更新。

输入

字段 类型 必填 描述
tenant 字符串 可选租户,作为路径参数提供。
name 字符串 要订阅的任务的资源名称。格式:tasks/{task_id}

输出

错误

行为

该操作支持实时监控任务进度,可用于任何未处于终止状态的任务。当任务达到终止状态(completedfailedcancelledrejected)时,流必须终止。

操作必须返回一个 Task 对象作为流中的第一个事件,表示订阅时任务的当前状态。这可以防止在调用 GetTask 和调用 SubscribeToTask 之间潜在的信息丢失。

3.1.7. 设置或更新推送通知配置

为任务创建或更新推送通知配置,以通过 webhook 接收异步更新。

输入

表示对 tasks/pushNotificationConfig/set 方法的请求。

字段 类型 必填 描述
tenant 字符串 可选租户,作为路径参数提供。
parent 字符串 此配置的父任务资源。格式:tasks/{task_id}
configId 字符串 新配置的 ID。
config TaskPushNotificationConfig 要创建的配置。

输出

错误

行为

操作必须建立一个 webhook 终点用于任务更新通知。当任务更新发生时,代理将向配置的 webhook URL 发送 HTTP POST 请求,其中包含 StreamResponse 有效负载(有关详细信息,请参阅推送通知有效负载)。仅当代理支持推送通知功能时,此操作才可用。配置必须持续存在,直到任务完成或显式删除。

3.1.8. 获取推送通知配置

检索任务的现有推送通知配置。

输入

字段 类型 必填 描述
tenant 字符串 可选租户,作为路径参数提供。
name 字符串 要检索的配置的资源名称。格式:tasks/{task_id}/pushNotificationConfigs/{config_id}

输出

错误

行为

操作必须返回配置详细信息,包括 webhook URL 和通知设置。如果配置不存在或客户端缺乏访问权限,操作必须失败。

3.1.9. 列出推送通知配置

检索任务的所有推送通知配置。

输入

字段 类型 必填 描述
tenant 字符串 可选租户,作为路径参数提供。
parent 字符串 父任务资源。格式:tasks/{task_id}
pageSize 整数 要返回的最大配置数。
pageToken 字符串 从上一个 ListTaskPushNotificationConfigRequest 调用接收到的页面令牌。

输出

表示 tasks/pushNotificationConfig/list 方法的成功响应。

字段 类型 必填 描述
configs TaskPushNotificationConfig 数组 推送通知配置列表。
nextPageToken 字符串 一个令牌,可以作为 page_token 发送以检索下一页。如果此字段省略,则没有后续页面。

错误

行为

操作必须返回指定任务的所有活动推送通知配置,并且可以支持具有多个配置的任务的分页。

3.1.10. 删除推送通知配置

删除任务的推送通知配置。

输入

表示对 tasks/pushNotificationConfig/delete 方法的请求。

字段 类型 必填 描述
tenant 字符串 可选租户,作为路径参数提供。
name 字符串 要删除的配置的资源名称。格式:tasks/{task_id}/pushNotificationConfigs/{config_id}

输出

  • 删除确认(具体实现)

错误

行为

操作必须永久删除指定的推送通知配置。删除后,将不再向配置的 webhook 发送通知。此操作必须是幂等的——多次删除同一配置具有相同的效果。

3.1.11. 获取扩展代理卡

客户端身份验证后,检索代理卡可能更详细的版本。此端点仅在 AgentCard.capabilities.extendedAgentCardtrue 时可用。

输入

字段 类型 必填 描述
tenant 字符串 可选租户,作为路径参数提供。

输出

  • AgentCard:一个完整的代理卡对象,其中可能包含公共卡中不存在的其他详细信息或技能

错误

行为

  • 身份验证:客户端必须使用公共 AgentCard.securitySchemesAgentCard.security 字段中声明的一种方案来验证请求。
  • 扩展信息:操作可以根据客户端身份验证级别返回不同的详细信息,包括公共代理卡中未提供的附加技能、功能或配置。
  • 卡片替换:客户端检索此扩展卡后,应在其已验证会话期间或直到卡片版本更改时,将其缓存的公共代理卡替换为此端点收到的内容。
  • 可用性:此操作仅在公共代理卡声明 capabilities.extendedAgentCard: true 时可用。

有关扩展代理卡的安全指南,请参阅第 13.3 节 扩展代理卡访问控制

3.2. 操作参数对象

本节定义了跨多个操作使用的通用参数对象。

3.2.1. SendMessageRequest

表示对 message/send 方法的请求。

字段 类型 必填 描述
tenant 字符串 可选租户,作为路径参数提供。
message Message 要发送给代理的消息。
configuration SendMessageConfiguration 发送请求的配置。
metadata 对象 用于传递额外上下文或参数的灵活键值映射。

3.2.2. SendMessageConfiguration

发送消息请求的配置。

字段 类型 必填 描述
acceptedOutputModes string 数组 客户端准备接受的响应部分的媒体类型列表。代理应使用此功能来定制其输出。
pushNotificationConfig PushNotificationConfig 代理发送任务更新推送通知的配置。
historyLength 整数 可选 历史记录中包含的最大消息数。
blocking 布尔值 如果为 true,则操作会等待任务达到终止状态才返回。默认为 false。

阻塞与非阻塞执行

SendMessageConfiguration 中的 blocking 字段控制操作是否等待任务完成

  • 阻塞(blocking: true:操作必须等待任务达到终止状态(completedfailedcancelledrejected)才能返回。响应必须包含最终任务状态以及所有工件和状态信息。

  • 非阻塞(blocking: false:操作必须在创建任务后立即返回,即使处理仍在进行中。返回的任务将处于进行中状态(例如,workinginput_required)。调用方有责任使用 获取任务 轮询更新,通过 订阅任务 订阅,或通过推送通知接收更新。

blocking 字段无效

  • 当操作返回直接的Message响应而不是任务时。
  • 对于流式操作,它们总是实时返回更新。
  • 对配置的推送通知配置无效,它独立于阻塞模式运行。

3.2.3. 流式响应

流式操作中用于封装不同类型响应数据的包装对象。

字段 类型 必填 描述
task Task 包含任务当前状态的任务对象。
message Message 一个 Message 对象,包含来自代理的消息。
statusUpdate TaskStatusUpdateEvent 表示任务状态更新的事件。
artifactUpdate TaskArtifactUpdateEvent 表示任务工件更新的事件。

注意: StreamResponse 必须包含以下之一:taskmessagestatusUpdateartifactUpdate

此包装器允许流式终点通过单个响应流返回不同类型的更新,同时保持类型安全。

3.2.4. 历史长度语义

historyLength 参数出现在多个操作中,并控制响应中返回的任务历史记录量。此参数在所有操作中遵循一致的语义

  • 未设置/未定义:不施加限制;服务器返回其默认的历史记录量(实现定义,可能是所有历史记录)
  • 0:不应返回历史记录;history 字段应省略
  • > 0:从任务历史记录中返回最多此数量的最近消息

3.2.5. 元数据

用于通过操作传递额外上下文或参数的灵活键值映射。元数据键是字符串,值可以是 JSON 中可表示的任何有效值。Extensions 可用于为特定用例强类型化元数据值。

3.2.6 服务参数

一个键值映射,用于传递具有不区分大小写字符串键和区分大小写字符串值的水平适用上下文或参数。这些服务参数键值对的传输机制由特定的协议绑定定义(例如,HTTP 绑定的 HTTP 头,gRPC 绑定的 gRPC 元数据)。自定义协议绑定必须在其绑定规范中指定服务参数的传输方式。

标准 A2A 服务参数

名称 描述 示例值
A2A-Extensions 客户端希望用于请求的扩展 URI 列表,以逗号分隔 https://example.com/extensions/geolocation/v1,https://standards.org/extensions/citations/v1
A2A-Version 客户端正在使用的 A2A 协议版本。如果不支持该版本,代理将返回 VersionNotSupportedError 0.3

由于服务参数名称可能需要与底层传输协议或基础设施定义的其他参数共存,因此本规范定义的所有服务参数都将以 a2a- 为前缀。

3.3. 操作语义

3.3.1. 幂等性

  • 获取操作(获取任务、列出任务、获取扩展代理卡)天然是幂等的
  • 发送消息操作可以是幂等的。代理可以利用 messageId 来检测重复消息。
  • 取消任务操作是幂等的——多次取消请求具有相同的效果。如果任务已被取消并清除,重复的取消请求可能会返回 TaskNotFoundError

3.3.2. 错误处理

所有操作都可能返回以下类别的错误。服务器必须返回适当的错误,并提供可操作的信息以帮助客户端解决问题。

错误类别和服务器要求

  • 身份验证错误:凭据无效或缺失

    • 服务器必须拒绝凭据无效或缺失的请求
    • 服务器在错误响应中包含身份验证质询信息
    • 服务器指定所需的身份验证方案
    • 错误代码示例:HTTP 401 Unauthorized,gRPC UNAUTHENTICATED,JSON-RPC 自定义错误
    • 场景示例:缺少承载令牌、API 密钥过期、OAuth 令牌无效
  • 授权错误:对请求操作的权限不足

    • 当已验证的客户端缺少所需权限时,服务器必须返回授权错误
    • 服务器指示缺少哪些权限或范围(不泄露有关客户端无法访问的资源的敏感信息)
    • 服务器不得泄露客户端未授权访问的资源的存在
    • 错误代码示例:HTTP 403 Forbidden,gRPC PERMISSION_DENIED,JSON-RPC 自定义错误
    • 场景示例:尝试访问由其他用户创建的任务,OAuth 范围不足
  • 验证错误:输入参数或消息格式无效

    • 服务器必须在处理前验证所有输入参数
    • 服务器指定哪些参数验证失败以及原因
    • 服务器提供有关有效参数值或格式的指导
    • 错误代码示例:HTTP 400 Bad Request,gRPC INVALID_ARGUMENT,JSON-RPC -32602 Invalid params
    • 场景示例:任务 ID 格式无效,缺少必需的消息部分,不支持的内容类型
  • 资源错误:请求的任务未找到或不可访问

    • 当请求的资源不存在或已验证的客户端无法访问时,服务器必须返回未找到错误
    • 服务器不应区分“不存在”和“未授权”以防止信息泄露
    • 错误代码示例:HTTP 404 Not Found,gRPC NOT_FOUND,JSON-RPC 自定义错误(参见 A2A 特定错误)
    • 场景示例:任务 ID 不存在,任务已删除,配置未找到
  • 系统错误:内部代理故障或暂时不可用

    • 服务器为临时故障与永久错误返回适当的错误代码
    • 服务器可以包含重试指导(例如,HTTP 中的 Retry-After 头部)
    • 服务器记录系统错误以用于诊断目的
    • 错误代码示例:HTTP 500 Internal Server Error503 Service Unavailable,gRPC INTERNALUNAVAILABLE,JSON-RPC -32603 Internal error
    • 场景示例:数据库连接失败,下游服务超时,超出速率限制

错误负载结构

A2A 协议中的所有错误响应,无论绑定如何,必须传达以下信息

  1. 错误代码:错误类型的机器可读标识符(例如,字符串代码、数字代码或协议特定状态)
  2. 错误消息:错误的易读描述
  3. 错误详情(可选):有关错误的附加结构化信息,例如
    • 受影响的字段或参数
    • 上下文信息(例如,任务 ID、时间戳)
    • 解决建议

协议绑定必须将这些元素映射到其本机错误表示,同时保留语义含义。有关具体的错误格式示例,请参阅绑定特定章节:JSON-RPC 错误处理gRPC 错误处理HTTP/REST 错误处理

A2A 特定错误

错误名称 描述
TaskNotFoundError 指定的任务 ID 与现有或可访问的任务不对应。它可能无效、已过期或已完成并被清除。
TaskNotCancelableError 尝试取消一个不可取消的任务(例如,它已达到终止状态,如 completedfailedcanceled)。
PushNotificationNotSupportedError 客户端尝试使用推送通知功能,但服务器代理不支持(即,AgentCard.capabilities.pushNotificationsfalse)。
UnsupportedOperationError 此服务器代理实现不支持请求的操作或其特定方面。
ContentTypeNotSupportedError 请求消息部分中提供或工件隐含的媒体类型不受代理或正在调用的特定技能支持。
InvalidAgentResponseError 代理返回的响应不符合当前方法的规范。
ExtendedAgentCardNotConfiguredError 当请求操作需要扩展代理卡时,代理未配置扩展代理卡。
ExtensionSupportRequiredError 客户端请求使用在代理卡中标记为 required: true 的扩展,但客户端未在请求中声明支持它。
VersionNotSupportedError 代理不支持请求中指定的 A2A 协议版本(通过 A2A-Version 服务参数)。

3.3.3. 异步处理

A2A 操作旨在进行异步任务执行。操作会立即返回 Task 对象或 Message 对象,当返回 Task 时,处理会在后台继续进行。客户端通过轮询、流式传输或推送通知来检索任务更新(请参阅第 3.5 节)。代理可以接受处于非终止状态的任务的额外消息,以实现多轮交互(请参阅第 3.4 节)。

3.3.4. 能力验证

代理在其AgentCard中声明可选功能。当客户端尝试使用需要代理卡中未声明为支持的功能或特性时,代理必须返回适当的错误响应

  • 推送通知:如果 AgentCard.capabilities.pushNotificationsfalse 或不存在,则与推送通知配置相关的操作(设置、获取、列出、删除)必须返回 PushNotificationNotSupportedError
  • 流式传输:如果 AgentCard.capabilities.streamingfalse 或不存在,则尝试使用 SendStreamingMessageSubscribeToTask 操作必须返回 UnsupportedOperationError
  • 扩展代理卡:如果 AgentCard.capabilities.extendedAgentCardfalse 或不存在,则尝试调用获取扩展代理卡操作必须返回 UnsupportedOperationError。如果代理声明支持但未配置扩展卡,则必须返回 ExtendedAgentCardNotConfiguredError
  • 扩展:当客户端请求使用在代理卡中标记为 required: true 的扩展,但客户端未声明支持它时,代理必须返回 ExtensionSupportRequiredError

客户端在尝试需要可选功能的操作之前,通过检查代理卡来验证功能支持。

3.4. 多轮交互

A2A 协议通过上下文标识符和任务引用支持多轮对话,使代理能够在多个交互中保持对话连续性。

3.4.1. 上下文标识符语义

contextId 是一个标识符,用于逻辑上将多个相关的 TaskMessage 对象分组,提供一系列交互中的连续性。

生成和分配

  • 当处理不包含 contextId 字段的 Message 时,代理必须生成新的 contextId
  • 生成的 contextId 必须包含在响应中(TaskMessage
  • 如果验证通过(即,它不与提供的 taskId 冲突),代理必须接受并保留客户端提供的 contextId
  • contextId被客户端视为不透明标识符

分组和范围

  • contextId 逻辑上将属于同一对话上下文的多个 Task 对象和 Message 对象分组
  • 所有具有相同 contextId 的任务和消息被视为同一对话会话的一部分
  • 代理可以使用 contextId 在多个交互中维护内部状态、对话历史或 LLM 上下文
  • 代理可以实施上下文过期或清理策略,并记录任何此类策略

3.4.2. 多轮对话模式

A2A 协议支持多种多轮交互模式

上下文连续性

  • Task 对象通过 contextId 字段维护对话上下文
  • 客户端可以在后续消息中包含 contextId 以指示先前交互的继续
  • 客户端可以使用 taskId(带或不带 contextId)来继续或完善特定任务
  • 客户端可以在没有 taskId 的情况下使用 contextId 在现有对话上下文中启动新任务
  • 如果只提供了 taskId,代理必须从任务中推断 contextId
  • 代理必须拒绝包含不匹配 contextIdtaskId 的消息(即,提供的 contextId 与引用的 TaskcontextId 不同)。

需要输入状态

  • 代理可以通过将任务转换为 input-required 状态来请求处理过程中的额外输入
  • 客户端通过发送具有相同 taskIdcontextId 的新消息来继续交互

后续消息

  • 客户端可以发送带有 taskId 引用的额外消息以继续或完善现有任务
  • 客户端使用 Message 中的 referenceTaskIds 字段明确引用相关任务
  • 代理使用引用的任务来理解后续请求的上下文和意图

上下文继承

  • 在相同 contextId 内创建的新任务可以从先前的交互中继承上下文
  • 代理利用共享的 contextId 提供上下文相关的响应

3.5. 任务更新交付机制

A2A 协议提供了三种互补机制,供客户端接收任务进度和完成情况的更新。

3.5.1. 更新机制概述

轮询(获取任务)

  • 客户端定期调用获取任务(第 3.1.3 节)以检查任务状态
  • 易于实现,适用于所有协议绑定
  • 延迟较高,可能产生不必要的请求
  • 最适合:简单集成、不频繁更新、位于严格防火墙后的客户端

流式传输

  • 事件发生时实时交付
  • 操作:流式消息(第 3.1.2 节)和订阅任务(第 3.1.6 节
  • 低延迟,适用于频繁更新
  • 需要持久连接支持
  • 最适合:交互式应用程序、实时仪表板、实时进度监控
  • 需要 AgentCard.capabilities.streamingtrue

推送通知(WebHooks)

  • 当任务状态更改时,代理向客户端注册的端点发送 HTTP POST 请求
  • 客户端不保持持久连接
  • 异步交付,客户端必须可通过 HTTP 访问
  • 最适合:服务器到服务器集成、长时间运行的任务、事件驱动架构
  • 操作:设置(第 3.1.7 节)、获取(第 3.1.8 节)、列出(第 3.1.9 节)、删除(第 3.1.10 节
  • 事件类型:TaskStatusUpdateEvent(第 4.2.1 节)、TaskArtifactUpdateEvent(第 4.2.2 节)、WebHook 有效负载(第 4.3 节
  • 需要 AgentCard.capabilities.pushNotificationstrue
  • 无论代理使用何种协议绑定,WebHook 调用都使用纯 HTTP 和 HTTP 协议绑定中定义的 JSON 有效负载

3.5.2. 流式事件交付

事件排序

所有实现都必须按照事件生成的顺序交付事件。事件在传输过程中不得重新排序,无论协议绑定如何。

每个任务多个流

代理可以为一个或多个客户端服务同一任务的多个并发流。这允许多个客户端(或具有多个连接的同一客户端)独立订阅和接收有关任务进度的更新。

当任务有多个活动流时

  • 事件必须广播到该任务的所有活动流
  • 每个流必须以相同的顺序接收相同的事件
  • 关闭一个流不得影响同一任务的其他活动流
  • 任务生命周期独立于任何单个流的生命周期

此功能支持以下场景

  • 多个团队成员监控同一个长时间运行的任务
  • 客户端在网络中断后通过打开新流重新连接到任务
  • 不同的应用程序或仪表板显示同一任务的实时更新

3.5.3. 推送通知交付

推送通知通过 HTTP POST 发送到客户端注册的 webhook 端点。交付语义和可靠性保证在第 4.3 节中定义。

3.6 版本控制

正在使用的 A2A 协议的特定版本使用相应 A2A 规范版本的 Major.Minor 元素(例如 1.0)标识。规范使用的补丁版本号不影响协议兼容性。补丁版本号不应在请求、响应和代理卡中使用,并且在客户端和服务器协商协议版本时不得考虑。

3.6.1 客户端职责

建议客户端在每次请求中发送 A2A-Version 头,以在代理升级到新版本协议后保持兼容性。发送 A2A-Version 头还可以向代理提供有关生态系统中版本使用情况的可见性,这有助于告知就地版本升级的风险。

带版本头的 HTTP GET 请求示例

GET /tasks/task-123 HTTP/1.1
Host: agent.example.com
A2A-Version: 1.0
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Accept: application/json

3.6.2 服务器职责

代理必须使用所请求 A2A-Version(匹配 Major.Minor)的语义处理请求。如果不支持该版本,代理必须返回 VersionNotSupportedError

代理应在其代理卡的 protocolVersions 字段中声明其支持的协议版本

  • 对于稳定版本(1.x 及以上): 主要版本内的向后兼容性是必需的。支持版本 1.2 的代理也必须支持 1.01.1。每个主要版本只需列出最新支持的次要版本。
  • 对于旧版实验版本(0.x): 这些早期版本在次要版本之间引入了破坏性变更。仍然支持任何 0.x 版本的代理必须明确列出其支持的每个版本。

带支持协议版本的代理卡示例

{
  "agentId": "agent-123",
  "name": "Example Agent",
  "protocolVersions": ["0.3", "1.1"]
}

以上示例表明代理支持 A2A 协议版本 0.31.01.1

3.6.3 客户端回退

接收到 VersionNotSupportedError 的客户端可以选择使用早期支持的版本重试请求,或者使请求失败。这种明确的故障处理有助于防止因代理处理包含它无法识别的协议特性或字段的请求而可能发生的意外行为。

3.6.4 工具支持

实现 A2A 协议的工具库和 SDK 应提供机制来帮助客户端管理协议版本控制,例如提供配置选项以在遇到 VersionNotSupportedError 时启用自动回退到早期版本。需要协议最新功能的客户端代理不应启用自动回退,以避免无声地丢失功能。

4. 协议数据模型

A2A 协议使用 Protocol Buffers 定义了规范数据模型。所有协议绑定必须提供这些数据结构的功能等效表示。

4.1. 核心对象

4.1.1. 任务

任务是 A2A 的核心行动单元。它具有当前状态,当为任务创建结果时,它们存储在工件中。如果任务有多个回合,这些回合存储在历史记录中。

字段 类型 必填 描述
id 字符串 任务的唯一标识符(例如 UUID),由服务器为新任务生成。
contextId 字符串 交互(任务和消息)上下文集合的唯一标识符(例如 UUID)。由 A2A 服务器创建。
status TaskStatus 任务的当前状态,包括状态和消息。
artifacts Artifact 数组 任务的一组输出工件。
history Message 数组 任务的交互历史记录。
metadata 对象 用于存储任务自定义元数据的键/值对象。

4.1.2. 任务状态

任务状态的容器

字段 类型 必填 描述
state TaskState 此任务的当前状态。
message Message 与状态关联的消息。
时间戳 时间戳 状态记录时的 ISO 8601 时间戳。示例:“2023-10-27T10:00:00Z”

4.1.3. 任务状态枚举

定义任务可能的生命周期状态。

描述
TASK_STATE_UNSPECIFIED 任务处于未知或不确定状态。
TASK_STATE_SUBMITTED 表示任务已创建的确认状态。
TASK_STATE_WORKING 表示任务正在积极处理中的状态。
TASK_STATE_COMPLETED 表示任务已完成的状态。这是一个终止状态。
TASK_STATE_FAILED 表示任务已完成但失败的状态。这是一个终止状态。
TASK_STATE_CANCELLED 表示任务在完成前被取消的状态。这是一个终止状态。
TASK_STATE_INPUT_REQUIRED 表示任务需要信息才能完成的状态。这是一个中断状态。
TASK_STATE_REJECTED 表示代理已决定不执行任务的状态。这可以在任务初始创建期间完成,或者在代理确定无法或不会继续进行之后完成。这是一个终止状态。
TASK_STATE_AUTH_REQUIRED 表示需要上游客户端进行身份验证的状态。身份验证预计是带外的,因此这既不是中断状态也不是终止状态。

4.1.4. 消息

消息是客户端和服务器之间的一个通信单元。它可以与上下文和/或任务关联。对于服务器消息,必须提供 context_id,并且只有在创建任务时才提供 task_id。对于客户端消息,这两个字段都是可选的,但需要注意的是,如果两者都提供,它们必须匹配(context_id 必须是任务上设置的那个)。如果只提供了 task_id,服务器将从中推断 context_id。

字段 类型 必填 描述
messageId 字符串 消息的唯一标识符(例如 UUID)。这是必需的,并由消息创建者创建。
contextId 字符串 消息的上下文 ID。这是可选的,如果设置,消息将与给定上下文关联。
taskId 字符串 消息的任务 ID。这是可选的,如果设置,消息将与给定任务关联。
role Role 标识消息的发送者。
parts Part 数组 部分是消息内容的容器。
metadata 对象 与消息一起提供的任何可选元数据。
extensions string 数组 此消息中存在或贡献的扩展 URI。
referenceTaskIds string 数组 此消息引用以获取额外上下文的任务 ID 列表。

4.1.5. 角色

定义 A2A 协议通信中消息的发送者。

描述
ROLE_UNSPECIFIED
ROLE_USER USER 角色指从客户端到服务器的通信。
ROLE_AGENT AGENT 角色指从服务器到客户端的通信。

4.1.6. 部分

部分表示通信内容的一个部分的容器。部分可以是纯文本、某种文件(图像、视频等)或结构化数据 Blob(即 JSON)。

字段 类型 必填 描述
text 字符串 文本部分的字符串内容。
file FilePart 文件内容,表示为 URI 或 base64 编码的字节。
data DataPart 结构化数据内容。
metadata 对象 与此部分关联的可选元数据。

注意: Part 必须包含以下之一:textfiledata

4.1.7. 文件部分

FilePart 表示提供文件的不同方式。如果文件很小,可以通过 file_with_bytes 直接馈送字节。如果文件很大,代理应直接从 file_with_uri 源读取内容。

字段 类型 必填 描述
fileWithUri 字符串 指向文件内容的 URL。
fileWithBytes bytes 文件的 base64 编码内容。
mediaType 字符串 文件的媒体类型(例如,“application/pdf”)。
name 字符串 文件的可选名称(例如,“document.pdf”)。

注意: FilePart 必须包含以下之一:fileWithUrifileWithBytes

4.1.8. 数据部分

DataPart 表示结构化 Blob。

字段 类型 必填 描述
data 对象 包含任意数据的 JSON 对象。

4.1.9. 工件

工件表示任务输出。

字段 类型 必填 描述
artifactId 字符串 工件的唯一标识符(例如 UUID)。它必须至少在一个任务内是唯一的。
name 字符串 工件的人类可读名称。
description 字符串 工件的人类可读描述,可选。
parts Part 数组 工件的内容。必须至少包含一个部分。
metadata 对象 工件中包含的可选元数据。
extensions string 数组 此工件中存在或贡献的扩展 URI。

4.2. 流式事件

4.2.1. TaskStatusUpdateEvent

代理发送的事件,用于通知客户端任务状态的更改。

字段 类型 必填 描述
taskId 字符串 已更改的任务 ID
contextId 字符串 任务所属上下文的 ID
status TaskStatus 任务的新状态。
最终 布尔值 如果为 true,则这是此交互流中的最终事件。
metadata 对象 与任务更新关联的可选元数据。

4.2.2. TaskArtifactUpdateEvent

TaskArtifactUpdateEvent 表示已生成工件的任务增量。

字段 类型 必填 描述
taskId 字符串 此工件的任务 ID。
contextId 字符串 此任务所属上下文的 ID。
工件 工件 已生成或更新的工件。
追加 布尔值 如果为 true,此工件的内容应追加到先前发送的具有相同 ID 的工件中。
lastChunk 布尔值 如果为 true,则这是工件的最后一个块。
metadata 对象 与工件更新关联的可选元数据。

4.3. 推送通知对象

4.3.1. PushNotificationConfig

用于设置任务更新推送通知的配置。

字段 类型 必填 描述
id 字符串 此推送通知的唯一标识符(例如 UUID)。
url 字符串 发送通知的 URL
token 字符串 此任务/会话的唯一令牌
authentication AuthenticationInfo 有关随通知发送的身份验证信息

4.3.2. AuthenticationInfo

定义身份验证详细信息,用于推送通知。

字段 类型 必填 描述
schemes string 数组 支持的身份验证方案列表(例如,“Basic”、“Bearer”)。
credentials 字符串 可选凭据

4.3.3. 推送通知负载

当发生任务更新时,代理会向配置的 webhook URL 发送 HTTP POST 请求。负载使用与流式操作相同的 StreamResponse 格式,允许推送通知传递与实时流相同的事件类型。

请求格式

POST {webhook_url}
Authorization: {authentication_scheme} {credentials}
Content-Type: application/json

{
  /* StreamResponse object - one of: */
  "task": { /* Task object */ },
  "message": { /* Message object */ },
  "statusUpdate": { /* TaskStatusUpdateEvent object */ },
  "artifactUpdate": { /* TaskArtifactUpdateEvent object */ }
}

负载结构

webhook 负载是一个 StreamResponse 对象,其中包含以下之一

身份验证

代理必须在请求头中包含 PushNotificationConfig.authentication 字段中指定的身份验证凭据。格式遵循标准 HTTP 身份验证模式(Bearer 令牌、基本身份验证等)。

客户端职责

  • 客户端必须以 HTTP 2xx 状态码响应以确认成功接收
  • 客户端应该幂等地处理通知,因为可能会发生重复交付
  • 客户端必须验证任务 ID 是否与预期任务匹配
  • 客户端应该实施适当的安全措施来验证通知来源

服务器保证

  • 代理必须至少尝试为每个配置的 webhook 交付一次
  • 代理可以为失败的交付实施具有指数退避的重试逻辑
  • 代理应该为 webhook 请求设置合理的超时(建议:10-30 秒)
  • 代理可以在连续失败达到配置次数后停止尝试交付

有关推送通知的详细安全指南,请参阅第 13.2 节 推送通知安全

4.4. 代理发现对象

4.4.1. AgentCard

AgentCard 是代理的自描述清单。它提供基本的元数据,包括代理的身份、功能、技能、支持的通信方法和安全要求。

字段 类型 必填 描述
protocolVersions string 数组 此代理支持的 A2A 协议版本。对于稳定版本 (1.x+),每个主要版本仅列出最新的支持次要版本。对于旧版实验版本 (0.x),明确列出每个支持版本。默认值:["1.0"]
name 字符串 代理的人类可读名称。示例:“食谱代理”
description 字符串 代理的人类可读描述,帮助用户和其他代理了解其用途。示例:“帮助用户制作食谱和烹饪的代理。”
supportedInterfaces AgentInterface 数组 支持的接口的有序列表。第一个条目是首选。
provider AgentProvider 代理的服务提供商。
version 字符串 代理的版本。示例:“1.0.0”
documentationUrl 字符串 可选 提供有关代理的附加文档的 URL。
capabilities AgentCapabilities 代理支持的 A2A 功能集。
securitySchemes SecurityScheme 映射 用于与此代理进行身份验证的安全方案详细信息。
security Security 数组 联系代理的安全要求。
defaultInputModes string 数组 代理在所有技能中支持的交互模式集。这可以在每个技能中被覆盖。定义为媒体类型。
defaultOutputModes string 数组 此代理作为输出支持的媒体类型。
skills AgentSkill 数组 技能代表代理的能力。它主要是一个描述性概念,但代表代理可能成功的更集中的行为集。
signatures AgentCardSignature 数组 为此 AgentCard 计算的 JSON Web 签名。
iconUrl 字符串 可选 代理图标的可选 URL。

4.4.2. AgentProvider

表示代理的服务提供商。

字段 类型 必填 描述
url 字符串 代理提供商网站或相关文档的 URL。示例:“https://ai.google.dev”
organization 字符串 代理提供商组织的名称。示例:“Google”

4.4.3. AgentCapabilities

定义代理支持的可选功能。

字段 类型 必填 描述
streaming 布尔值 可选 指示代理是否支持流式响应。
pushNotifications 布尔值 可选 指示代理是否支持发送推送通知以进行异步任务更新。
extensions AgentExtension 数组 代理支持的协议扩展列表。
stateTransitionHistory 布尔值 可选 指示代理是否提供任务状态转换历史记录。
extendedAgentCard 布尔值 可选 指示代理在进行身份验证时是否支持提供扩展代理卡。

4.4.4. AgentExtension

代理支持的协议扩展声明。

字段 类型 必填 描述
uri 字符串 识别扩展的唯一 URI。
description 字符串 此代理如何使用扩展的人类可读描述。
required 布尔值 如果为 true,客户端必须理解并遵守扩展的要求。
params 对象 可选的、特定于扩展的配置参数。

4.4.5. AgentSkill

表示代理可以执行的独特能力或功能。

字段 类型 必填 描述
id 字符串 代理技能的唯一标识符。
name 字符串 技能的人类可读名称。
description 字符串 技能的详细描述。
tags string 数组 描述技能能力的关键词集。
examples string 数组 此技能可以处理的示例提示或场景。
inputModes string 数组 此技能支持的输入媒体类型集,覆盖代理的默认值。
outputModes string 数组 此技能支持的输出媒体类型集,覆盖代理的默认值。
security Security 数组 此技能所需的安全方案。

4.4.6. AgentInterface

声明用于与代理交互的目标 URL 和传输协议的组合。这允许代理通过多种协议绑定机制公开相同的功能。

字段 类型 必填 描述
url 字符串 此接口可用的 URL。在生产环境中必须是有效的绝对 HTTPS URL。示例:“https://api.example.com/a2a/v1”、“https://grpc.example.com/a2a”
protocolBinding 字符串 此 URL 支持的协议绑定。这是一个开放形式的字符串,以便于扩展其他协议绑定。官方支持的核心绑定是 JSONRPCGRPCHTTP+JSON
tenant 字符串 调用代理时要在请求中设置的租户。

4.4.7. AgentCardSignature

AgentCardSignature 表示 AgentCard 的 JWS 签名。这遵循 RFC 7515 JSON Web Signature (JWS) 的 JSON 格式。

字段 类型 必填 描述
protected 字符串 签名的受保护 JWS 标头。这始终是 base64url 编码的 JSON 对象。必需。
signature 字符串 计算出的签名,base64url 编码。必需。
header 对象 未受保护的 JWS 标头值。

4.5. 安全对象

4.5.1. SecurityScheme

定义可用于保护代理端点的安全方案。这是一个基于 OpenAPI 3.2 Security Scheme Object 的可辨识联合类型。请参阅:https://spec.openapis.org.cn/oas/v3.2.0.html#security-scheme-object

字段 类型 必填 描述
apiKeySecurityScheme APIKeySecurityScheme 基于 API 密钥的身份验证。
httpAuthSecurityScheme HTTPAuthSecurityScheme HTTP 身份验证(Basic、Bearer 等)。
oauth2SecurityScheme OAuth2SecurityScheme OAuth 2.0 身份验证。
openIdConnectSecurityScheme OpenIdConnectSecurityScheme OpenID Connect 身份验证。
mtlsSecurityScheme MutualTlsSecurityScheme 相互 TLS 身份验证。

注意:SecurityScheme 必须只包含以下之一:apiKeySecuritySchemehttpAuthSecuritySchemeoauth2SecuritySchemeopenIdConnectSecuritySchememtlsSecurityScheme

4.5.2. APIKeySecurityScheme

定义使用 API 密钥的安全方案。

字段 类型 必填 描述
description 字符串 安全方案的可选描述。
location 字符串 API 密钥的位置。有效值为“query”、“header”或“cookie”。
name 字符串 要使用的标头、查询或 cookie 参数的名称。

4.5.3. HTTPAuthSecurityScheme

定义使用 HTTP 身份验证的安全方案。

字段 类型 必填 描述
description 字符串 安全方案的可选描述。
scheme 字符串 在授权标头中使用的 HTTP 身份验证方案名称,如 RFC7235 所定义(例如,“Bearer”)。此值应在 IANA 身份验证方案注册表中注册。
bearerFormat 字符串 向客户端提示如何格式化 bearer 令牌(例如,“JWT”)。这主要用于文档目的。

4.5.4. OAuth2SecurityScheme

定义使用 OAuth 2.0 的安全方案。

字段 类型 必填 描述
description 字符串 安全方案的可选描述。
flows OAuthFlows 包含受支持的 OAuth 2.0 流程的配置信息的对象。
oauth2MetadataUrl 字符串 OAuth2 授权服务器元数据 RFC8414 (https://datatracker.ietf.org/doc/html/rfc8414) 的 URL。需要 TLS。

4.5.5. OpenIdConnectSecurityScheme

定义使用 OpenID Connect 的安全方案。

字段 类型 必填 描述
description 字符串 安全方案的可选描述。
openIdConnectUrl 字符串 OIDC 提供商元数据的 OpenID Connect 发现 URL。请参阅:https://openid.net/specs/openid-connect-discovery-1_0.html

4.5.6. MutualTLSSecurityScheme

错误:在 specification/grpc/a2a.proto 中未找到消息“MutualTlsSecurityScheme”

4.5.7. OAuthFlows

定义受支持的 OAuth 2.0 流程的配置。

字段 类型 必填 描述
authorizationCode AuthorizationCodeOAuthFlow OAuth 授权码流的配置。
clientCredentials ClientCredentialsOAuthFlow OAuth 客户端凭据流的配置。
deviceCode DeviceCodeOAuthFlow OAuth 设备码流的配置。

注意:OAuthFlows 必须只包含以下之一:authorizationCodeclientCredentialsdeviceCode

4.5.8. AuthorizationCodeOAuthFlow

定义 OAuth 2.0 授权码流的配置详细信息。

字段 类型 必填 描述
authorizationUrl 字符串 此流要使用的授权 URL。
tokenUrl 字符串 此流要使用的令牌 URL。
refreshUrl 字符串 用于获取刷新令牌的 URL。
scopes string 映射 OAuth2 安全方案的可用范围。
pkceRequired 布尔值 指示此流是否需要 PKCE (RFC 7636)。PKCE 应始终用于公共客户端,并推荐用于所有客户端。

4.5.9. ClientCredentialsOAuthFlow

定义 OAuth 2.0 客户端凭据流的配置详细信息。

字段 类型 必填 描述
tokenUrl 字符串 此流要使用的令牌 URL。
refreshUrl 字符串 用于获取刷新令牌的 URL。
scopes string 映射 OAuth2 安全方案的可用范围。

4.5.10. DeviceCodeOAuthFlow

定义 OAuth 2.0 设备码流 (RFC 8628) 的配置详细信息。此流专为输入受限设备(如 IoT 设备和 CLI 工具)设计,用户在单独的设备上进行身份验证。

字段 类型 必填 描述
deviceAuthorizationUrl 字符串 设备授权端点 URL。
tokenUrl 字符串 此流要使用的令牌 URL。
refreshUrl 字符串 用于获取刷新令牌的 URL。
scopes string 映射 OAuth2 安全方案的可用范围。

4.6. 扩展

A2A 协议支持扩展,以提供超出核心规范的附加功能或数据,同时保持向后兼容性和互操作性。扩展允许代理声明附加功能(例如协议增强或供应商特定功能),与不支持特定扩展的客户端保持兼容性,通过实验性或领域特定功能实现创新而无需修改核心协议,并通过为社区开发的功能成为核心规范的一部分提供途径来促进标准化。

4.6.1. 扩展声明

代理在 AgentCard 中使用 extensions 字段声明其支持的扩展,该字段包含 AgentExtension 对象的数组。

示例:AgentCard 中声明扩展支持的代理

{
  "protocolVersions": ["0.3"],
  "name": "Research Assistant Agent",
  "description": "AI agent for academic research and fact-checking",
  "supportedInterfaces": [
    {
      "url": "https://research-agent.example.com/a2a/v1",
      "protocolBinding": "HTTP+JSON"
    }
  ],
  "capabilities": {
    "streaming": false,
    "pushNotifications": false,
    "extensions": [
      {
        "uri": "https://standards.org/extensions/citations/v1",
        "description": "Provides citation formatting and source verification",
        "required": false
      },
      {
        "uri": "https://example.com/extensions/geolocation/v1",
        "description": "Location-based search capabilities",
        "required": false
      }
    ]
  },
  "defaultInputModes": ["text/plain"],
  "defaultOutputModes": ["text/plain"],
  "skills": [
    {
      "id": "academic-research",
      "name": "Academic Research Assistant",
      "description": "Provides research assistance with citations and source verification",
      "tags": ["research", "citations", "academic"],
      "examples": ["Find peer-reviewed articles on climate change"],
      "inputModes": ["text/plain"],
      "outputModes": ["text/plain"]
    }
  ]
}

客户端通过绑定特定机制(例如 HTTP 标头、gRPC 元数据或 JSON-RPC 请求参数)指示他们希望在交互期间使用的扩展标识符来表明他们希望使用特定扩展。

示例:使用标头选择扩展的 HTTP 客户端

POST /message:send HTTP/1.1
Host: agent.example.com
Content-Type: application/json
Authorization: Bearer token
A2A-Extensions: https://example.com/extensions/geolocation/v1,https://standards.org/extensions/citations/v1

{
  "message": {
    "role": "user",
    "parts": [{"text": "Find restaurants near me"}],
    "extensions": ["https://example.com/extensions/geolocation/v1"],
    "metadata": {
      "https://example.com/extensions/geolocation/v1": {
        "latitude": 37.7749,
        "longitude": -122.4194
      }
    }
  }
}

4.6.2. 扩展点

扩展可以集成到 A2A 协议的几个定义良好的扩展点

消息扩展

消息可以扩展,以允许客户端提供与正在发送的消息相关的附加强类型上下文或参数,或任务状态消息以包含有关任务进度的额外信息。

示例:使用扩展和元数据数组的位置扩展

{
  "role": "user",
  "parts": [
    {"text": "Find restaurants near me"}
  ],
  "extensions": ["https://example.com/extensions/geolocation/v1"],
  "metadata": {
    "https://example.com/extensions/geolocation/v1": {
      "latitude": 37.7749,
      "longitude": -122.4194,
      "accuracy": 10.0,
      "timestamp": "2025-10-21T14:30:00Z"
    }
  }
}

工件扩展

工件可以包含扩展数据,以提供有关生成内容的强类型上下文或元数据。

示例:具有研究来源引用扩展的工件

{
  "artifactId": "research-summary-001",
  "name": "Climate Change Summary",
  "parts": [
    {
      "text": "Global temperatures have risen by 1.1°C since pre-industrial times, with significant impacts on weather patterns and sea levels."
    }
  ],
  "extensions": ["https://standards.org/extensions/citations/v1"],
  "metadata": {
    "https://standards.org/extensions/citations/v1": {
      "sources": [
        {
          "title": "Global Temperature Anomalies - 2023 Report",
          "authors": ["Smith, J.", "Johnson, M."],
          "url": "https://climate.gov/reports/2023-temperature",
          "accessDate": "2025-10-21",
          "relevantText": "Global temperatures have risen by 1.1°C"
        }
      ]
    }
  }
}

4.6.3. 扩展版本控制和兼容性

扩展应该在其 URI 标识符中包含版本信息。这允许客户端和代理在交互期间协商兼容的扩展版本。对于扩展的破坏性更改,必须创建新的 URI。

如果客户端请求代理不支持的扩展版本,代理应该忽略该交互的扩展并继续执行,除非该扩展在 AgentCard 中标记为 required,在这种情况下,代理必须返回错误指示不支持的扩展。它不能自动回退到以前版本的扩展。

5. 协议绑定要求和互操作性

5.1. 功能等效性要求

当代理支持多种协议时,所有受支持的协议必须

  • 相同功能:提供相同的操作和功能集
  • 一致行为:对相同请求返回语义等效的结果
  • 相同错误处理:使用适当的协议特定代码一致地映射错误
  • 等效身份验证:支持 AgentCard 中声明的相同身份验证方案

5.2. 协议选择和协商

  • 代理声明:代理必须在其 AgentCard 中声明所有受支持的协议
  • 客户端选择:客户端可以选择代理声明的任何协议
  • 无动态协商:A2A 不定义运行时协议协商
  • 回退行为:客户端应该为替代协议实施回退逻辑

5.3. 方法映射参考

功能 JSON-RPC 方法 gRPC 方法 REST 端点
发送消息 SendMessage SendMessage POST /message:send
流消息 SendStreamingMessage SendStreamingMessage POST /message:stream
获取任务 GetTask GetTask GET /tasks/{id}
列出任务 ListTasks ListTasks GET /tasks
取消任务 CancelTask CancelTask POST /tasks/{id}:cancel
订阅任务 SubscribeToTask SubscribeToTask POST /tasks/{id}:subscribe
设置推送通知配置 SetTaskPushNotificationConfig SetTaskPushNotificationConfig POST /tasks/{id}/pushNotificationConfigs
获取推送通知配置 GetTaskPushNotificationConfig GetTaskPushNotificationConfig GET /tasks/{id}/pushNotificationConfigs/{configId}
列出推送通知配置 ListTaskPushNotificationConfig ListTaskPushNotificationConfig GET /tasks/{id}/pushNotificationConfigs
删除推送通知配置 DeleteTaskPushNotificationConfig DeleteTaskPushNotificationConfig DELETE /tasks/{id}/pushNotificationConfigs/{configId}
获取扩展代理卡 GetExtendedAgentCard GetExtendedAgentCard GET /extendedAgentCard

5.4. 错误码映射

第 3.3.2 节中定义的所有 A2A 特定错误必须映射到绑定特定的错误表示。下表提供了每个标准协议绑定的规范映射

A2A 错误类型 JSON-RPC 代码 gRPC 状态 HTTP 状态 HTTP 类型 URI
TaskNotFoundError -32001 NOT_FOUND 404 Not Found https://a2a-protocol.org.cn/errors/task-not-found
TaskNotCancelableError -32002 FAILED_PRECONDITION 409 Conflict https://a2a-protocol.org.cn/errors/task-not-cancelable
PushNotificationNotSupportedError -32003 UNIMPLEMENTED 400 Bad Request https://a2a-protocol.org.cn/errors/push-notification-not-supported
UnsupportedOperationError -32004 UNIMPLEMENTED 400 Bad Request https://a2a-protocol.org.cn/errors/unsupported-operation
ContentTypeNotSupportedError -32005 INVALID_ARGUMENT 415 Unsupported Media Type https://a2a-protocol.org.cn/errors/content-type-not-supported
InvalidAgentResponseError -32006 INTERNAL 502 Bad Gateway https://a2a-protocol.org.cn/errors/invalid-agent-response
ExtendedAgentCardNotConfiguredError -32007 FAILED_PRECONDITION 400 Bad Request https://a2a-protocol.org.cn/errors/extended-agent-card-not-configured
ExtensionSupportRequiredError -32008 FAILED_PRECONDITION 400 Bad Request https://a2a-protocol.org.cn/errors/extension-support-required
VersionNotSupportedError -32009 UNIMPLEMENTED 400 Bad Request https://a2a-protocol.org.cn/errors/version-not-supported

自定义绑定要求

自定义协议绑定必须定义等效的错误码映射,以保留每个 A2A 错误类型的语义含义。绑定规范应该提供类似的映射表,显示每个 A2A 错误类型如何在自定义绑定的本机错误格式中表示。

有关绑定特定的错误结构和示例,请参阅

5.5. JSON 字段命名约定

A2A 协议数据模型的所有 JSON 序列化必须对字段名使用驼峰命名法,而不是 Protocol Buffer 定义中使用的 snake_case 约定。

命名约定

  • Protocol Buffer 字段:protocol_versions → JSON 字段:protocolVersions
  • Protocol Buffer 字段:context_id → JSON 字段:contextId
  • Protocol Buffer 字段:default_input_modes → JSON 字段:defaultInputModes
  • Protocol Buffer 字段:push_notification_config → JSON 字段:pushNotificationConfig

枚举值

  • 枚举值必须在 JSON 中表示为其字符串名称,并在删除任何类型名称前缀后使用小写 kebab-case

示例

  • Protocol Buffer 枚举:TASK_STATE_INPUT_REQUIRED → JSON 值:input-required
  • Protocol Buffer 枚举:ROLE_USER → JSON 值:user

5.6. 数据类型约定

本节记录了 A2A 协议中使用的常见数据类型的约定,特别是它们如何应用于协议绑定。

5.6.1. 时间戳

A2A 协议在 Protocol Buffer 定义中对所有时间戳字段使用 google.protobuf.Timestamp。当序列化为 JSON(在 JSON-RPC、HTTP/REST 或其他基于 JSON 的绑定中)时,这些时间戳必须表示为 UTC 时区中的 ISO 8601 格式字符串。

格式要求

  • 格式:ISO 8601 组合日期和时间表示
  • 时区:UTC(由“Z”后缀表示)
  • 精度:应尽可能使用毫秒精度
  • 模式:YYYY-MM-DDTHH:mm:ss.sssZ

示例

{
  "timestamp": "2025-10-28T10:30:00.000Z",
  "createdAt": "2025-10-28T14:25:33.142Z",
  "lastModified": "2025-10-31T17:45:22.891Z"
}

实施说明

  • Protocol Buffer 的 google.protobuf.Timestamp 将时间表示为自 Unix 纪元(1970 年 1 月 1 日 00:00:00 UTC)以来的秒数加上纳秒
  • 使用标准 Protocol Buffer JSON 编码时,JSON 序列化会自动将其转换为 ISO 8601 格式
  • 客户端和服务器必须正确解析和生成 ISO 8601 时间戳
  • 当无法获得毫秒精度时,小数秒部分可以省略或填充零
  • 时间戳不能包含除“Z”以外的时区偏移量(所有时间均为 UTC)

5.7. 字段存在和可选性

specification/grpc/a2a.proto 中的 Protocol Buffer 定义使用 google.api.field_behavior 注释来指示字段是否为 REQUIRED。这些注释既作为文档也作为实现验证提示。

必填字段

标记为 [(google.api.field_behavior) = REQUIRED] 的字段表示该字段必须存在并设置在有效消息中。实现应该验证这些要求并拒绝缺少必填字段的消息。标记为必需的数组必须至少包含一个元素。

可选字段存在

Protocol Buffer optional 关键字用于区分字段是显式设置还是省略。这种区分对于两种情况至关重要

  1. 显式默认值:规范中的某些字段定义了与 Protocol Buffer 隐式默认值不同的默认值(例如,protocolVersions 默认值为 ["1.0"] 而不是空数组)。当未显式提供字段时,实现应应用默认值。

  2. Agent Card 规范化:当创建 Agent Card 的加密签名时,需要生成规范的 JSON 表示。optional 关键字使实现能够区分显式设置的字段(应包含在规范形式中)和省略的字段(应从规范化中排除)。这确保了 Agent Card 可以重构以准确匹配其签名。

无法识别的字段

实现应该忽略消息中无法识别的字段,以允许协议演进时的向前兼容性。

6. 常见工作流与示例

本节提供了跨不同绑定的常见 A2A 交互的说明性示例。

6.1. 基本任务执行

场景:客户端提出问题并收到已完成的任务响应。

请求

POST /message:send HTTP/1.1
Host: agent.example.com
Content-Type: application/a2a+json
Authorization: Bearer token

{
  "message": {
    "role": "user",
    "parts": [{"text": "What is the weather today?"}],
    "messageId": "msg-uuid"
  }
}

响应

HTTP/1.1 200 OK
Content-Type: application/a2a+json

{
  "task": {
    "id": "task-uuid",
    "contextId": "context-uuid",
    "status": {"state": "completed"},
    "artifacts": [{
      "artifactId": "artifact-uuid",
      "name": "Weather Report",
      "parts": [{"text": "Today will be sunny with a high of 75°F"}]
    }]
  }
}

6.2. 流式任务执行

场景:客户端请求一个长时间运行的任务并进行实时更新。

请求

POST /message:stream HTTP/1.1
Host: agent.example.com
Content-Type: application/a2a+json
Authorization: Bearer token

{
  "message": {
    "role": "user",
    "parts": [{"text": "Write a detailed report on climate change"}],
    "messageId": "msg-uuid"
  }
}

SSE 响应流

HTTP/1.1 200 OK
Content-Type: text/event-stream

data: {"task": {"id": "task-uuid", "status": {"state": "working"}}}

data: {"artifactUpdate": {"taskId": "task-uuid", "artifact": {"parts": [{"text": "# Climate Change Report\n\n"}]}}}

data: {"statusUpdate": {"taskId": "task-uuid", "status": {"state": "completed"}, "final": true}}

6.3. 多轮交互

场景:代理需要额外输入才能完成任务。

初始请求

POST /message:send HTTP/1.1
Host: agent.example.com
Content-Type: application/a2a+json
Authorization: Bearer token

{
  "message": {
    "role": "user",
    "parts": [{"text": "Book me a flight"}],
    "messageId": "msg-1"
  }
}

响应(需要输入)

HTTP/1.1 200 OK
Content-Type: application/a2a+json

{
  "task": {
    "id": "task-uuid",
    "status": {
      "state": "input-required",
      "message": {
        "role": "agent",
        "parts": [{"text": "I need more details. Where would you like to fly from and to?"}]
      }
    }
  }
}

后续请求

POST /message:send HTTP/1.1
Host: agent.example.com
Content-Type: application/a2a+json
Authorization: Bearer token

{
  "message": {
    "taskId": "task-uuid",
    "role": "user",
    "parts": [{"text": "From San Francisco to New York"}],
    "messageId": "msg-2"
  }
}

6.4. 版本协商错误

场景:客户端请求不支持的协议版本。

请求

POST /message:send HTTP/1.1
Host: agent.example.com
Content-Type: application/a2a+json
Authorization: Bearer token
A2A-Version: 0.5

{
  "message": {
    "role": "user",
    "parts": [{"text": "Hello"}],
    "messageId": "msg-uuid"
  }
}

响应

HTTP/1.1 400 Bad Request
Content-Type: application/problem+json

{
  "type": "https://a2a-protocol.org.cn/errors/version-not-supported",
  "title": "Protocol Version Not Supported",
  "status": 400,
  "detail": "The requested A2A protocol version 0.5 is not supported by this agent",
  "supportedVersions": ["0.3"]
}

6.5. 任务列表和管理

场景:客户端希望查看特定上下文中的所有任务或具有特定状态的所有任务。

请求:特定上下文中的所有任务

请求

POST /tasks/list HTTP/1.1
Host: agent.example.com
Content-Type: application/a2a+json
Authorization: Bearer token

{
  "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4",
  "pageSize": 10,
  "historyLength": 3
}

响应

HTTP/1.1 200 OK
Content-Type: application/a2a+json

{
  "tasks": [
    {
      "id": "3f36680c-7f37-4a5f-945e-d78981fafd36",
      "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4",
      "status": {
        "state": "completed",
        "timestamp": "2024-03-15T10:15:00Z"
      }
    }
  ],
  "totalSize": 5,
  "pageSize": 10,
  "nextPageToken": ""
}

请求:所有上下文中的所有工作任务

请求

POST /tasks/list HTTP/1.1
Host: agent.example.com
Content-Type: application/a2a+json
Authorization: Bearer token

{
  "status": "working",
  "pageSize": 20
}

响应

HTTP/1.1 200 OK
Content-Type: application/a2a+json

{
  "tasks": [
    {
      "id": "789abc-def0-1234-5678-9abcdef01234",
      "contextId": "another-context-id",
      "status": {
        "state": "working",
        "message": {
          "role": "agent",
          "parts": [
            {
              "text": "Processing your document analysis..."
            }
          ],
          "messageId": "msg-status-update"
        },
        "timestamp": "2024-03-15T10:20:00Z"
      }
    }
  ],
  "totalSize": 1,
  "pageSize": 20,
  "nextPageToken": ""
}

分页示例

请求

POST /tasks/list HTTP/1.1
Host: agent.example.com
Content-Type: application/a2a+json
Authorization: Bearer token

{
  "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4",
  "pageSize": 10,
  "pageToken": "base64-encoded-cursor-token"
}

响应

HTTP/1.1 200 OK
Content-Type: application/a2a+json

{
  "tasks": [
    /* ... additional tasks */
  ],
  "totalSize": 15,
  "pageSize": 10,
  "nextPageToken": "base64-encoded-next-cursor-token"
}

验证错误示例

请求

POST /tasks/list HTTP/1.1
Host: agent.example.com
Content-Type: application/a2a+json
Authorization: Bearer token

{
  "pageSize": 150,
  "historyLength": -5,
  "status": "running"
}

响应

HTTP/1.1 400 Bad Request
Content-Type: application/problem+json

{
  "status": 400,
  "detail": "Invalid parameters",
  "errors": [
    {
      "field": "pageSize",
      "message": "Must be between 1 and 100 inclusive, got 150"
    },
    {
      "field": "historyLength",
      "message": "Must be non-negative integer, got -5"
    },
    {
      "field": "status",
      "message": "Invalid status value 'running'. Must be one of: pending, working, completed, failed, canceled"
    }
  ]
}

6.6. 推送通知设置和使用

场景:客户端请求一个长时间运行的报告生成,并希望在完成后通过 webhook 收到通知。

包含推送通知配置的初始请求

POST /message:send HTTP/1.1
Host: agent.example.com
Content-Type: application/a2a+json
Authorization: Bearer token

{
  "message": {
    "role": "user",
    "parts": [
      {
        "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"]
      }
    }
  }
}

响应(任务已提交)

HTTP/1.1 200 OK
Content-Type: application/a2a+json

{
  "task": {
    "id": "43667960-d455-4453-b0cf-1bae4955270d",
    "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4",
    "status": {
      "state": "submitted",
      "timestamp": "2024-03-15T11:00:00Z"
    }
  }
}

稍后:服务器通过 POST 向 Webhook 发送通知

POST /webhook/a2a-notifications HTTP/1.1
Host: client.example.com
Authorization: Bearer server-generated-jwt
Content-Type: application/a2a+json
X-A2A-Notification-Token: secure-client-token-for-task-aaa

{
  "statusUpdate": {
    "taskId": "43667960-d455-4453-b0cf-1bae4955270d",
    "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4",
    "status": {
      "state": "completed",
      "timestamp": "2024-03-15T18:30:00Z"
    },
    "final": true
  }
}

6.7. 文件交换(上传和下载)

场景:客户端发送图像进行分析,代理返回修改后的图像。

包含文件上传的请求

POST /message:send HTTP/1.1
Host: agent.example.com
Content-Type: application/a2a+json
Authorization: Bearer token

{
  "message": {
    "role": "user",
    "parts": [
      {
        "text": "Analyze this image and highlight any faces."
      },
      {
        "file": {
          "name": "input_image.png",
          "mediaType": "image/png",
          "fileWithBytes": "iVBORw0KGgoAAAANSUhEUgAAAAUA..."
        }
      }
    ],
    "messageId": "6dbc13b5-bd57-4c2b-b503-24e381b6c8d6"
  }
}

包含文件引用的响应

HTTP/1.1 200 OK
Content-Type: application/a2a+json

{
  "task": {
    "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": [
          {
            "file": {
              "name": "output.png",
              "mediaType": "image/png",
              "fileWithUri": "https://storage.example.com/processed/task-bbb/output.png?token=xyz"
            }
          }
        ]
      }
    ]
  }
}

6.8. 结构化数据交换

场景:客户端请求以特定 JSON 格式列出未解决的支持工单。

请求

POST /message:send HTTP/1.1
Host: agent.example.com
Content-Type: application/a2a+json
Authorization: Bearer token

{
  "message": {
    "role": "user",
    "parts": [
      {
        "text": "Show me a list of my open IT tickets",
        "metadata": {
          "mediaType": "application/json",
          "schema": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "ticketNumber": { "type": "string" },
                "description": { "type": "string" }
              }
            }
          }
        }
      }
    ],
    "messageId": "85b26db5-ffbb-4278-a5da-a7b09dea1b47"
  }
}

包含结构化数据的响应

HTTP/1.1 200 OK
Content-Type: application/a2a+json

{
  "task": {
    "id": "d8c6243f-5f7a-4f6f-821d-957ce51e856c",
    "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4",
    "status": {
      "state": "completed",
      "timestamp": "2025-04-17T17:47:09.680794Z"
    },
    "artifacts": [
      {
        "artifactId": "c5e0382f-b57f-4da7-87d8-b85171fad17c",
        "parts": [
          {
            "text": "[{\"ticketNumber\":\"REQ12312\",\"description\":\"request for VPN access\"},{\"ticketNumber\":\"REQ23422\",\"description\":\"Add to DL - team-gcp-onboarding\"}]"
          }
        ]
      }
    ]
  }
}

6.9. 获取经过身份验证的扩展代理卡

场景:客户端发现支持经过身份验证的扩展卡的公共代理卡,并希望检索完整详细信息。

步骤 1:客户端获取公共代理卡

GET /.well-known/agent-card.json HTTP/1.1
Host: example.com

响应包含

{
  "capabilities": {
    "extendedAgentCard": true
  },
  "securitySchemes": {
    "google": {
      "openIdConnectSecurityScheme": {
        "openIdConnectUrl": "https://#/.well-known/openid-configuration"
      }
    }
  }
}

步骤 2:客户端获取凭据(带外 OAuth 2.0 流程)

步骤 3:客户端获取经过身份验证的扩展代理卡

GET /extendedAgentCard HTTP/1.1
Host: agent.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

响应

HTTP/1.1 200 OK
Content-Type: application/a2a+json

{
  "protocolVersions": ["1.0"],
  "name": "Extended Agent with Additional Skills",
  "skills": [
    /* Extended skills available to authenticated users */
  ]
}

7. 身份验证和授权

A2A 将代理视为标准企业应用程序,依赖于既定的 Web 安全实践。身份信息在协议层处理,而不是在 A2A 语义内部处理。

有关企业安全方面的全面指南,请参阅企业级功能

7.1. 协议安全

生产部署必须使用加密通信(HTTPS 用于基于 HTTP 的绑定,TLS 用于 gRPC)。实现应该使用现代 TLS 配置(建议 TLS 1.3+)和强大的密码套件。

7.2. 服务器身份验证

A2A 客户端应该通过在 TLS 握手期间根据受信任的证书颁发机构 (CA) 验证其 TLS 证书来验证 A2A 服务器的身份。

7.3. 客户端身份验证过程

  1. 需求发现:客户端通过 AgentCard 中的 securitySchemes 字段发现服务器所需的身份验证方案。
  2. 凭据获取(带外):客户端通过特定于所需身份验证方案的带外过程获取必要的凭据。
  3. 凭据传输:客户端在每个 A2A 请求的协议适当的标头或元数据中包含这些凭据。

7.4. 服务器身份验证职责

A2A 服务器

  • 必须根据提供的凭据及其声明的身份验证要求对每个传入请求进行身份验证。
  • 应该对身份验证挑战或拒绝使用适当的绑定特定错误代码。
  • 应该在错误响应中提供相关的身份验证挑战信息。

7.5. 任务内身份验证(辅助凭据)

如果代理在任务执行期间需要额外的凭据

  1. 应该将 A2A 任务转换为 TASK_STATE_AUTH_REQUIRED 状态。
  2. 随附的 TaskStatus.update 应该提供有关所需辅助身份验证的详细信息。
  3. A2A 客户端带外获取这些凭据,并在后续消息请求中提供它们。

7.6. 授权

身份验证后,A2A 服务器根据已验证的身份及其自己的策略授权请求。授权逻辑是实现特定的,可以考虑

  • 请求的特定技能
  • 任务中尝试的操作
  • 数据访问策略
  • OAuth 范围(如果适用)

8. 代理发现:Agent Card

8.1. 目的

A2A 服务器必须提供 Agent Card。Agent Card 描述了服务器的身份、功能、技能和交互要求。客户端使用此信息来发现合适的代理并配置交互。

有关发现策略的更多信息,请参阅代理发现指南

8.2. 发现机制

客户端可以通过以下方式找到 Agent Card

  • 知名 URI:访问 https://{server_domain}/.well-known/agent-card.json
  • 注册表/目录:查询精选的代理目录
  • 直接配置:预配置的 Agent Card URL 或内容

8.3. 协议声明要求

AgentCard 必须正确声明受支持的协议

8.3.1. 支持的接口声明

  • supportedInterfaces 字段应该按偏好顺序声明所有受支持的协议组合
  • supportedInterfaces 中的第一个条目代表首选接口
  • 每个接口必须准确声明其传输协议和 URL
  • 如果同一端点有多个传输可用,则 URL 可以重复使用

8.3.2. 客户端协议选择

客户端必须遵循以下规则

  1. 如果存在,解析 supportedInterfaces,并选择第一个支持的传输
  2. 当支持多个选项时,优先选择有序列表中的较早条目
  3. 为选定的传输使用正确的 URL

8.4. Agent Card 签名

Agent Card 可以使用 RFC 7515 中定义的 JSON Web Signature (JWS) 进行数字签名,以确保真实性和完整性。签名允许客户端验证 Agent Card 未被篡改,并且来自声称的提供商。

8.4.1. 规范化要求

在签名之前,Agent Card 内容必须使用 RFC 8785 中定义的 JSON 规范化方案 (JCS) 进行规范化。这确保了跨不同 JSON 实现的一致签名生成和验证。

规范化规则

  1. 字段存在和默认值处理:在规范化之前,JSON 表示必须遵循 第 5.7 节中定义的 Protocol Buffer 字段存在语义。这确保了规范形式准确反映了哪些字段是显式提供的,哪些是被省略的,从而在 Agent Card 重建时能够进行签名验证

    • 未显式设置的可选字段:标记为 optional 关键字但未显式设置的字段必须从 JSON 对象中省略
    • 显式设置为默认值的可选字段:标记为 optional 但显式设置为某个值(即使该值与默认值匹配)的字段必须包含在 JSON 对象中
    • 必填字段:标记为 REQUIRED 的字段必须始终存在,即使字段值与默认值匹配。
    • 默认值:具有默认值的字段必须省略,除非该字段被标记为 REQUIRED 或具有 optional 关键字。
  2. RFC 8785 符合性:Agent Card JSON 必须根据 RFC 8785 进行规范化,该标准指定

    • 对象属性的可预测排序(按键按字典顺序排列)
    • 数字、字符串和其他原始值的一致表示
    • 去除无关的空白
  3. 签名字段排除signatures 字段本身必须从被签名的内容中排除,以避免循环依赖。

默认值去除示例

原始 Agent Card 片段

{
  "name": "Example Agent",
  "description": "",
  "capabilities": {
    "streaming": false,
    "pushNotifications": false,
    "extensions": []
  },
  "skills": []
}

应用规范化规则

  • name:“示例代理” - 必填字段 → 包括
  • description:"" - 必填字段 → 包括
  • capabilities:对象 - 必填字段 → 包括(在处理子级之后)
    • streaming:false - 可选字段,存在于 JSON 中(显式设置)→ 包括
    • pushNotifications:false - 可选字段,存在于 JSON 中(显式设置)→ 包括
    • extensions:[] - 重复字段(非必填)带空数组 → 省略
  • skills:[] - 必填字段 → 包括

应用 RFC 8785 后

{"capabilities":{"pushNotifications":false,"streaming":false},"description":"","name":"Example Agent","skills":[]}

8.4.2. 签名格式

签名使用 RFC 7515 中定义的 JSON Web Signature (JWS) 格式。AgentCardSignature 对象使用三个字段表示 JWS 组件

  • protected(必需,字符串):包含 JWS 受保护标头的 Base64url 编码 JSON 对象
  • signature(必需,字符串):Base64url 编码的签名值
  • header(可选,对象):JWS 未受保护标头作为 JSON 对象(未 Base64url 编码)

JWS 受保护标头参数

受保护标头必须包含

  • alg:用于签名的算法(例如,“ES256”、“RS256”)
  • typ:对于 JWS 应该设置为“JOSE”
  • kid:用于识别签名密钥的密钥 ID

受保护标头可以包含

  • jku:指向包含公钥的 JSON Web Key Set (JWKS) 的 URL

签名生成过程

  1. 准备负载

    • 从 Agent Card 中删除具有默认值的属性
    • 排除 signatures 字段
    • 使用 RFC 8785 规范化生成的 JSON 以生成规范负载
  2. 创建受保护标头

    • 使用所需的标头参数(algtypkid)和任何可选参数(jku)构建 JSON 对象
    • 将标头序列化为 JSON
    • Base64url-编码序列化标头以生成 protected 字段值
  3. 计算签名

    • 构建 JWS 签名输入:ASCII(BASE64URL(UTF8(JWS Protected Header)) || '.' || BASE64URL(JWS Payload))
    • 使用 alg 标头参数中指定的算法和私钥对 JWS 签名输入进行签名
    • Base64url-编码生成的签名字节以生成 signature 字段值
  4. 组装 AgentCardSignature

    • protected 设置为步骤 2 中 Base64url 编码的受保护标头
    • signature 设置为步骤 3 中 Base64url 编码的签名值
    • 可选地将 header 设置为包含任何不受保护标头参数的 JSON 对象。

示例

给定规范的 Agent Card 负载和签名密钥,签名生成

{
  "protected": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpPU0UiLCJraWQiOiJrZXktMSIsImprdSI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYWdlbnQvandrcy5qc29uIn0",
  "signature": "QFdkNLNszlGj3z3u0YQGt_T9LixY3qtdQpZmsTdDHDe3fXV9y9-B3m2-XgCpzuhiLt8E0tV6HXoZKHv4GtHgKQ"
}

其中 protected 值解码为

{"alg":"ES256","typ":"JOSE","kid":"key-1","jku":"https://example.com/agent/jwks.json"}

8.4.3. 签名验证

验证 Agent Card 签名的客户端必须

  1. signatures 数组中提取签名
  2. 使用 kidjku(或从受信任的密钥库)检索公钥
  3. 从收到的 Agent Card 中删除具有默认值的属性
  4. 排除 signatures 字段
  5. 使用 RFC 8785 规范化生成的 JSON
  6. 根据规范化的负载验证签名

安全注意事项

  • 客户端应该在信任 Agent Card 之前验证至少一个签名
  • 公钥应该通过安全通道 (HTTPS) 检索
  • 客户端可以维护一个已知代理提供商的受信任密钥库
  • 过期或已吊销的密钥不能用于验证
  • 可以存在多个签名以支持密钥轮换

8.5. 示例 Agent Card

{
  "protocolVersions": ["1.0"],
  "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.",
  "supportedInterfaces": [
    {"url": "https://georoute-agent.example.com/a2a/v1", "protocolBinding": "JSONRPC"},
    {"url": "https://georoute-agent.example.com/a2a/grpc", "protocolBinding": "GRPC"},
    {"url": "https://georoute-agent.example.com/a2a/json", "protocolBinding": "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,
    "extendedAgentCard": true
  },
  "securitySchemes": {
    "google": {
      "openIdConnectSecurityScheme": {
        "openIdConnectUrl": "https://#/.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"
      ]
    }
  ],
  "signatures": [
    {
      "protected": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpPU0UiLCJraWQiOiJrZXktMSIsImprdSI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYWdlbnQvandrcy5qc29uIn0",
      "signature": "QFdkNLNszlGj3z3u0YQGt_T9LixY3qtdQpZmsTdDHDe3fXV9y9-B3m2-XgCpzuhiLt8E0tV6HXoZKHv4GtHgKQ"
    }
  ]
}

9. JSON-RPC 协议绑定

JSON-RPC 协议绑定提供了一个简单的、基于 HTTP 的接口,使用 JSON-RPC 2.0 进行方法调用,使用 Server-Sent Events 进行流式传输。

9.1. 协议要求

  • 协议:基于 HTTP(S) 的 JSON-RPC 2.0
  • Content-Type:请求和响应均为 application/json
  • 方法命名:与 gRPC 约定匹配的 PascalCase 方法名(例如,SendMessageGetTask
  • 流式传输:Server-Sent Events (text/event-stream)

9.2. 服务参数传输

第 3.2.6 节中定义的 A2A 服务参数必须使用标准 HTTP 请求头进行传输,因为 JSON-RPC 2.0 在 HTTP(S) 上运行。

服务参数要求

  • 服务参数名称必须作为 HTTP 头部字段传输
  • 根据 HTTP 规范 (RFC 7230),服务参数键不区分大小写
  • 同一服务参数的多个值(例如,A2A-Extensions应该在单个头部字段中用逗号分隔

包含 A2A 服务参数的请求示例

POST /rpc HTTP/1.1
Host: agent.example.com
Content-Type: application/json
Authorization: Bearer token
A2A-Version: 0.3
A2A-Extensions: https://example.com/extensions/geolocation/v1,https://standards.org/extensions/citations/v1

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "SendMessage",
  "params": { /* SendMessageRequest */ }
}

9.3. 基本请求结构

所有 JSON-RPC 请求必须遵循标准 JSON-RPC 2.0 格式

{
  "jsonrpc": "2.0",
  "id": "unique-request-id",
  "method": "category/action",
  "params": { /* method-specific parameters */ }
}

9.4. 核心方法

9.4.1. SendMessage

发送消息以启动或继续任务。

请求

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "SendMessage",
  "params": { /* SendMessageRequest object */ }
}

引用对象:SendMessageRequest, Message

响应

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    /* SendMessageResponse object, contains one of:
     * "task": { Task object }
     * "message": { Message object }
    */
  }

引用对象:Task, Message

9.4.2. SendStreamingMessage

发送消息并通过 Server-Sent Events 订阅实时更新。

请求:SendMessage 相同

响应:HTTP 200,带 Content-Type: text/event-stream

data: {"jsonrpc": "2.0", "id": 1, "result": { /* Task | Message | TaskArtifactUpdateEvent | TaskStatusUpdateEvent */ }}

data: {"jsonrpc": "2.0", "id": 1, "result": { /* Task | Message | TaskArtifactUpdateEvent | TaskStatusUpdateEvent */ }}

引用对象:Task, Message, TaskArtifactUpdateEvent, TaskStatusUpdateEvent

9.4.3. GetTask

检索任务的当前状态。

请求

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "GetTask",
  "params": {
    "id": "task-uuid",
    "historyLength": 10
  }
}

9.4.4. ListTasks

列出具有可选过滤和分页的任务。

请求

{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "ListTasks",
  "params": {
    "contextId": "context-uuid",
    "status": "working",
    "pageSize": 50,
    "pageToken": "cursor-token"
  }
}

9.4.5. CancelTask

取消正在进行的任务。

请求

{
  "jsonrpc": "2.0",
  "id": 4,
  "method": "CancelTask",
  "params": {
    "id": "task-uuid"
  }
}

9.4.6. SubscribeToTask

订阅任务流,以接收非终止状态任务的更新。

请求

{
  "jsonrpc": "2.0",
  "id": 5,
  "method": "SubscribeToTask",
  "params": {
    "id": "task-uuid"
  }
}

响应:SSE 流(与 SendStreamingMessage 格式相同)

错误:如果任务处于终止状态(completedfailedcancelledrejected),则返回 UnsupportedOperationError

9.4.7. 推送通知配置方法

  • SetTaskPushNotificationConfig - 设置推送通知配置
  • GetTaskPushNotificationConfig - 获取推送通知配置
  • ListTaskPushNotificationConfig - 列出推送通知配置
  • DeleteTaskPushNotificationConfig - 删除推送通知配置

9.4.8. GetExtendedAgentCard

检索扩展代理卡。

请求

{
  "jsonrpc": "2.0",
  "id": 6,
  "method": "GetExtendedAgentCard"
}

9.5. 错误处理

JSON-RPC 错误响应使用标准的 JSON-RPC 2.0 错误对象结构,该结构映射到 第 3.3.2 节中定义的通用 A2A 错误模型,如下所示

  • 错误代码:映射到 error.code(数字 JSON-RPC 错误代码)
  • 错误消息:映射到 error.message(人类可读字符串)
  • 错误详细信息:映射到 error.data(可选结构化对象)

标准 JSON-RPC 错误代码

JSON-RPC 错误代码 错误名称 标准消息 描述
-32700 JSONParseError “无效的 JSON 负载” 服务器收到无效的 JSON
-32600 InvalidRequestError “请求负载验证错误” 发送的 JSON 不是有效的请求对象
-32601 MethodNotFoundError “未找到方法” 请求的方法不存在或不可用
-32602 InvalidParamsError “无效参数” 方法参数无效
-32603 InternalError “内部错误” 服务器上发生内部错误

A2A 特定错误代码

A2A 特定错误使用范围在 -32001-32099 之间的代码。有关 A2A 错误类型到 JSON-RPC 错误代码的完整映射,请参阅第 5.4 节(错误代码映射)

错误响应结构

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32601,
    "message": "Method not found",
    "data": {
      "method": "invalid/method"
    }
  }
}

A2A 特定错误响应示例

{
  "jsonrpc": "2.0",
  "id": 2,
  "error": {
    "code": -32001,
    "message": "Task not found",
    "data": {
      "taskId": "nonexistent-task-id",
      "timestamp": "2025-11-09T10:30:00.000Z"
    }
  }
}

data 字段可以包含额外的上下文特定信息,以帮助客户端诊断和解决错误。

10. gRPC 协议绑定

gRPC 协议绑定使用 Protocol Buffers over HTTP/2 提供高性能、强类型接口。gRPC 协议绑定利用 API 指南来简化 gRPC 到 HTTP 的映射。

10.1. 协议要求

  • 协议:带 TLS 的 gRPC over HTTP/2
  • 定义:使用 specification/grpc/a2a.proto 中的规范 Protocol Buffers 定义
  • 序列化:Protocol Buffers version 3
  • 服务:实现 A2AService gRPC 服务

10.2. 服务参数传输

第 3.2.6 节中定义的 A2A 服务参数必须使用 gRPC 元数据(头部)进行传输。

服务参数要求

  • 服务参数名称必须作为 gRPC 元数据键传输
  • 元数据键不区分大小写,gRPC 会自动将其转换为小写
  • 同一服务参数的多个值(例如,A2A-Extensions应该在单个元数据条目中用逗号分隔

包含 A2A 服务参数的 gRPC 请求示例

// Go example using gRPC metadata
md := metadata.Pairs(
    "authorization", "Bearer token",
    "a2a-version", "0.3",
    "a2a-extensions", "https://example.com/extensions/geolocation/v1,https://standards.org/extensions/citations/v1",
)
ctx := metadata.NewOutgoingContext(context.Background(), md)

// Make the RPC call with the context containing metadata
response, err := client.SendMessage(ctx, request)

元数据处理

  • 实现必须从 gRPC 元数据中提取 A2A 服务参数进行处理
  • 服务器应该验证元数据中所需的 서비스 参数(例如,A2A-Version
  • 根据 gRPC 约定,元数据中的服务参数键规范化为小写

10.3. 服务定义

service A2AService {
  rpc SendMessage(SendMessageRequest) returns (SendMessageResponse);
  rpc SendStreamingMessage(SendMessageRequest) returns (stream StreamResponse);
  rpc GetTask(GetTaskRequest) returns (Task);
  rpc ListTasks(ListTasksRequest) returns (ListTasksResponse);
  rpc CancelTask(CancelTaskRequest) returns (Task);
  rpc SubscribeToTask(SubscribeToTaskRequest) returns (stream StreamResponse);
  rpc SetTaskPushNotificationConfig(SetTaskPushNotificationConfigRequest) returns (TaskPushNotificationConfig);
  rpc GetTaskPushNotificationConfig(GetTaskPushNotificationConfigRequest) returns (TaskPushNotificationConfig);
  rpc ListTaskPushNotificationConfig(ListTaskPushNotificationConfigRequest) returns (ListTaskPushNotificationConfigResponse);
  rpc DeleteTaskPushNotificationConfig(DeleteTaskPushNotificationConfigRequest) returns (google.protobuf.Empty);
  rpc GetExtendedAgentCard(GetExtendedAgentCardRequest) returns (AgentCard);
}

10.4. 核心方法

10.4.1. SendMessage

向代理发送消息。

请求

// Represents a request for the `message/send` method.
message SendMessageRequest {
  // Optional tenant, provided as a path parameter.
  string tenant = 4;
  // The message to send to the agent.
  Message message = 1 [(google.api.field_behavior) = REQUIRED];
  // Configuration for the send request.
  SendMessageConfiguration configuration = 2;
  // A flexible key-value map for passing additional context or parameters.
  google.protobuf.Struct metadata = 3;
}

响应

message SendMessageResponse {
  oneof payload {
    Task task = 1;
    Message message = 2;
  }
}

10.4.2. SendStreamingMessage

发送带流式更新的消息。

请求

// Represents a request for the `message/send` method.
message SendMessageRequest {
  // Optional tenant, provided as a path parameter.
  string tenant = 4;
  // The message to send to the agent.
  Message message = 1 [(google.api.field_behavior) = REQUIRED];
  // Configuration for the send request.
  SendMessageConfiguration configuration = 2;
  // A flexible key-value map for passing additional context or parameters.
  google.protobuf.Struct metadata = 3;
}

响应:服务器流式传输 StreamResponse 对象。

10.4.3. GetTask

检索任务状态。

请求

// Represents a request for the `tasks/get` method.
message GetTaskRequest {
  // Optional tenant, provided as a path parameter.
  string tenant = 3;
  // The resource name of the task.
  // Format: tasks/{task_id}
  string name = 1 [(google.api.field_behavior) = REQUIRED];
  // The maximum number of messages to include in the history.
  optional int32 history_length = 2;
}

响应:请参阅 Task 对象定义。

10.4.4. ListTasks

列出带过滤器的任务。

请求

// Parameters for listing tasks with optional filtering criteria.
message ListTasksRequest {
  // Optional tenant, provided as a path parameter.
  string tenant = 9;
  // Filter tasks by context ID to get tasks from a specific conversation or session.
  string context_id = 1;
  // Filter tasks by their current status state.
  TaskState status = 2;
  // Maximum number of tasks to return. Must be between 1 and 100.
  // Defaults to 50 if not specified.
  optional int32 page_size = 3;
  // Token for pagination. Use the next_page_token from a previous ListTasksResponse.
  string page_token = 4;
  // The maximum number of messages to include in each task's history.
  optional int32 history_length = 5;
  // Filter tasks which have a status updated after the provided timestamp in ISO 8601 format (e.g., "2023-10-27T10:00:00Z").
  // Only tasks with a status timestamp time greater than or equal to this value will be returned.
  google.protobuf.Timestamp status_timestamp_after = 6;
  // Whether to include artifacts in the returned tasks.
  // Defaults to false to reduce payload size.
  optional bool include_artifacts = 7;
}

响应

// Result object for tasks/list method containing an array of tasks and pagination information.
message ListTasksResponse {
  // Array of tasks matching the specified criteria.
  repeated Task tasks = 1 [(google.api.field_behavior) = REQUIRED];
  // Token for retrieving the next page. Empty string if no more results.
  string next_page_token = 2 [(google.api.field_behavior) = REQUIRED];
  // The size of page requested.
  int32 page_size = 3 [(google.api.field_behavior) = REQUIRED];
  // Total number of tasks available (before pagination).
  int32 total_size = 4 [(google.api.field_behavior) = REQUIRED];
}

10.4.5. CancelTask

取消正在运行的任务。

请求

// Represents a request for the `tasks/cancel` method.
message CancelTaskRequest {
  // Optional tenant, provided as a path parameter.
  string tenant = 2;
  // The resource name of the task to cancel.
  // Format: tasks/{task_id}
  string name = 1;
}

响应:请参阅 Task 对象定义。

10.4.6. SubscribeToTask

通过流式传输订阅任务更新。如果任务处于终止状态,则返回 UnsupportedOperationError

请求

message SubscribeToTaskRequest {
  // Optional tenant, provided as a path parameter.
  string tenant = 2;
  // The resource name of the task to subscribe to.
  // Format: tasks/{task_id}
  string name = 1;
}

响应:服务器流式传输 StreamResponse 对象。

10.4.7. SetTaskPushNotificationConfig

为任务创建推送通知配置。

请求

// Represents a request for the `tasks/pushNotificationConfig/set` method.
message SetTaskPushNotificationConfigRequest {
  // Optional tenant, provided as a path parameter.
  string tenant = 4;
  // The parent task resource for this config.
  // Format: tasks/{task_id}
  string parent = 1 [(google.api.field_behavior) = REQUIRED];
  // The ID for the new config.
  string config_id = 2 [(google.api.field_behavior) = REQUIRED];
  // The configuration to create.
  TaskPushNotificationConfig config = 3 [(google.api.field_behavior) = REQUIRED];
}

响应:请参阅 PushNotificationConfig 对象定义。

10.4.8. GetTaskPushNotificationConfig

检索任务的现有推送通知配置。

请求

message GetTaskPushNotificationConfigRequest {
  // Optional tenant, provided as a path parameter.
  string tenant = 2;
  // The resource name of the config to retrieve.
  // Format: tasks/{task_id}/pushNotificationConfigs/{config_id}
  string name = 1;
}

响应:请参阅 PushNotificationConfig 对象定义。

10.4.9. ListTaskPushNotificationConfig

列出任务的所有推送通知配置。

请求

message ListTaskPushNotificationConfigRequest {
  // Optional tenant, provided as a path parameter.
  string tenant = 4;
  // The parent task resource.
  // Format: tasks/{task_id}
  string parent = 1;
  // The maximum number of configurations to return.
  int32 page_size = 2;

  // A page token received from a previous ListTaskPushNotificationConfigRequest call.
  string page_token = 3;
}

响应

// Represents a successful response for the `tasks/pushNotificationConfig/list`
// method.
message ListTaskPushNotificationConfigResponse {
  // The list of push notification configurations.
  repeated TaskPushNotificationConfig configs = 1;
  // A token, which can be sent as `page_token` to retrieve the next page.
  // If this field is omitted, there are no subsequent pages.
  string next_page_token = 2;
}

10.4.10. DeleteTaskPushNotificationConfig

删除任务的推送通知配置。

请求

// Represents a request for the `tasks/pushNotificationConfig/delete` method.
message DeleteTaskPushNotificationConfigRequest {
  // Optional tenant, provided as a path parameter.
  string tenant = 2;
  // The resource name of the config to delete.
  // Format: tasks/{task_id}/pushNotificationConfigs/{config_id}
  string name = 1;
}

响应:google.protobuf.Empty

10.4.11. GetExtendedAgentCard

身份验证后检索代理的扩展能力卡。

请求

message GetExtendedAgentCardRequest {
  // Optional tenant, provided as a path parameter.
  string tenant = 1;
}

响应:请参阅 AgentCard 对象定义。

10.5. gRPC 特定数据类型

10.5.1. TaskPushNotificationConfig

推送通知配置的资源包装器。这是一个 gRPC 特定类型,用于面向资源的操作中,以提供完整的资源名称以及配置数据。

// A container associating a push notification configuration with a specific
// task.
message TaskPushNotificationConfig {
  // The resource name of the config.
  // Format: tasks/{task_id}/pushNotificationConfigs/{config_id}
  string name = 1 [(google.api.field_behavior) = REQUIRED];
  // The push notification configuration details.
  PushNotificationConfig push_notification_config = 2 [(google.api.field_behavior) = REQUIRED];
}

字段

将推送通知配置与特定任务关联的容器。

字段 类型 必填 描述
name 字符串 配置的资源名称。格式:tasks/{task_id}/pushNotificationConfigs/{config_id}
pushNotificationConfig PushNotificationConfig 推送通知配置详情。

10.6. 错误处理

gRPC 错误响应使用标准的 gRPC 状态结构和 google.rpc.Status,该结构映射到 第 3.3.2 节中定义的通用 A2A 错误模型,如下所示

  • 错误代码:映射到 status.code(gRPC 状态码枚举)
  • 错误消息:映射到 status.message(人类可读字符串)
  • 错误详细信息:映射到 status.details(重复的 google.protobuf.Any 消息)

A2A 错误表示

对于 A2A 特定错误,实现必须status.details 数组中包含 google.rpc.ErrorInfo 消息,其中包含

  • reason:大写下划线命名法的 A2A 错误类型,不带“Error”后缀(例如,TASK_NOT_FOUND
  • domain:设置为 "a2a-protocol.org"
  • metadata:附加错误上下文的可选映射

有关 A2A 错误类型到 gRPC 状态码的完整映射,请参阅第 5.4 节(错误码映射)

错误响应示例

// Standard gRPC invalid argument error
status {
  code: INVALID_ARGUMENT
  message: "Invalid request parameters"
  details: [
    {
      type: "type.googleapis.com/google.rpc.BadRequest"
      field_violations: [
        {
          field: "message.parts"
          description: "At least one part is required"
        }
      ]
    }
  ]
}

A2A 特定错误响应示例

// A2A-specific task not found error
status {
  code: NOT_FOUND
  message: "Task with ID 'task-123' not found"
  details: [
    {
      type: "type.googleapis.com/google.rpc.ErrorInfo"
      reason: "TASK_NOT_FOUND"
      domain: "a2a-protocol.org"
      metadata: {
        task_id: "task-123"
        timestamp: "2025-11-09T10:30:00Z"
      }
    }
  ]
}

10.7. 流式传输

gRPC 流式传输使用服务器流式 RPC 进行实时更新。StreamResponse 消息提供了可能的流式传输事件的联合

// A wrapper object used in streaming operations to encapsulate different types of response data.
message StreamResponse {
  oneof payload {
    // A Task object containing the current state of the task.
    Task task = 1;
    // A Message object containing a message from the agent.
    Message message = 2;
    // An event indicating a task status update.
    TaskStatusUpdateEvent status_update = 3;
    // An event indicating a task artifact update.
    TaskArtifactUpdateEvent artifact_update = 4;
  }
}

11. HTTP+JSON/REST 协议绑定

HTTP+JSON 协议绑定提供了一个使用标准 HTTP 方法和 JSON 负载的 RESTful 接口。

11.1. 协议要求

  • 协议:HTTP(S) 和 JSON 负载
  • Content-Type:请求和响应均为 application/json
  • 方法:标准 HTTP 动词(GET、POST、PUT、DELETE)
  • URL 模式:基于 RESTful 资源的 URL
  • 流式传输:Server-Sent Events 用于实时更新

11.2. 服务参数传输

第 3.2.6 节中定义的 A2A 服务参数必须使用标准 HTTP 请求头进行传输。

服务参数要求

  • 服务参数名称必须作为 HTTP 头部字段传输
  • 根据 HTTP 规范 (RFC 9110),服务参数键不区分大小写
  • 同一服务参数的多个值(例如,A2A-Extensions应该在单个头部字段中用逗号分隔

包含 A2A 服务参数的请求示例

POST /message:send HTTP/1.1
Host: agent.example.com
Content-Type: application/json
Authorization: Bearer token
A2A-Version: 0.3
A2A-Extensions: https://example.com/extensions/geolocation/v1,https://standards.org/extensions/citations/v1

{
  "message": {
    "role": "user",
    "parts": [{"text": "Find restaurants near me"}]
  }
}

11.3. URL 模式和 HTTP 方法

11.3.1. 消息操作

  • POST /message:send - 发送消息
  • POST /message:stream - 流式发送消息(SSE 响应)

11.3.2. 任务操作

  • GET /tasks/{id} - 获取任务状态
  • GET /tasks - 列出任务(带查询参数)
  • POST /tasks/{id}:cancel - 取消任务
  • POST /tasks/{id}:subscribe - 订阅任务更新(SSE 响应,对终止任务返回错误)

11.3.3. 推送通知配置

  • POST /tasks/{id}/pushNotificationConfigs - 创建配置
  • GET /tasks/{id}/pushNotificationConfigs/{configId} - 获取配置
  • GET /tasks/{id}/pushNotificationConfigs - 列出配置
  • DELETE /tasks/{id}/pushNotificationConfigs/{configId} - 删除配置

11.3.4. 代理卡

  • GET /extendedAgentCard - 获取经过身份验证的扩展 Agent Card

11.4. 请求/响应格式

所有请求和响应都使用在结构上等效于 Protocol Buffer 定义的 JSON 对象。

示例发送消息

POST /message:send
Content-Type: application/json

{
  "message": {
    "messageId": "uuid",
    "role": "user",
    "parts": [{"text": "Hello"}]
  },
  "configuration": {
    "acceptedOutputModes": ["text/plain"]
  }
}

引用对象:SendMessageRequest, Message

响应

HTTP/1.1 200 OK
Content-Type: application/json

{
  "task": {
    "id": "task-uuid",
    "contextId": "context-uuid",
    "status": {
      "state": "completed"
    }
  }
}

引用对象:Task

11.5. 请求参数的查询参数命名

不支持请求正文的 HTTP 方法 (GET, DELETE) 必须将操作请求参数作为路径参数或查询参数进行传输。本节定义了如何将 Protocol Buffer 字段名映射到查询参数名。

命名约定

查询参数名称必须使用 camelCase 以匹配 Protocol Buffer 字段名称的 JSON 序列化。这确保了与 POST 操作中使用的请求正文的一致性。

示例映射

Protocol Buffer 字段 查询参数名称 使用示例
context_id contextId ?contextId=uuid
page_size pageSize ?pageSize=50
page_token pageToken ?pageToken=cursor
task_id taskId ?taskId=uuid

使用示例

列出带过滤的任务

GET /tasks?contextId=uuid&status=working&pageSize=50&pageToken=cursor

获取带历史的任务

GET /tasks/{id}?historyLength=10

字段类型处理

  • 字符串:直接作为查询参数值传递
  • 布尔值:表示为小写字符串(truefalse
  • 数字:表示为十进制字符串
  • 枚举:使用其字符串值表示(例如,status=working
  • 重复字段:可以通过重复参数名称(例如,?tag=value1&tag=value2)或作为逗号分隔值(例如,?tag=value1,value2)来传递多个值
  • 嵌套对象:查询参数中不支持;需要嵌套对象的操作必须使用带请求正文的 POST

URL 编码

所有查询参数值必须根据 RFC 3986 进行正确的 URL 编码。

11.6. 错误处理

HTTP 错误响应使用 RFC 9457 Problem Details 格式,Content-Type: application/problem+json,其映射到 第 3.3.2 节中定义的通用 A2A 错误模型,如下所示

  • 错误代码:映射到 status (HTTP 状态码) 和 type (URI 标识符)
  • 错误消息:映射到 detail (人类可读字符串)
  • 错误详细信息:映射到问题详细信息对象中的扩展字段

A2A 错误表示

对于 A2A 特定错误,type 字段必须使用第 5.4 节(错误码映射)中映射表中的 URI。附加错误上下文可以作为扩展字段包含在问题详细信息对象中。

错误响应示例

HTTP/1.1 404 Not Found
Content-Type: application/problem+json

{
  "type": "https://a2a-protocol.org.cn/errors/task-not-found",
  "title": "Task Not Found",
  "status": 404,
  "detail": "The specified task ID does not exist or is not accessible",
  "taskId": "task-123",
  "timestamp": "2025-11-09T10:30:00.000Z"
}

taskIdtimestamp 等扩展字段提供了额外的上下文,以帮助诊断错误。

11.7. 流式传输

REST 流式传输使用 Server-Sent Events,其中 data 字段包含协议数据对象的 JSON 序列化

POST /message:stream
Content-Type: application/json

{ /* SendMessageRequest object */ }

引用对象:SendMessageRequest

响应

HTTP/1.1 200 OK
Content-Type: text/event-stream

data: {"task": { /* Task object */ }}

data: {"artifactUpdate": { /* TaskArtifactUpdateEvent */ }}

data: {"statusUpdate": { /* TaskStatusUpdateEvent */ }}

引用对象:Task, TaskStatusUpdateEvent, TaskArtifactUpdateEvent 流式响应是简单、线性有序的序列:首先是一个 Task(或单个 Message),然后是零个或多个状态或工件更新事件,直到任务达到终止或中断状态,此时流关闭。实现应该避免重新排序事件,并且可以在关闭之前选择性地重新发送最终的 Task 快照。

12. 自定义绑定指南

虽然 A2A 协议提供了三种标准绑定(JSON-RPC、gRPC 和 HTTP+JSON/REST),但实现者可以创建自定义协议绑定以支持额外的传输机制或通信模式。自定义绑定必须遵守第 5 节(协议绑定要求和互操作性)中定义的所有要求。本节提供了开发自定义绑定的额外具体指南。

12.1. 绑定要求

自定义协议绑定必须

  1. 实现所有核心操作:支持第 3 节(A2A 协议操作)中定义的所有操作
  2. 保留数据模型:使用功能上等同于第 4 节(协议数据模型)中定义的数据结构
  3. 保持语义:确保操作行为与抽象操作定义一致
  4. 完整文档:提供绑定规范的全面文档

12.2. 数据类型映射

自定义绑定必须提供明确的映射,用于

  • Protocol Buffer 类型:定义每个 Protocol Buffer 消息类型的表示方式
  • 时间戳:遵循第 5.6.1 节(时间戳)中的约定
  • 二进制数据:指定二进制内容的编码(例如,基于文本协议的 base64)
  • 枚举:定义枚举值的表示方式(例如,字符串、整数)

12.3. 服务参数传输

第 3.2.6 节(服务参数)中所述,自定义协议绑定必须记录服务参数的传输方式。绑定规范必须解决

  1. 传输机制:传输服务参数键值对的协议特定方法
  2. 值约束:服务参数值的任何限制(例如,字符编码、大小限制)
  3. 保留名称:绑定本身保留的任何服务参数名称
  4. 回退策略:当协议缺少本机标头支持时会发生什么(例如,在元数据中传递服务参数)

示例文档要求

  • 对于本机标头支持:“服务参数使用 HTTP 请求标头传输。服务参数键不区分大小写,并且必须符合 RFC 7230。服务参数值必须是 UTF-8 字符串。”
  • 对于没有标头的协议:“服务参数序列化为 JSON 对象,并在请求元数据字段 a2a-service-parameters 中传输。”

12.4. 错误映射

自定义绑定必须

  1. 映射标准错误:提供第 3.2.2 节(错误处理)中定义的所有 A2A 特定错误的映射
  2. 保留错误信息:确保客户端可以访问错误详细信息
  3. 使用适当的代码:在适用时映射到协议原生错误代码
  4. 文档错误格式:指定错误响应的结构

12.5. 流式传输支持

如果绑定支持流式操作

  1. 定义流机制:文档如何实现流式传输(例如,WebSockets、长轮询、分块编码)
  2. 事件排序:指定流式事件的排序保证
  3. 重新连接:定义连接中断和恢复的行为
  4. 流终止:指定如何发出流完成信号

如果不支持流式传输,绑定必须在 Agent Card 中明确记录此限制。

12.6. 身份验证和授权

自定义绑定必须

  1. 支持标准方案:实现 Agent Card 中声明的身份验证方案
  2. 文档集成:指定凭据在协议中的传输方式
  3. 处理挑战:定义如何传达身份验证挑战
  4. 维护安全:遵循传输协议的安全最佳实践

12.7. Agent Card 声明

自定义绑定必须在 Agent Card 中声明

  1. 传输标识符:使用清晰、描述性的传输名称
  2. 端点 URL:提供绑定可用的完整 URL
  3. 文档链接:包含指向完整绑定规范的 URL

示例

{
  "supportedInterfaces": [
    {
      "url": "wss://agent.example.com/a2a/websocket",
      "protocolBinding": "WEBSOCKET"
    }
  ]
}

12.8. 互操作性测试

自定义绑定实现者应该

  1. 对照参考进行测试:验证行为是否与标准绑定匹配
  2. 记录差异:明确指出与标准绑定行为的任何偏差
  3. 提供示例:包括示例请求和响应
  4. 测试边缘情况:验证错误条件、大负载和长时间运行任务的处理

13. 安全注意事项

本节整合了实现和操作 A2A 代理的安全指南和最佳实践。有关其他企业安全注意事项,请参阅企业级功能

13.1. 数据访问和授权范围

实现必须确保根据已验证调用者的授权边界进行适当的范围限制。这适用于访问或列出任务和其他资源的所有操作。

授权原则

  • 服务器必须对每个A2A 协议操作请求实施授权检查
  • 实现必须根据代理授权模型定义的调用者授权访问边界来确定结果范围
  • 即使请求中未指定 contextId 或其他筛选参数,实现也必须将结果范围限定在调用者的授权访问边界内
  • 授权模型由代理定义,可以基于
    • 用户身份(基于用户的授权)
    • 组织角色或组(基于角色的授权)
    • 项目或工作区成员身份(基于项目的授权)
    • 组织或租户边界(多租户授权)
    • 特定于代理领域的自定义授权逻辑

需要范围限制的操作

  • List Tasks必须仅返回根据代理授权模型对已验证客户端可见的任务
  • Get Task必须验证已验证客户端根据代理授权模型是否具有访问请求任务的权限
  • 任务相关操作(取消、订阅、推送通知配置):必须验证客户端根据代理授权模型是否具有适当的访问权限

实施要求

  • 授权边界由每个代理的授权模型定义,而不是由协议规定
  • 授权检查必须在任何数据库查询或可能泄露调用者授权范围外资源存在的信息的操作之前进行
  • 代理应该记录其授权模型和访问控制策略

另请参阅:第 3.1.4 节 列出任务(安全注意事项)以获取操作特定要求。

13.2. 推送通知安全

在实施推送通知时,代理(作为 webhook 调用者)和客户端(作为 webhook 接收者)都负有安全责任。

代理(Webhook 调用者)要求

  • 代理必须在 webhook 请求中包含PushNotificationConfig.authentication中指定的身份验证凭据
  • 代理应该为 webhook 请求设置合理的超时值(建议:10-30 秒)
  • 代理应该为失败的交付实施具有指数退避的重试逻辑
  • 代理 可以 在连续多次失败后停止尝试交付
  • 代理 应该 验证 webhook URL 以防止 SSRF (Server-Side Request Forgery) 攻击
    • 拒绝私有 IP 范围 (127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
    • 拒绝 localhost 和链路本地地址
    • 在适当情况下实施 URL 允许列表

客户端(Webhook 接收器)要求

  • 客户端 必须 使用提供的认证凭据验证 webhook 真实性
  • 客户端 应该 验证负载中的任务 ID 是否与他们创建的预期任务匹配
  • 客户端 必须 以 HTTP 2xx 状态码响应以确认成功接收
  • 客户端 应该 幂等地处理通知,因为可能会发生重复交付
  • 客户端 应该 实施速率限制以防止 webhook 泛滥
  • 客户端 应该 为 webhook URL 使用 HTTPS 端点以确保机密性

配置安全

  • Webhook URL 应该 使用 HTTPS 来保护传输中的负载机密性
  • PushNotificationConfig 中的认证令牌 应该 被视为秘密并定期轮换
  • 代理 应该 安全地存储推送通知配置和凭据
  • 客户端 应该 为每个推送通知配置使用唯一的、单一用途的令牌

另请参阅:第 4.3 节 推送通知对象第 4.3.3 节 推送通知负载

13.3. 扩展代理卡访问控制

扩展代理卡功能允许代理向经过身份验证的客户端提供公共代理卡中未包含的额外功能或信息。

访问控制要求

  • 获取扩展代理卡 操作 必须 要求认证
  • 代理 必须 使用公共 AgentCard.securitySchemesAgentCard.security 字段中声明的方案之一进行请求认证
  • 代理 可以 根据经过身份验证的客户端身份或授权级别返回不同的扩展卡内容
  • 代理 应该 实施适当的缓存头以控制客户端对扩展卡的缓存

基于能力访问

  • 扩展卡 可以 包含公共卡中不存在的额外技能
  • 扩展卡 可以 暴露更详细的能力信息(例如,速率限制、配额)
  • 扩展卡 可以 包含特定于组织或用户的配置
  • 代理 应该 记录在不同认证级别下可用的功能

安全注意事项

  • 扩展卡 不应该 包含敏感信息,以免泄露后被利用(例如,内部服务 URL、未遮盖的凭据)
  • 代理 必须 在扩展卡中返回特权信息之前验证客户端是否具有适当的权限
  • 检索扩展卡的客户端 应该 在其认证会话期间将其缓存的公共代理卡替换为扩展版本
  • 代理 应该 适当地对扩展卡进行版本控制并遵守客户端缓存失效

可用性声明

另请参阅:第 3.1.11 节 获取扩展代理卡第 3.3.4 节 能力验证

13.4. 一般安全最佳实践

传输安全

  • 生产部署 必须 使用加密通信(基于 HTTP 的绑定使用 HTTPS,gRPC 使用 TLS)
  • 实现 应该 使用现代 TLS 配置(建议 TLS 1.3+)和强大的密码套件
  • 代理 应该 在使用基于 HTTP 的绑定时强制执行 HSTS (HTTP Strict Transport Security) 头
  • 实现 应该 禁用对已弃用 SSL/TLS 版本的支持 (SSLv3, TLS 1.0, TLS 1.1)

输入验证

  • 代理 必须 在处理前验证所有输入参数
  • 代理 应该 对消息大小、文件大小和请求复杂性实施适当的限制
  • 代理 应该 清理或验证文件内容类型并拒绝意外的媒体类型

凭据管理

  • API 密钥、令牌和其他凭据 必须 被视为秘密
  • 凭据 应该 定期轮换
  • 凭据 应该 仅通过加密连接传输
  • 代理 应该 实施凭据撤销机制
  • 代理 应该 记录身份验证失败并实施速率限制以防止暴力攻击

审计和监控

  • 代理 应该 记录安全相关事件(身份验证失败、授权拒绝、可疑请求)
  • 代理 应该 实施对异常模式的监控(快速创建任务、过度取消)
  • 代理 应该 为敏感操作提供审计跟踪
  • 除非必要且受到适当保护,否则日志 不得 包含敏感信息(凭据、个人数据)

速率限制和滥用预防

  • 代理 应该 对所有操作实施速率限制
  • 代理 应该 在超出速率限制时返回适当的错误响应
  • 代理 可以 对不同的操作或用户级别实施不同的速率限制

数据隐私

  • 代理 必须 遵守适用的数据保护法规
  • 代理 应该 提供机制供用户请求删除其数据
  • 代理 应该 实施适当的数据保留策略
  • 代理 应该 最大限度地减少对敏感或个人信息的日志记录

自定义绑定安全

  • 自定义协议绑定 必须 在其规范中解决安全考虑
  • 自定义绑定 应该 遵循与标准绑定相同的安全原则
  • 自定义绑定 必须 记录认证集成和凭据传输

另请参阅:第 12.6 节 认证和授权(自定义绑定)

14. IANA 考虑

本节提供 A2A 协议的媒体类型、HTTP 头和众所周知 URI 的注册模板,旨在提交给互联网号码分配机构 (IANA)。

14.1. 媒体类型注册

14.1.1. application/a2a+json

类型名称: application

子类型名称: a2a+json

必需参数:

可选参数

编码注意事项: 二进制(JSON 文本 必须 使用 UTF-8 编码)

安全注意事项: 此媒体类型共享 RFC 8259 第 12 节中描述的与所有基于 JSON 的格式相同的安全注意事项。此外

  • 内容 必须 在处理前根据 A2A 协议模式进行验证
  • 实现 必须 清理用户提供的内容以防止注入攻击
  • A2A 消息中的文件引用 必须 经过验证以防止服务器端请求伪造 (SSRF)
  • 认证和授权 必须 按照 A2A 规范第 7 节中的规定执行
  • 任务历史记录和工件中的敏感信息 必须 根据适用的数据保护法规进行保护

互操作性注意事项: A2A 协议支持多种协议绑定。此媒体类型旨在用于 HTTP+JSON/REST 绑定。

已发布规范: Agent2Agent (A2A) 协议规范,可在以下网址获取:https://a2a-protocol.org.cn/latest/specification

使用此媒体类型的应用程序: 实现 A2A 协议进行代理间通信的 AI 代理平台、代理工作流系统、多代理协作工具和企业自动化系统。

片段标识符注意事项:

附加信息

  • 此类型的已弃用别名:
  • 魔术数字:
  • 文件扩展名: .a2a.json
  • Macintosh 文件类型代码: TEXT

联系人及电子邮件地址以获取更多信息: A2A 协议工作组,a2a-protocol@example.org

预期用途: 常用

使用限制:

作者: A2A 协议工作组

变更控制者: A2A 协议工作组

临时注册:

14.2. HTTP 头字段注册

注意: 以下 HTTP 头表示 第 3.2.6 节 中定义的抽象 A2A 服务参数的基于 HTTP 的协议绑定实现。这些注册特定于 HTTP/HTTPS 传输。

14.2.1. A2A-Version 头

头字段名称: A2A-Version

适用协议: HTTP

状态: 标准

作者/变更控制者: A2A 协议工作组

规范文档: A2A 协议规范第 3.2.5 节

相关信息: A2A-Version 头字段指示客户端正在使用的 A2A 协议版本。该值 必须Major.Minor 格式(例如,“0.3”)。如果代理不支持该版本,代理将返回 VersionNotSupportedError

示例

A2A-Version: 0.3

14.2.2. A2A-Extensions 头

头字段名称: A2A-Extensions

适用协议: HTTP

状态: 标准

作者/变更控制者: A2A 协议工作组

规范文档: A2A 协议规范第 3.2.5 节

相关信息: A2A-Extensions 头字段包含一个逗号分隔的扩展 URI 列表,客户端希望在请求中使用这些扩展。扩展允许代理提供超出核心 A2A 规范的附加功能,同时保持向后兼容性。

示例

A2A-Extensions: https://example.com/extensions/geolocation/v1,https://standards.org/extensions/citations/v1

14.3. 众所周知 URI 注册

URI 后缀: agent-card.json

变更控制者: A2A 协议工作组

规范文档: A2A 协议规范第 8.2 节

相关信息: .well-known/agent-card.json URI 提供了一个标准化位置,用于发现 A2A 代理的能力、支持的协议、认证要求和可用技能。此 URI 上的资源 必须 返回 A2A 规范第 4.4.1 节中定义的 AgentCard 对象。

状态: 永久

安全注意事项

  • 代理卡 可以 包含有关代理能力的公共信息,并且 不应该 包含敏感凭据或内部实现细节
  • 实现 应该 支持 HTTPS 以确保代理卡的真实性和完整性
  • 代理卡 可以 使用 JSON Web 签名 (JWS) 进行签名,如 AgentCardSignature 对象(第 4.4.7 节)中指定
  • 客户端 应该 在存在签名时验证签名,以确保代理卡未被篡改
  • 通过认证端点(第 3.1.11 节)检索的扩展代理卡 可以 包含附加信息,并且 必须 执行适当的访问控制

示例

https://agent.example.com/.well-known/agent-card.json

附录 A. 迁移与遗留兼容性

本附录列出了已重命名的协议消息和对象、它们的遗留标识符以及计划的弃用/移除时间表。所有遗留名称和锚点 必须 在规定的最早移除版本之前保持可解析。

遗留名称 当前名称 最早移除版本 备注
MessageSendParams SendMessageRequest >= 0.5.0 为清晰起见重命名请求负载(请求 vs 参数)
SendMessageSuccessResponse SendMessageResponse >= 0.5.0 统一的成功响应命名
SendStreamingMessageSuccessResponse StreamResponse >= 0.5.0 更短、与绑定无关的流式响应
SetTaskPushNotificationConfigRequest CreateTaskPushNotificationConfigRequest >= 0.5.0 明确的创建意图
ListTaskPushNotificationConfigSuccessResponse ListTaskPushNotificationConfigResponse >= 0.5.0 一致的响应后缀移除
GetAuthenticatedExtendedCardRequest GetExtendedAgentCardRequest >= 0.5.0 从命名中移除“Authenticated”

计划生命周期(示例时间线;根据发布策略调整)

  1. 0.3.x:引入新名称;记录遗留名称;添加别名。
  2. 0.4.x:在 SDK 和模式中将遗留名称标记为“已弃用”;添加警告说明。
  3. ≥0.5.0:遗留名称经审查后有资格移除;更新迁移附录。

A.1 遗留文档锚点

隐藏的锚点跨度保留旧的入站链接

每个遗留跨度 应该 放置在当前对象标题旁边(将在详细对象部分编辑期间插入)。如果存在精确的数字前缀锚点(例如,#414-message),则如果已知,请添加一个与该历史形式匹配的附加跨度。

A.2 迁移指南

客户端实现 应该

  • 立即为所有新集成优先使用新名称。
  • 在模式/类型允许的情况下实现双重处理(例如,联合类型或向后兼容的解码器)。
  • 在首次弃用公告发布后收到遗留命名对象时记录警告。

服务器实现 可以

  • 在重叠期间接受遗留和当前请求消息形式。
  • 在响应中只发出当前形式(推荐),同时提供明确的升级说明。

A.2.1 破坏性变更:移除 Kind 鉴别器

版本 1.0 引入了一个破坏性变更,改变了协议中多态对象的表示方式。这影响了 Part 类型和流事件类型。

遗留模式 (v0.3.x): 对象使用内联 kind 字段作为鉴别器来标识对象类型

示例 1 - TextPart

{
  "kind": "TextPart",
  "text": "Hello, world!"
}

示例 2 - FilePart

{
  "kind": "FilePart",
  "mimeType": "image/png",
  "name": "diagram.png",
  "fileWithBytes": "iVBORw0KGgo..."
}

当前模式 (v1.0): 对象现在使用 JSON 成员名称 本身来标识类型。成员名称作为鉴别器,值结构取决于特定类型

示例 1 - TextPart

{
  "text": "Hello, world!"
}

示例 2 - FilePart

{
  "file": {
    "mediaType": "image/png",
    "name": "diagram.png",
    "fileWithBytes": "iVBORw0KGgo..."
  }
}

受影响的类型

  1. 部分联合类型:
  2. TextPart:
    • 遗留: { "kind": "TextPart", "text": "..." }
    • 当前: { "text": "..." } (直接字符串值)
  3. FilePart:
    • 遗留: { "kind": "FilePart", "mimeType": "...", "name": "...", "fileWithBytes": "..." }
    • 当前: { "file": { "mediaType": "...", "name": "...", "fileWithBytes": "..." } }
  4. DataPart:

    • 遗留: { "kind": "DataPart", "data": {...} }
    • 当前: { "data": { "data": {...} } }
  5. 流事件类型:

  6. TaskStatusUpdateEvent:
    • 遗留: { "kind": "TaskStatusUpdateEvent", "taskId": "...", "status": {...} }
    • 当前: { "statusUpdate": { "taskId": "...", "status": {...} } }
  7. TaskArtifactUpdateEvent:
    • 遗留: { "kind": "TaskArtifactUpdateEvent", "taskId": "...", "artifact": {...} }
    • 当前: { "artifactUpdate": { "taskId": "...", "artifact": {...} } }

迁移策略

对于从 pre-0.3.x 升级的 客户端

  1. 更新解析器以期望以成员名称作为鉴别器的包装对象
  2. 在构建请求时,使用新的包装格式
  3. 根据代理 AgentCard 中的 protocolVersions 实现版本检测
  4. 考虑在过渡期内通过检测和处理两种格式来保持向后兼容性

对于从 pre-0.3.x 升级的 服务器

  1. 更新序列化逻辑以发出包装对象
  2. 破坏性变更: kind 字段不再是协议的一部分,不应发出
  3. 更新反序列化以期望以成员名称作为包装对象
  4. 确保 AgentCard 声明正确的 protocolVersions(例如,["1.0"] 或更高版本)

基本原理

此变更与现代 API 设计实践和 Protocol Buffers 的 oneof 语义保持一致,其中字段名称本身作为类型鉴别器。这种方法

  • 减少冗余(无需同时使用字段名称和 kind 值)
  • 使 JSON-RPC 和 gRPC 表示更紧密地对齐
  • 简化了从模式定义生成代码
  • 消除了在模式语言中表示继承结构的需要
  • 提高了强类型语言的类型安全性

A.2.2 破坏性变更:扩展代理卡字段重新定位

版本 1.0 将扩展代理卡能力 从顶层字段重新定位到 capabilities 对象,以实现架构一致性。

遗留结构(1.0 之前)

{
  "supportsExtendedAgentCard": true,
  "capabilities": {
    "streaming": true
  }
}

当前结构(1.0+)

{
  "capabilities": {
    "streaming": true,
    "extendedAgentCard": true
  }
}

Proto 变更

  • 已移除:AgentCard.supports_extended_agent_card(字段 13)
  • 已添加:AgentCapabilities.extended_agent_card(字段 5)

迁移步骤

对于 代理实现

  1. 从顶级 AgentCard 中移除 supportsExtendedAgentCard
  2. extendedAgentCard 添加到 capabilities 对象
  3. 更新验证:agentCard.capabilities?.extendedAgentCard

对于 客户端实现

  1. 更新能力检查:agentCard.capabilities?.extendedAgentCard
  2. 临时回退(过渡期)
const supported = agentCard.capabilities?.extendedAgentCard ||
                  agentCard.supportsExtendedAgentCard;
  1. 在代理生态系统迁移后移除回退

对于 SDK 开发者

  1. 从更新的 proto 重新生成代码
  2. 更新类型定义
  3. 在发布说明中记录破坏性变更

基本原理

所有启用特定操作的可选功能(streamingpushNotificationsstateTransitionHistory)都位于 AgentCapabilities 中。移动 extendedAgentCard 实现了

  • 架构一致性
  • 提高了可发现性
  • 语义正确性(它是一种能力)

A.3 未来自动化

一旦 proto→schema 生成管道落地,本附录将部分自动生成(遗留映射表源自维护的清单)。在此之前,编辑 必须 手动进行,并在影响 a2a.proto 的 PR 中进行审查。

附录 B. 与 MCP(模型上下文协议)的关系

A2A 和 MCP 是互补协议,设计用于代理系统的不同方面

  • 模型上下文协议 (MCP) 专注于标准化 AI 模型和代理如何连接并与工具、API、数据源和其他外部资源交互。它定义了描述工具能力(如 LLM 中的函数调用)、传递输入和接收结构化输出的结构化方式。将 MCP 视为代理如何使用特定能力或访问资源的“操作指南”。
  • Agent2Agent 协议 (A2A): 专注于标准化独立的、通常不透明的AI 代理如何相互通信和协作。A2A 提供了一个应用程序级协议,供代理相互发现、协商交互方式、管理共享任务以及交换对话上下文或复杂结果。它关乎代理如何合作委派工作。

它们如何协同工作: 一个 A2A 客户端代理可能会请求一个 A2A 服务器代理执行一个复杂的任务。服务器代理反过来可能会使用 MCP 与多个底层工具、API 或数据源交互,以收集信息或执行完成 A2A 任务所需的操作。

有关更详细的比较,请参阅A2A 和 MCP 指南