乐于分享
好东西不私藏

A2A协议文档

A2A协议文档

来自官方文档 https://a2a-protocol.org/latest/  学习笔记

A2A 是什么?

A2A 协议是一种开放标准,旨在实现 AI 智能体(AI Agents)之间的无缝通信与协作。它为由不同供应商使用不同框架构建的智能体提供了一种通用语言,从而促进互操作性并打破信息孤岛。智能体是在其环境中独立行动的自主问题解决者。A2A 允许来自不同开发者、基于不同框架构建且归属于不同组织的智能体联合起来协同工作。

A2A Protocol (智能体对智能体协议) 为 AI 智能体提供了一种标准化的方式,用于:

  • 发现彼此的能力

智能体可以使用 JSON 格式的”智能体卡”(Agent Card)来广告其能力。这使客户端智能体能够识别最适合执行任务的智能体,并利用 A2A 与远程智能体通信。例如,客户端智能体可能发现另一个智能体专门处理财务数据,并将财务分析任务委托给它。

  • 协商交互模式(文本、表单、文件等)

  • 管理协作任务

  • 以结构化格式交换信息

A2A协议使用基于 HTTP(S) 的 JSON-RPC 2.0,并支持标准的请求/响应模式和通过服务器发送事件 (SSE) 进行流式传输。

A2A 的核心优势

实施 A2A 协议为 AI 生态系统带来显著优势:

  • 安全协作:没有标准,很难确保智能体之间的通信安全。A2A 使用 HTTPS 进行安全通信,并保持操作的不透明性(opaque operations),因此智能体在协作过程中无法窥探其他智能体的内部运作。

  • 互操作性:A2A 打破了不同 AI 智能体生态系统之间的孤岛,使来自不同供应商和框架的智能体能够无缝协作。

  • 智能体自主性:A2A 允许智能体在与其他智能体协作的同时,保留其独立的能力并作为自主实体行动。

  • 降低集成复杂度:该协议标准化了智能体通信,使团队能够专注于其智能体提供的独特价值。

  • 支持 LRO:该协议通过服务器发送事件 (SSE) 和异步执行,支持长运行操作 (LRO) 和流式传输。

A2A 设计原则

A2A 的开发遵循优先考虑广泛采用、企业级能力和面向未来的原则。

  1. 简洁性 (Simplicity):A2A 利用现有的标准,如 HTTP、JSON-RPC 和服务器发送事件 (SSE)。这避免了核心技术的重复发明,并加速了开发者的采用。

  2. 企业级就绪 (Enterprise Readiness):A2A 解决了关键的企业需求。它符合关于健壮的身份验证、授权、安全性、隐私、链路追踪和监控的标准 Web 实践。

  3. 异步 (Asynchronous):A2A 原生支持长运行任务。它处理智能体或用户可能不会保持持续连接的场景,并使用流式传输和推送通知等机制。

  4. 模态无关 (Modality Independent):该协议允许智能体使用多种内容类型进行通信。这允许超越纯文本的丰富且灵活的交互。

  5. 不透明执行 (Opaque Execution):智能体在不暴露其内部逻辑、内存或专有工具的情况下进行有效协作。交互依赖于声明的能力和交换的上下文。这保护了知识产权并增强了安全性。

理解智能体技术栈:A2A、 MCP、 智能体框架与模型

A2A 位于广义的智能体技术栈中,该技术栈包括:

  • A2A: 部署在不同组织中并使用不同框架开发的智能体之间的标准化通信。

  • MCP: 连接模型与数据及外部资源。

  • 框架(如 ADK): 提供构建智能体的工具包。

  • 模型: 智能体推理的基础,可以是任何大型语言模型 (LLM)。

A2A 与 MCP

A2A 的定位是与 MCP 互补。

MCP 的侧重点: 降低连接智能体与工具和数据的复杂性。工具通常是无状态的,执行特定的、预定义的功能(例如计算器、数据库查询)。

A2A 的侧重点: 使智能体能够在其原生模式下进行协作,允许它们作为“智能体”(或作为用户)进行通信,而不是被局限于类似“工具”的交互。这实现了复杂的多轮交互,其中智能体可以进行推理、规划并将任务委派给其他智能体。

将智能体封装为简单的工具这种做法在根本上是有局限性的,因为它未能捕捉到智能体的全部能力。

为什么不能把智能体仅仅当做工具?

应该用不同的方式与工具和智能体进行交互。

智能体之间交互的时候能否简化成,把其中一个智能体当做另一个智能体的工具?

工具的明确定义

工具用于采取行动,无论是收集信息、做出更改,还是将信息从一种形式转换为另一种形式。在每一种情况下,都存在一种时间关系:提供输入,然后返回某些输出。下图展示了这一点,其中也包含流式操作(streaming action)的示例。

长运行操作(Long running operations, LRO)在概念上与标准流程完全一致,只是时间轴更长。实际应用中,接口先返回该 LRO 的引用标识,然后通过独立操作查询其运行状态。

当我们谈论**行动单元(unit of action)时,会默认其遵循一套固定的时间流程:请求行动 -> 执行行动 -> 完成行动,若行动无法完成则执行错误处理。在这个序列中,除了“工作中”、“已完成”或“错误”之外,没有其他状态。这符合传统的 API 结构,也是工具(tool)概念的基础。工具可以被要求采取行动、可以等待行动完成并可以报告错误。

对于解决问题而言,与另一个智能体的交互必须能够支持:反馈补充信息的请求,提出弥补缺失信息的建议。有人可能会尝试将这两种能力整合到工具定义的异常码处理逻辑中,或扩展工具完成操作后的输出数据体,但这样做的结果,会让工具从一个行动单元变成了一个问题解决的参与者。如果用户(人类或智能体)在解决问题的过程中改变了目标,事情会变得更加复杂。本文的立场是,我们应该将这两种场景建模为不同的交互。

智能体是解决问题的协作者

智能体被期望拥有自主性。这意味着它们被授权根据可用信息和操作环境做出决策。它们能够处理不断变化的需求(“我改变主意了,我不想要 A,我想要 B”)。举个例子,一个智能体被要求“将用户的地址更新为 X”。这听起来像是一个行动请求,应该简单地以成功或失败的结果完成。但实际上,取决于智能体的环境和知识,这可能会复杂得多。例如:

  • 如果智能体唯一追踪的地址是电子邮件地址,而提供的地址是物理邮寄地址怎么办?

  • 如果智能体使用的系统在进行此类更改之前需要某种验证怎么办?例如,提供地址证明?

  • 如果智能体与之对话的记录系统有特定期望,比如所有带有地址的用户帐户都必须有电话号码怎么办?

在这个世界里,智能体不是工具,它现在是一个问题解决者(problem solver)。为了成为问题解决者,它需要与调用者互动以确定最佳行动方案。下图展示了智能体接口的多轮交互特性,其中智能体使用了工具接口。

通过这个接口,智能体可以将信息返回给调用者,共同解决问题。例如:

  • “抱歉,我需要电子邮件地址来更新用户资料,但您提供的是邮寄地址。”

  • “是的,我可以更新地址。但首先必须按照 http://verify.my.address/ 的步骤验证地址。”

  • “我很乐意更新地址。看起来该帐户没有电话号码。我需要那个号码才能完成地址更新。”

此时,调用者可以自行决定如何进行。也许它们有必要的信息并可以提供,也许这需要提交给人类进行处理等等。这与工具流程的关键区别在于,行动不保证在返回时已完成。行动处于不完整或中断状态;它已经开始,也许某些子行动已经完成,但原始行动是不完整的。更进一步说,行动甚至可能永远不会完成。例如,如果用户不验证他们的地址,更改地址的行动就永远不会完成。

结构化交互与无界的交互

深究下去,工具与智能体的输入和输出形状存在区别。如上所述,工具定义了一个行动单元,这个定义可以通过高度结构化的输入和输出模式(schema)来制定。这种结构限制了输入域 ? 和输出范围 ℝ,从而严格约束了行动空间。这种严格约束允许对错误空间进行清晰的解释。任何不符合输入域的内容都是错误,任何不能由输出范围表示的内容也是错误。如何处理错误取决于调用者,但错误状态的表示最少由一个错误代码定义。

因此,我们将工具定义为一个有时间限制的行动,它使用结构化的输入和输出定义函数映射 ƒ(x ∈ ?) → y ∈ ℝ,如果 x ∉∊? 或函数产生 y ∉ ℝ 则为错误状态。如果返回错误,模型可以推断未满足这两个条件之一。它还可以假设在行动完成时将返回错误或 y ∈ ℝ。行动的错误状态意味着行动失败。再次调用时不会恢复该行动,而是执行一个新的行动,带有新的 x ∈ ?。这是工具和智能体之间的一个关键区别

然而,在智能体交互中,? 和 ℝ 实际上都是无界的。此外,当 y ∈ ℝ 返回时,行动可能并未完成,相反,y 可能包含一些增量信息,调用者应该消费、转换并将这些信息传回给智能体以继续。这种以完成操作为目标的迭代过程,会带来一系列新的挑战,这也是我们提出智能体交互接口应与工具接口区分设计的原因——因此智能体不能被当作工具对待。工具接口是智能体接口的一种退化情况。只有在仅需支持这种退化情形的场景下,才可以将智能体当作工具使用 —— 即智能体执行操作后,只会返回完成或异常的结果,不会进入需要恢复执行的中断状态。

说明性示例:旅行规划器

我们转向一个更具体的例子来说明解决问题对于实现目标的重要性。这个例子基于 [a2a-samples] 中的案例。场景为帮助用户规划一次出行。这个旅行规划解决方案有多个参与者:一个编排者(Orchestrator)、一个规划者(Planner)、一个航班预订智能体、一个酒店预订智能体和一个租车预订智能体。该系统旨在帮助用户完成类似这样的任务:“我想在 7 月去伦敦待 5 天,预算在 4000 美元以下。”

在这里,规划者必须提出标准以开始搜索。例如,预算分配以及关于地点和时间线的参数。该计划用于与 3 个不同的智能体交互以制定提案。计划的每一部分可能都需要特定的信息,这可能需要编排者向用户展示。例如,“你要从哪家航空公司出发?”或“你想靠近伦敦的哪个地铁站”。甚至可以聪明地问:“大多数人在伦敦不租车,你确定要租车吗?”。

关键在于这是一个解决问题的交互。什么是正确的参数集,可以用来适应问题空间的整体约束?这些约束甚至不是先验(a priori)已知的,而是通过多次交互发展出来的。

一旦知道了完整的约束集(包括预算、时间、对舱位的具体偏好、酒店的精准位置等),问题就变得更容易识别出一组最佳选项。可以将这些选项呈现给用户并进行预订。搜索和预订都是通过工具完成的,而对各类约束条件的梳理、搜索范围的界定,则通过智能体之间开放式的多轮交互实现。。

类比 GOTO 语句:未来的发展方向

我们可以用传统编程中的GOTO 语句,类比智能体的交互逻辑。智能体接口会引入类似 GOTO 的场景:控制流可能被迫脱离预期的执行上下文,甚至永远无法返回;还有可能被跳转到另一个 GOTO 语句,进入新的执行上下文。这类场景的管理和设计难度极高。正如编程领域对 GOTO 语句的使用共识 —— 建议将其使用范围限定在特定结构中(比如跳出循环),我们也提出:应将智能体这种无界的交互逻辑,仅限定在智能体与智能体的交互边界内,切勿延伸至工具的交互边界。工具的交互边界应严格遵循结构化编程的原则,保证其可读性、可解释性和可调试性。

若遵循上述原则,每个独立的智能体都能在自身的操作范围内,以更可控、更受约束的方式运行,进而提升解决方案的可扩展性。

A2A and ADK

Agent Development Kit (ADK) 是由谷歌研发的开源智能体开发工具集。A2A 是一款面向智能体的通信协议,可实现智能体间的跨框架通信,无论智能体的构建基于何种开发框架(如 ADK、LangGraph、Crew AI)均能适配。ADK 是一套灵活的模块化框架,专为 AI 智能体的开发与部署打造。尽管该工具包针对 Gemini AI 和谷歌技术生态做了专属优化,但同时具备模型无关部署无关的特性,且在设计之初就考虑了与其他框架的兼容性。

A2A 请求生命周期

A2A 请求生命周期是一套标准化流程,详细定义了请求执行的四大核心步骤:智能体发现、身份验证、调用 sendMessage API、调用 sendMessageStream API。下图将深入解析该流程的实际运行逻辑,直观呈现客户端、A2A 服务器与认证服务器之间的交互过程。

A2A 的核心概念与组件

A2A 交互的核心参与主体

用户:终端使用者,可为人工操作人员或自动化服务。用户发起请求,或定义需要一个或多个 AI 智能体协助完成的目标。

A2A 客户端(客户端智能体):代表用户执行操作的应用、服务或其他 AI 智能体,负责基于 A2A 协议发起通信。

A2A 服务端(远端智能体):AI 智能体或智能体化系统,对外提供实现 A2A 协议的 HTTP 端点。接收客户端的请求、处理任务,并返回结果或更新状态。从客户端视角来看,远端智能体是一个黑盒系统,即其内部运行逻辑、内存数据、调用的工具均不对外暴露。

基础通信元素

核心元素
说明
核心用途
智能体卡片
描述智能体身份、能力、端点 URL 、技能及认证要求的 JSON 元数据文档。
支持客户端发现智能体,并明确如何安全、高效地与智能体进行交互。
任务
由智能体启动的核心工作单元,有状态,拥有唯一标识,且具备定义好的生命周期,经历不同的状态(已提交、工作中、需要输入、已完成、失败、已取消)。
便于追踪长时间运行操作,同时支持多轮交互与协作。
消息
客户端(角色:”user”)与智能体(角色:”agent”)之间的单轮通信内容,包含具体信息与角色标识。消息包含部件。
传递指令、上下文、问题、答案或状态更新,此类信息无需是标准化工件。
部件(Part)
消息和工件的基础内容容器(如文本部件、文件部件、数据部件)。
为智能体在消息和工件中交换不同内容类型提供灵活性。
工件(Artifact)
智能体在执行任务过程中生成的具体输出(如文档、图片、结构化数据)。工件包含部件。
交付智能体的实际工作成果,确保输出内容结构化、可检索。

交互机制

A2A 协议支持多种交互模式,以适配不同的响应性需求与持久性需求。无论任务的复杂程度和执行时长如何,这些机制都能保障智能体高效、可靠地交换信息:

  1. 请求 / 响应(轮询模式):客户端发送请求,服务端做出响应;针对长时间运行的任务,客户端通过定期轮询服务端获取更新。

  2. 基于服务器发送事件(SSE)的流式传输:客户端发起一个流,通过打开的 HTTP 连接,实时接收来自服务端的增量结果或状态更新。

  3. 推送通知:针对超长时间运行的任务或断连场景,当任务发生重要更新时,服务端可主动向客户端提供的 Webhook 地址发送异步通知。

如需深入了解流式传输与推送通知的细节,可参考《流式传输与异步操作》文档。

智能体卡片

智能体卡片是一份 JSON 文档,相当于智能体的数字名片,用于初次发现和交互设置,包含智能体的核心元数据。客户端通过解析该文档,可判断某一智能体是否适用于指定任务、如何构造请求,以及如何进行安全通信。其核心信息包括:智能体身份、服务端点(URL)、A2A 协议能力、认证要求及技能列表。

消息与部件(Messages and Parts)

消息代表客户端与智能体之间的一次单轮通信,包含角色标识(”user” or “agent”)与唯一的 messageId,它包含一个或多个部件对象 ,部件是承载实际内容的细粒度容器。这一设计让 A2A 协议具备模态无关(modality independent)的特性。

主要的部件类型包括:

  • TextPart :承载纯文本内容。

  • FilePart :代表一个文件,它可以内联传输(Base64 编码)或通过 URI 传输。它包含诸如 “name” 和 “mimeType” 等元数据。

  • DataPart :承载结构化的 JSON 数据,适用于表单、参数或各类机器可读信息的传输。

工件(Artifacts )

工件是远端智能体在任务处理过程中生成的有形输出或具体结果。与普通消息不同,工件是智能体的实际交付成果,拥有唯一的 artifactId 、一个人类可读的名称,且由一个 / 多个部件对象组成。工件与任务生命周期深度绑定,并且可以增量流式传输给客户端。

智能体响应:任务或消息

智能体的响应分为两种类型:若需要执行长时间运行操作,返回新任务;若可即时响应,返回消息。

其他重要概念

  • Context ( contextId ):服务端生成的标识符,用于逻辑上将多个相关的 Task 对象分组,从而在一系列交互中提供上下文。

  • Transport and Format (传输与格式):A2A 通信通过 HTTP(S) 进行。JSON-RPC 2.0 用作所有请求和响应的载荷格式。

  • Authentication & Authorization (认证与授权):A2A 依赖于标准的 Web 安全实践。认证要求在 Agent Card 中声明,凭证(例如 OAuth tokens、API keys)通常通过 HTTP 标头传递,与 A2A 协议消息本身分离。

  • Agent Discovery (智能体发现):客户端查找 Agent Card 以了解可用的 A2A 服务端及其能力的过程。

  • Extensions (扩展):A2A 允许智能体在其 Agent Card 中声明自定义协议扩展。

A2A 中的智能体发现

智能体卡片的发现方式会根据部署环境与实际需求有所不同。智能体卡片定义了某一智能体可提供的服务能力,客户端智能体可通过多种策略发现这些卡片,具体策略的选择由部署环境和安全要求决定。

智能体卡片的作用

智能体卡片包含的关键信息如下:

  • 身份信息:包含namedescription, 和 provider 相关信息。

  • 服务端点:指定 A2A 服务的访问地址( url )。

  • A2A 能力:列出支持的功能特性,如 streaming 、pushNotifications 等;

  • 认证信息:详细说明所需的认证方案(例如 令牌认证”Bearer”, “OAuth2″)。

  • 技能信息:通过 AgentSkill 对象描述该智能体可执行的任务,包含 idnamedescriptioninputModesoutputModes, 和 examples.

客户端智能体使用智能体卡片来判断该智能体是否适配目标任务、构建请求并确保通信安全。

发现策略

1. 众所周知的 URI

该策略推荐用于公共智能体,或需要在特定领域内实现广泛发现的智能体。

  • 机制: A2A 服务器遵循 RFC 8615 原则,通过在其域名的标准化、众所周知的 URI 上托管智能体卡片,使其可被发现。标准路径为:https://{agent-server-domain}/.well-known/agent-card.json

  • 流程:

    • 客户端智能体获知或通过程序发现潜在 A2A 服务器的域名(例如 smart-thermostat.example.com)。

    • 客户端向 https://smart-thermostat.example.com/.well-known/agent-card.json 发起 HTTP GET 请求。

    • 如果智能体卡片存在且可访问,服务器将以 JSON 响应形式返回。

  • 优点:

    • 易于实现

    • 遵循通用行业标准

    • 支持自动化的智能体发现

  • 注意事项:

    • 最适用于开放场景或受领域管控的智能体发现场景。

    • 若智能体卡片包含敏感信息,其托管端点需配置身份认证机制。

  1. 精选注册中心(基于目录的发现)

该策略适用于企业内部环境或公共市场,这类场景通常由一个中心化的注册中心统一管理智能体卡片。精选注册中心作为中央仓库,支持客户端根据 “skills” 或 “tags” 等标准查询并发现智能体。

  • 机制:由一个中间服务(即注册中心)维护所有智能体卡片的集合,客户端可根据各类标准(如提供的技能、标签、服务提供方名称、支持的能力)向该注册中心发起查询,发现目标智能体。

  • 流程:

    • A2A 服务端将自身的智能体卡片发布至该注册中心;

    • 客户端智能体调用注册中心的接口,根据特定条件(如某一具体技能)发起搜索请求;

    • 注册中心返回匹配的智能体卡片,或卡片的访问引用地址。

  • 优点:

    • 集中化管理与治理;

    • 实现基于能力的智能体发现(如按技能检索);

    • 支持访问控制与信任框架;

    • 同时适用于私有环境和公共市场。

  • 注意事项:

    • 需单独部署并维护注册中心服务;

    • 现行 A2A 协议规范尚未为精选注册中心制定标准化的接口规范。

  1. 直接配置 / 私有发现

该策略适用于紧耦合系统、私有智能体,或开发场景,这类场景中会直接为客户端配置智能体卡片的相关信息或URLs。

  • 机制:客户端应用通过硬编码详情、配置文件、环境变量或私有 API 进行发现。

  • 流程:具体流程由应用的部署方式和配置策略决定,无统一标准。

  • 优点:在已知、静态的关系中建立连接非常简洁直接。

  • 注意事项:

    • 灵活性差,无法适配动态的智能体发现场景;

    • 若智能体卡片的信息发生变更,需重新对客户端进行配置;

    • 基于私有接口的发现方式缺乏统一的行业标准。

智能体卡片的安全防护

智能体卡片可能包含以下敏感信息:

  • 内部或受限智能体的 URL。

  • 敏感技能的描述。

保护机制

为降低安全风险,建议采用以下保护机制:

  • 经过身份验证的智能体卡片:若卡片包含敏感信息,或需要向客户端提供更详细的卡片版本,建议使用经过身份认证的扩展型智能体卡片。

  • 安全访问端点:对提供智能体卡片的 HTTP 端点(如 /.well-known/agent-card.json 或注册表 API)实施访问控制。方法包括:

    • 双向传输层安全协议认证 (mTLS)。

    • 网络访问限制(如基于 IP 地址段管控)。

    • HTTP 身份验证(例如 OAuth 2.0)。

  • 注册中心选择性披露:注册中心可根据客户端的身份和权限返回不同的智能体卡片。

任何包含敏感数据的智能体卡片,都必须通过身份认证和授权机制进行保护。A2A 协议规范强烈建议使用带外动态凭证完成认证,而非在智能体卡片中直接嵌入静态密钥。

未来展望

A2A 社区正在探索注册中心交互的标准化或更高级的发现协议。

A2A的企业级实施

A2A协议从设计之初便以企业级需求为核心。它并未发明新的安全和操作专有标准,而是致力于与现有企业基础设施及业界通用最佳实践无缝集成。这种设计让组织能够复用在安全、监控、治理和身份管理领域已有的投入与专业能力。

传输层安全(TLS)

保障数据在传输过程中的机密性与完整性,是所有企业级应用的基础要求。

  • HTTPS 强制要求:生产环境中所有 A2A 通信必须基于 HTTPS 进行。

  • 现代 TLS 标准:实现应采用现代 TLS 版本,推荐使用 TLS 1.2 及以上版本,并搭配业界标准的强密码套件,防范数据被窃听与篡改。

  • 服务器身份校验:A2A 客户端应在 TLS 握手阶段,通过校验服务端 TLS 证书与可信证书颁发机构的匹配性,验证 A2A 服务端身份,防范中间人攻击。

身份认证

A2A 将身份认证能力委托给标准 Web 机制,主要依托 HTTP 请求头与 OAuth2、OpenID Connect 等成熟标准实现。认证要求由 A2A 服务器在其代理卡(Agent Card)中声明。

  • 载荷中不含身份信息:A2A 协议载荷(如 JSON-RPC 消息)不直接携带用户或客户端身份信息,身份认证在传输层 / HTTP 层完成。

  • 智能体卡片声明:A2A 服务端的智能体卡片会在 security 字段中声明所支持的认证方案。

  • 带外凭证获取:A2A 客户端通过 A2A 协议之外的流程获取所需凭证(如 OAuth2 令牌、API keys),例如 OAuth 流程或安全密钥分发。

  • HTTP 头传输:凭证必须通过所选认证方案要求的标准 HTTP 头传输,例如:

    • Authorization: Bearer <TOKEN>

    • API-Key: <KEY_VALUE>

  • 服务端校验:A2A 服务端必须使用 HTTP 头中的凭证对每一次入站请求做身份认证。

  • 任务内认证(二级凭证):若某个智能体在任务执行中需要额外凭证才能访问其他系统或服务(例如代用户调用某工具),A2A 服务端会向客户端提示需要补充信息。客户端需通过 A2A 协议外的流程(如 OAuth 流程)获取这些二级凭证,并回传给 A2A 服务端以继续任务。

授权

客户端完成身份认证后,由 A2A 服务端负责对请求进行授权。授权逻辑与智能体实现、所处理数据及适用的企业策略强相关。

  • 细粒度控制:授权应基于已认证身份执行,身份可对应用户、客户端应用或二者兼有。

  • 基于技能的授权:可按智能体卡片中声明的技能粒度控制访问。

  • 数据和操作级授权:对接后端系统、数据库或工具的智能体,在执行敏感操作或访问敏感数据前,必须强制执行相应授权校验,智能体充当门卫角色。

  • 最小权限原则:智能体仅授予客户端或用户通过 A2A 接口完成目标操作所需的最小权限。

链路追踪、可观测性与监控

A2A 依赖于 HTTP,使其可轻松对接标准的企业链路追踪、日志与监控工具,为智能体间工作流提供关键可视能力。

  • 分布式追踪:A2A 客户端与服务端应接入分布式追踪系统。例如使用 OpenTelemetry,通过 W3C Trace Context 等标准 HTTP 头传递追踪上下文(包含trace IDs、span IDs),实现调试与性能分析的端到端可视化。

  • 全面日志记录:客户端与服务端均需记录详细日志,包括任务 ID、会话 ID、关联 ID、追踪上下文等,用于问题排查与审计。

  • 指标:A2A 服务端应暴露关键运行指标,如请求速率、错误率、任务处理延迟、资源利用率等,用于性能监控、告警与容量规划。

  • 审计:对关键事件(任务创建、关键状态变更、智能体操作)进行审计,尤其涉及敏感数据或高影响操作时。

API 管理与治理

对于对外暴露、跨组织或大型企业内部使用的 A2A 服务端,强烈建议接入 API 管理解决方案,可提供:

  • 集中式策略执行:统一实施安全策略,如身份认证、授权、限流、配额管控。

  • 流量管理:负载均衡、路由转发、中介处理。

  • 分析与报告:深入洞察智能体的使用情况、性能表现及趋势。

  • 开发者门户:支持 A2A 智能体发现,提供智能体卡片等文档,简化客户端开发者接入流程。

遵循上述企业级实践,A2A 实现可在复杂组织环境中安全、可靠、可管控地部署。这不仅能建立信任,还能实现可扩展的智能体间协作。

任务的生命周期

在 Agent2Agent (A2A) 协议中,交互场景可以从简单的无状态交换,到复杂的长运行进程。当智能体收到来自客户端的消息时,响应有以下两种:

  • 以无状态消息 Message 响应:这种类型的响应通常用于即时的、自包含的(self-contained)交互,无需进一步的状态管理即可完成。

  • 发起有状态任务 Task:如果响应是一个任务,智能体将按照已定义的生命周期处理它,根据需要,同步进度或请求输入,直到达到中断状态(例如 input-required [需输入]、auth-required [需授权])或终止状态(例如 completed [已完成]、canceled [已取消]、rejected [已拒绝]、failed [失败])。

分组关联交互 (Group Related Interactions)

contextId 是一个关键标识符,用于在逻辑上将多个 Task 对象和独立的 Message 对象进行分组,从而在一系列交互中提供连续性。

  • 当客户端首次发送消息时,智能体会响应一个新的 contextId。如果发起了任务,该任务还会有一个 taskId

  • 客户端可以在后续消息中包含相同的 contextId,以表明它们是在同一上下文中继续之前的交互。

  • 客户端可以选择在后续消息中附加 taskId,以表明该消息是针对特定任务的延续。

contextId使得多个(可能是并发的)任务能够为了一个共同目标或共享的上下文会话进行协作。在内部,A2A Agent(尤其是使用 LLM 的 Agent)使用 contextId 来管理其内部会话状态或 LLM 上下文。

智能体响应:消息还是任务

选择以 Message 还是 Task 响应,取决于交互的性质和智能体的能力:

  • 用于轻量交互的消息Message 对象适用于不需要长运行处理或复杂状态管理的事务性交互。智能体可能会在 Task 对象的提交之前,使用消息来协商任务的接收条件与范围。

  • 用于有状态交互的任务:当智能体将传入消息的意图映射到需要大量、可追踪、长周期工作的能力时,Agent 就会以 Task 对象进行响应。

从概念上讲,智能体按复杂度分为三类:

  1. 仅消息型智能体:始终返回 Message 对象。它们通常不管理复杂状态或长运行执行,并使用 contextId 将消息关联起来。这类智能体通常直接封装大模型调用与简单工具。

  2. 生成任务型智能体:始终返回 Task 对象,即便只是简单回复,也会建模为已完成的任务。一旦创建了任务,智能体仅返回 Task 对象;且一旦任务完成,就不能再发送更多消息。这种方法避免了在 Task 和 Message 之间做选择,但即使是简单的交互也会创建已完成的任务对象。

  3. 混合型智能体:既生成 Message 也生成 Task 对象。这些智能体使用消息来协商智能体能力和任务范围,然后发送 Task 对象来追踪执行并管理状态(例如 input-required或错误处理中)。一旦创建了任务,智能体仅会返回 Task 对象;且一旦任务完成,就不能再发送更多消息。有关混合型智能体的更多信息,请参阅 A2A 协议:揭秘任务与消息

任务改进

客户端经常需要根据任务结果发送新请求,或对先前任务的输出进行改进。模型设计为:沿用原任务的 contextId 发起新一轮交互。客户端通过在 Message 对象中使用 referenceTaskIds 提供对原始任务的引用,以此给智能体提示。随后智能体以新的 Task 或 Message 进行响应。

任务不可变性

一旦任务达到终结状态(已完成、已取消、已拒绝或失败),它就无法重启。任何与该任务相关的后续交互(例如改进),必须用相同的 contextId 发起一个新任务。这一原则提供了以下好处:

  • 任务不可变性:客户端可以可靠地引用任务及其关联的状态、Artifact(工件)和消息,提供了清晰的输入–输出映射,便于编排与可追溯。

  • 清晰的工作单元:每一个新的请求、改进或后续操作都成为一个不同的任务。这简化了簿记工作,允许对智能体的工作进行细粒度追踪,并能够将每个工件追溯到具体的工作单元。

  • 更易于实现:消除智能体开发者在 “新建任务” 还是 “重启旧任务” 上的歧义。

并行后续操作 (Parallel Follow-ups)

A2A 支持并行工作,允许智能体针对使用同一 contextId 发送的每个后续消息创建独特的、并行的任务。客户端可单独追踪每个任务,并在前置任务完成后立即创建依赖任务。 例如:

  • Task 1:预订飞往赫尔辛基的航班。

  • Task 2:基于 Task 1,预订酒店。

  • Task 3:基于 Task 1,预订雪地摩托活动。

  • Task 4:基于 Task 2,在酒店预订中增加水疗预约。

引用先前的工件

服务端智能体会从引用的任务或 contextId 中推断相关输出。服务端智能体最适合解决歧义或识别缺失的信息。如果存在歧义,智能体会通过返回 input-required(需输入)状态要求客户端进行澄清。客户端随后在其响应中指定工件,可选择在 Part 元数据中填充工件引用(artifactIdtaskId)。

追踪工件变更

后续任务或改进任务通常会导致基于旧工件创建新工件。追踪这些变更是很重要的,以确保在后续交互中仅使用最新版本的工件。这可理解为版本历史,其中每个新工件都与其前驱关联。

然而,客户端最适合管理这种工件链接关系。客户端决定什么构成可接受的结果,并有能力接受或拒绝新版本。因此,服务端智能体不应负责追踪工件的变更,这种链接关系也不属于 A2A 协议规范的一部分。客户端应在其端维护此版本历史,并向用户展示最新的可接受版本。

为方便客户端侧追踪,服务端智能体在生成现有工件的改进版本时,应使用一致的 artifact-name

当发起后续或改进任务时,客户端应显式引用它们要改进的工件,最好是其视角下的 “最新版”。如果未提供工件 引用,服务端智能体可以:

  • 基于当前 contextId 尝试推断目标工件。

  • 如果存在歧义或上下文不足,智能体应返回 input-required 任务状态,以请求客户端澄清。

后续操作场景示例

以下示例展示了一个带有后续操作的典型任务流:

  1. 客户端向智能体发送消息:

{  "jsonrpc": "2.0",  "id""req-001",  "method""message.send",  "params": {    "message": {      "role": "user",      "parts": [        {          "text": "Generate an image of a sailboat on the ocean."        }      ],      "messageId": "msg-user-001"    }  }}

  1. 智能体返回一张船的图片(已完成的任务):

{  "jsonrpc": "2.0",  "id": "req-001",  "result": {    "id": "task-boat-gen-123",    "contextId": "ctx-conversation-abc",    "status": {      "state": "TASK_STATE_COMPLETED"    },    "artifacts": [      {        "artifactId": "artifact-boat-v1-xyz",        "name": "sailboat_image.png",        "description": "A generated image of a sailboat on the ocean.",        "parts": [          {            "filename": "sailboat_image.png",            "mediaType": "image/png",            "raw": "base64_encoded_png_data_of_a_sailboat"          }        ]      }    ]  }}

  1. 客户端要求把船涂成红色。 此改进请求引用了先前的 taskId 并使用了相同的 contextId

{  "jsonrpc": "2.0",  "id""req-002",  "method""SendMessage",  "params": {    "message": {      "role": "user",      "messageId""msg-user-002",      "contextId""ctx-conversation-abc",      "referenceTaskIds": [        "task-boat-gen-123"      ],      "parts": [        {          "text": "Please modify the sailboat to be red."        }      ]    }  }}

  1. 智能体返回一个新的图片工件(新任务,相同上下文,相同工件名称): 智能体在相同的 contextId 内创建了一个新任务。新的船图片工件保留了相同的名称,但具有一个新的 artifactId

{  "jsonrpc": "2.0",  "id": "req-002",  "result": {    "id": "task-boat-color-456",    "contextId": "ctx-conversation-abc",    "status": {      "state": "TASK_STATE_COMPLETED"    },    "artifacts": [      {        "artifactId": "artifact-boat-v2-red-pqr",        "name": "sailboat_image.png",        "description": "A generated image of a red sailboat on the ocean.",        "parts": [          {            "filename": "sailboat_image.png",            "mediaType": "image/png",            "raw": "base64_encoded_png_data_of_a_RED_sailboat"          }        ]      }    ]  }}

A2A 中的扩展

A2A 协议为智能体间的通信提供了坚实的基础。然而,特定领域或高级用例往往需要在通用方法之外,增加额外的结构、自定义数据或新的交互模式。扩展 (Extensions) 是 A2A 协议中一种强大的机制,用于在基础协议之上叠加新的能力。

扩展允许通过引入新数据、需求、RPC 方法和状态机来延伸 A2A 协议。智能体在其 Agent Card中声明对特定扩展的支持,客户端随后可以在向智能体发出的请求中选择启用扩展所提供的行为。扩展通过 URI 进行标识,并由其自身的规范进行定义。任何人都可以定义、发布和实现扩展。

扩展的灵活性允许在不导致核心标准碎片化的情况下定制 A2A,从而促进创新和特定领域的优化。

扩展的范围

扩展的使用方式非常广泛,旨在促进 A2A 能够扩展到已知用例之外。一些可预见的应用包括:

  • 纯数据扩展:在智能体卡片中暴露新的结构化信息,不影响请求-响应流。例如,一个扩展可以添加关于智能体 GDPR 合规性的结构化数据。

  • 配置文件扩展 (Profile Extensions):在核心请求-响应消息上叠加额外的结构和状态变更要求。此类扩展实际上充当了核心 A2A 协议的配置文件,缩小合法取值范围(例如,要求所有消息使用符合特定 schema 的 DataParts )。也可通过元数据为任务状态机中的现有状态补充子状态。例如,当 TaskStatus.state 为 working 且 TaskStatus.message.metadata["generating-image"] 为 true 时,扩展可以定义一个 generating-image子状态。

  • 方法扩展(扩展技能):添加协议核心集定义之外的全新 RPC 方法。扩展技能是指,智能体通过实现一个定义新RPC方法的扩展,而获得或暴露的能力。例如,一个 task-history(任务历史)扩展可能会添加一个 tasks/search RPC 方法来检索先前的任务列表,从而有效地为智能体提供一种新的扩展技能。

  • 状态机扩展 (State Machine Extensions):向任务状态机添加新的状态或转换。

限制

扩展不允许对协议进行某些更改,这主要是为了防止破坏核心类型的验证:

  1. 更改核心数据结构的定义:例如,向协议定义的数据结构添加新字段或移除必填字段。扩展应将自定义属性放置在核心数据结构上的 metadata 映射(map)中。

  2. 向枚举类型添加新值:扩展应使用现有的枚举值,并在 metadata 字段中注明额外的语义含义。

扩展声明

智能体在智能体卡片中声明其对扩展的支持,在 AgentCapabilities 对象中包含 AgentExtension 对象。

以下是一个带有扩展的智能体卡片示例:

{  "name": "Magic 8-ball",  "description": "An agent that can tell your future... maybe.",  "version": "0.1.0",  "url": "https://example.com/agents/eightball",  "capabilities": {    "streaming": true,    "extensions": [      {        "uri": "https://example.com/ext/konami-code/v1",        "description": "Provide cheat codes to unlock new fortunes",        "required": false,        "params": {          "hints": [            "When your sims need extra cash fast",            "You might deny it, but we've seen the evidence of those cows."          ]        }      }    ]  },  "defaultInputModes": ["text/plain"],  "defaultOutputModes": ["text/plain"],  "skills": [    {      "id": "fortune",      "name": "Fortune teller",      "description": "Seek advice from the mystical magic 8-ball",      "tags": ["mystical", "untrustworthy"]    }  ]}

必选扩展

虽然扩展通常提供可选功能,但某些智能体可能有更严格的要求。当智能体卡片将扩展声明为 required: true 时,它向客户端发出信号,表明该扩展的某些方面会影响请求的结构或处理方式,客户端必须遵守。智能体不应将纯数据扩展标记为必选。如果客户端未请求激活必选扩展,或未能遵循其协议,智能体应以适当的错误拒绝传入的请求。

扩展规范

扩展的详细行为和结构由其规范定义。虽然确切格式未强制规定,但它应至少包含:

  • 标识该扩展的特定 URI(s) 。

  • AgentExtension 对象中 params 字段指定的对象的模式(Schema)和含义。

  • 客户端和智能体之间通信的任何额外数据结构的Schemas。

  • 实现该扩展所需的新请求-响应流、额外端点或任何其他逻辑的详细信息。

扩展依赖

扩展可能依赖于其他扩展。这可以是必需依赖(没有依赖项该扩展无法运行),也可以是可选依赖(如果存在另一个扩展,则启用附加功能)。扩展规范应文档化这些依赖关系。客户端有责任激活扩展及其在扩展规范中列出的所有必需依赖项。

扩展激活

扩展默认为非活动状态,以便为不知道该扩展的客户端提供基准体验。客户端和智能体通过协商,确定某次请求中激活哪些扩展。

  1. 客户端请求:客户端通过在发给智能体的 HTTP 请求中包含 A2A-Extensions 头部来请求激活扩展。该值是客户端打算激活的扩展 URI 列表,以逗号分隔。

  2. 智能体处理:智能体负责识别请求中支持的扩展,并执行激活。任何请求的扩展如智能体不支持可以被忽略。

  3. 响应:一旦智能体识别出所有已激活的扩展,响应应该 (SHOULD) 包含 A2A-Extensions 头部,列出该请求成功激活的所有扩展。

扩展激活请求示例:

POST /agents/eightball HTTP/1.1Host: example.comContent-Type: application/jsonA2A-Extensions: https://example.com/ext/konami-code/v1Content-Length: 519{  "jsonrpc""2.0",  "method""SendMessage",  "id""1",  "params": {    "message": {      "messageId""1",      "role""ROLE_USER",      "parts": [{"text""Oh magic 8-ball, will it rain today?"}]    },    "metadata": {      "https://example.com/ext/konami-code/v1/code""motherlode"    }  }}

回显已激活扩展的对应响应:

HTTP/1.1 200 OKContent-Type: application/jsonA2A-Extensions: https://example.com/ext/konami-code/v1Content-Length: 338{  "jsonrpc": "2.0",  "id""1",  "result": {    "message": {      "messageId": "2",      "role""ROLE_AGENT",      "parts": [{"text": "That's a bingo!"}]    }  }}

实现注意事项

虽然 A2A 协议定义了扩展的功能,本节提供了关于其实现的指导——包括编写、版本控制和分发扩展实现的最佳实践。

  • 版本控制:扩展规范会演变。制定清晰的版本控制策略至关重要,以确保客户端和智能体能够协商兼容的实现。

    • 建议:使用扩展的 URI 作为主要版本标识符,理想情况下包含版本号(例如,https://example.com/ext/my-extension/v1)。

    • 破坏性变更:当对扩展的逻辑、数据结构或必需参数引入破坏性变更时,必须使用新的 URI。

    • 处理不匹配:如果客户端请求的版本智能体不支持,智能体应该忽略该扩展的激活请求;它不得回退到不同的版本。

  • 可发现性与发布

    • 规范托管:扩展规范文档应该托管在扩展的 URI 处。

    • 永久标识符:鼓励作者为其扩展 URI 使用永久标识符服务(如 w3id.org),以防止链接失效。

    • 社区注册中心(未来):A2A 社区未来可能会建立一个中央注册中心,用于发现和浏览可用的扩展。

  • 打包与复用 (A2A SDK 和库):为提升普及度,扩展逻辑应打包成可复用的库,以便集成到现有的 A2A 客户端和服务器应用程序中。

    • 扩展实现应作为其语言生态系统的标准包进行分发(例如,Python 的 PyPI 包,TypeScript/JavaScript 的 npm 包)。

    • 目标是为开发者提供简化的集成体验。设计良好的扩展包应允许开发者用最少的代码将其添加到服务器中。

  • 安全性 :扩展修改了 A2A 协议的核心行为,因此引入了新的安全注意事项:

    • 输入验证:扩展引入的任何新数据字段、参数或方法必须经过严格验证。将所有来自外部方的扩展相关数据视为不可信输入。

    • 必选扩展的范围:在智能体卡片中将扩展标记为 required: true 时要务必小心。这会对所有客户端创建硬依赖,应仅用于对智能体核心功能和安全性至关重要的扩展(例如消息签名扩展)。

    • 认证与授权:如果扩展添加了新方法,实现必须确保这些方法接受与核心 A2A 方法相同的认证和授权检查。扩展不得提供绕过智能体主要安全控制的途径。

更多信息,请参阅 A2A Extensions: Empowering Custom Agent Functionality 博客文章。

长运行任务的流式传输与异步操作

Agent2Agent (A2A) 协议被明确设计用于处理可能无法立即完成的任务。许多 AI 驱动的操作通常是长运行的,涉及多个步骤,产生增量结果,或需要人工干预。A2A 提供了管理此类异步交互的机制,确保客户端能够有效地接收更新,无论它们是保持持续连接还是处于断连状态。

使用服务器发送事件 (SSE) 进行流式传输

对于产生增量结果(如生成长文档或流媒体)或提供持续状态更新的任务,A2A 支持使用服务器发送事件 (Server-Sent Events, SSE) 进行实时通信。当客户端能够与 A2A 服务器保持活跃的 HTTP 连接时,这种方法是理想的。

以下关键特性详细说明了如何在 A2A 协议中实现和管理 SSE 流式传输:

  • 服务器能力:A2A 服务器必须通过在其智能体卡片中设置 capabilities.streaming: true 来表明其支持流式传输。

  • 启动流 :客户端使用 SendStreamingMessage RPC 方法发送启动消息(例如,提示词或命令),并同时订阅该任务的更新。

  • 服务器响应与连接:如果订阅成功,服务器返回 HTTP 200 OK 状态和 Content-Type: text/event-stream 的响应。此 HTTP 连接保持打开状态,以便服务器向客户端推送事件。

  • 事件结构与类型:服务器通过此流发送事件。每个事件的 data 字段包含一个 JSON-RPC 2.0 响应对象,通常是 SendStreamingMessageResponseSendStreamingMessageResponse 的 result 字段包含:

    • Task:代表工作的当前状态。

    • TaskStatusUpdateEvent:通报任务生命周期状态的变更(例如,从 working 到 input-required 或 completed)。它还提供来自智能体的中间消息。

    • TaskArtifactUpdateEvent:交付任务生成的新的或更新的工件。这用于分块流式传输大文件或数据结构,带有 append 和 lastChunk 等字段以帮助重组。

  • 流终止 :当任务达到终结或中断状态(例如 COMPLETED [完成]、FAILED [失败]、CANCELED [取消]、REJECTED [拒绝] 或 INPUT_REQUIRED [需输入])时,服务器关闭流并不再发送更新。

  • 重新订阅 :如果客户端的 SSE 连接在任务仍然活跃时过早断开,客户端可以使用 SubscribeToTask RPC 方法尝试重新连接到流。

何时使用流式传输

SSE 流式传输最适合于:

  • 长运行任务的实时进度监控。

  • 增量接收大型结果(工件)。

  • 交互式、对话式交流中,即时反馈或部分响应更好。

  • 要求来自智能体的更新低延迟的应用。

针对断开连接场景的推送通知

针对非常耗时的任务(例如持续数分钟、数小时甚至数天)或当客户端无法或不愿维持持久连接时(如移动客户端或无服务器函数),A2A 支持使用推送通知进行异步更新。这允许 A2A 服务器在发生重大任务更新时主动通知客户端提供的 Webhook。

以下关键特性详细说明了如何在 A2A 协议中实现和管理推送通知:

  • 服务器能力:A2A 服务器必须通过在其智能体卡片中设置 capabilities.pushNotifications: true 来表明其支持此功能。

  • 配置 :客户端向服务器提供 PushNotificationConfig。此配置通过以下方式提供:

    • 在初始 SendMessage 或 SendStreamingMessage 请求中,或者

    • 针对现有任务单独使用 CreateTaskPushNotificationConfig RPC 方法。PushNotificationConfig 包含 url(HTTPS Webhook URL),可选的 token(用于客户端验证),以及可选的 authentication 细节(用于 A2A 服务器向 Webhook 进行身份验证)。

  • 触发通知:A2A 服务器决定何时发送推送通知,通常是在任务达到重大状态变更时(例如终结状态、input-required 或 auth-required)。

  • 通知的载荷 :A2A 协议将 HTTP 消息体载荷定义为 StreamResponse 对象,与流式操作中使用的格式匹配。载荷包含以下之一:taskmessagestatusUpdate, 或 artifactUpdate

  • 客户端操作:收到推送通知(并成功验证其真实性)后,客户端通常使用通知中的 taskId 调用 GetTask RPC 方法来获取完整的、更新后的 Task 对象,包括任何新的工件。

何时使用推送通知

推送通知最适合于:

  • 可能需要数分钟、数小时或数天才能完成的非常长运行的任务。

  • 无法或不愿维持持久连接的客户端,如移动应用程序或无服务器函数。

  • 客户端仅需在发生重大状态变更时被通知,而无需连续更新通知的场景。

客户端侧推送通知服务

PushNotificationConfig.url 中指定的 url 指向客户端侧的推送通知服务。该服务负责接收来自 A2A 服务器的 HTTP POST 通知。其职责包括验证传入通知的身份、验证其相关性,并将通知或其内容中继给适当的客户端逻辑或系统。

推送通知的安全考量

由于推送通知具有异步和服务器发起的出站性质,安全性至关重要。A2A 服务器(发送通知)和客户端的 Webhook 接收端都负有关键责任。

A2A 服务器安全性(向客户端 Webhook 发送通知时)

  • Webhook URL 验证:服务器 不应  盲目信任并向客户端提供的任何 URL 发送 POST 请求。恶意客户端可能会提供指向内部服务或无关第三方系统的 URL,导致服务端请求伪造 (SSRF) 攻击或充当分布式拒绝服务 (DDoS) 放大器。

    • 缓解策略:受信任域白名单,所有权验证(例如挑战-响应机制),以及网络控制(例如出口防火墙)。

  • 向客户端 Webhook 进行身份验证:A2A 服务器 必须 根据 PushNotificationConfig.authentication 中指定的方案向客户端 Webhook URL 验证自身身份。常见方案包括 Bearer Tokens (OAuth 2.0), API keys, HMAC 签名, 或双向 TLS (mTLS)。

客户端 Webhook 接收端安全性(接收来自 A2A 服务器的通知时)

  • 验证 A2A 服务器:Webhook 端点 必须 严格验证传入通知请求的真实性,以确保源自合法的 A2A 服务器而非冒充者。

    • 验证方法:验证签名/令牌(例如针对 A2A 服务器受信任公钥的 JWT 签名、HMAC 签名或 API key 验证)。此外,如果提供了 PushNotificationConfig.token,也要对其进行验证。

  • 防止重放攻击

    • 时间戳:通知 应该 包含时间戳。Webhook 应该 拒绝过旧的通知。

    • 一次性随机值 / 唯一 ID:对于关键通知,考虑使用唯一的、一次性标识符(例如 JWT 的 jti 声明或事件 ID)以防止处理重复通知。

  • 安全密钥管理与轮换:实施安全的密钥管理策略,包括定期轮换密钥,特别是对于加密密钥。像 JWKS (JSON Web Key Set) 这样的协议有助于非对称密钥的轮换。

非对称密钥流程示例 (JWT + JWKS)

  1. 客户端创建 PushNotificationConfig,指定 authentication.scheme: "Bearer" ,并可设置 JWT 的预期签发者( issuer )或受众( audience)。

  2. A2A 服务器在发送通知时:

    1. 生成一个 JWT,并用其私钥签名。JWT 包含如 iss (issuer 签发者), aud (audience 受众), iat ( issued at 签发时间), exp (expires 过期时间), jti (JWT ID), 和 taskId 等声明。

    2. JWT 头部指示签名算法和 key ID (kid)。

    3. A2A 服务器通过 JWKS 端点使其公钥可用。

  3. 客户端 Webhook 在收到通知时:

    1. 从 Authorization 头部提取 JWT。

    2. 检查 JWT 头部中的 kid (key ID 密钥 ID)。

    3. 从 A2A 服务器的 JWKS 端点获取相应的公钥(建议缓存密钥)。

    4. 使用公钥验证 JWT 签名。

    5. 验证声明 (issaudiatexpjti)。

    6. 如果提供了 PushNotificationConfig.token,则进行检查。

这种针对推送通知的全面、分层的安全方法有助于确保消息是真实的、完整的且及时的,从而保护发送方 A2A 服务器和接收方客户端 Webhook 基础设施。

A2A 与 MCP:详细对比

在 AI 智能体开发中,出现了两种关键的协议类型来促进互操作性。一种将智能体连接到工具和资源。另一种赋能智能体之间的协作。Agent2Agent (A2A) 协议模型上下文协议 (Model Context Protocol, MCP) 满足了这两种截然不同却高度互补的需求。

模型上下文协议 (Model Context Protocol, MCP)

模型上下文协议 (MCP) 定义了 AI 智能体如何与工具和资源(例如数据库或 API)进行交互。

该协议提供以下能力:

  • 标准化(AI 模型、智能体)与(工具、API 和其他外部资源)连接和交互的方式。

  • 定义一种结构化的方式来描述工具能力,类似于大语言模型中的函数调用 (function calling)。

  • 向工具传递输入并接收结构化输出。

  • 支持常见用例,例如 LLM 调用外部 API、智能体查询数据库或智能体连接到预定义的函数。

Agent2Agent 协议 (A2A)

Agent2Agent 协议专注于赋能不同的智能体相互协作以实现共同目标。

该协议提供以下能力:

  • 标准化独立的、内部逻辑通常不透明的 AI 智能体以对等身份进行通信与协作。

  • 提供应用层协议,用于智能体相互发现、协商交互、管理共享任务以及交换对话上下文和复杂数据。

  • 支持典型场景,例如客服智能体将查询转交给计费智能体,或旅行智能体与机票、酒店和活动智能体进行协调。

为何需要两类不同的协议?

MCP 和 A2A 协议对于构建复杂的 AI 系统都是必不可少的,二者解决的问题不同,却高度互补。区分 A2A 与 MCP 的关键,在于智能体的交互对象。

工具和资源 (MCP 领域):

  • 特征:这些通常是具有明确定义的、结构化输入和输出的基础组件 (primitives)。它们执行特定的、通常是无状态的功能。例如计算器、数据库查询 API 或天气查询服务。

  • 目的:智能体使用工具来收集信息并执行离散功能。

智能体 (A2A 领域):

  • 特征:这些是更自主的系统。它们推理、规划、使用多种工具、在较长时间的交互中维护状态,并进行复杂的、通常是多轮的对话以实现新颖或不断变化的任务。

  • 目的:智能体之间相互协作,以解决更广泛、更复杂的目标。

A2A & MCP:智能体系统的互补协议

一个智能体应用可能主要使用 A2A 与其他智能体通信。每个单独的智能体内部使用 MCP 与其特定的工具和资源交互。

场景示例:汽车修理店

设想一家由自主 AI 智能体 “机械师” 运营的汽车维修店。这些机械师使用专用工具(车辆诊断仪、维修手册、升降台)排查故障、维修车辆。维修过程可能涉及大量沟通、信息查询,以及与配件供应商的交互。

  1. 客户交互(用户→智能体,基于 A2A):客户(或其主助理智能体)通过 A2A 与 “店长” 智能体沟通。

    1. 例如,客户可能会说:“我的车有咔哒咔哒的异响”。

  2. 多轮诊断对话(智能体→智能体,基于 A2A):“店长”智能体使用 A2A 进行多轮诊断对话。

    1. 例如,店长可能会问:“你能发一段噪音的视频吗?”或者“我看到有液体渗漏,这种情况出现多久了?”

  3. 内部工具调用(智能体→工具,基于 MCP):“机械师”智能体,被“店长”分配任务,需要诊断问题。“机械师”智能体使用 MCP 与其专用工具进行交互。

    • raise_platform(height_meters=2)

    • get_repair_procedure(error_code='P0300', vehicle_make='Toyota', vehicle_model='Camry')

    • scan_vehicle_for_error_codes(vehicle_id='XYZ123')

    • 对“车辆诊断扫描仪”工具的 MCP 调用:

    • 对“维修手册数据库”工具的 MCP 调用:

    • 对“升降台”工具的 MCP 调用:

    1.   例如:

  4. 供应商交互(智能体→智能体,基于 A2A):“机械师”智能体确定需要的零件。“机械师”智能体使用 A2A 与“零部件供应商”智能体通信以订购零件。例如,“机械师”智能体可能会问:“你们有 2018 款丰田凯美瑞的零件 #12345 库存吗?”

  5. 订单处理(智能体→智能体,基于 A2A):“零部件供应商”智能体(也是一个符合 A2A 标准的系统)进行回复,后续完成订单。

在此示例中:

  • A2A 方便了客户与修理店之间、以及修理店智能体与外部供应商智能体之间的高层级、对话式和面向任务的交互。

  • MCP 使机械师智能体能够使用其特定的、结构化的工具来执行诊断和维修功能。

一个 A2A 服务器可以将其部分技能作为 MCP 兼容资源公开。然而,A2A 的主要优势在于支持更灵活、有状态和协作性交互。这些交互超越了典型的工具调用。A2A 专注于智能体在任务上的合作,而 MCP 专注于智能体对能力的使用。

将 A2A 智能体表示为 MCP 资源

一个 A2A 服务器(远程智能体)可以将其部分技能作为 MCP 兼容的资源公开,特别是如果这些技能定义明确且可以以更像工具的、无状态的方式调用。在这种情况下,另一个智能体可能会通过 MCP 风格的工具描述(可能源自其智能体卡片)“发现”该 A2A 智能体的特定技能。

然而,A2A 的主要优势在于支持更灵活、有状态和协作性的交互,这些交互超越了典型的工具调用。A2A 关乎智能体在任务上的合作 (partnering),而 MCP 更关乎智能体对能力的使用 (using)

通过利用 A2A 进行智能体间协作,并利用 MCP 进行工具集成,开发者可以构建更强大、更灵活且具备互操作性的 AI 系统。

本站文章均为手工撰写未经允许谢绝转载:夜雨聆风 » A2A协议文档

评论 抢沙发

5 + 2 =
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
×
订阅图标按钮