用于长时间运行任务的流式传输和异步操作¶
Agent2Agent (A2A) 协议明确设计用于处理可能不会立即完成的任务。许多人工智能驱动的操作通常运行时间长、涉及多个步骤、产生增量结果或需要人工干预。A2A 提供了管理此类异步交互的机制,确保客户端能够有效地接收更新,无论它们是持续连接还是以更离线的方式操作。
使用服务器发送事件 (SSE) 进行流式传输¶
对于产生增量结果(如生成长文档或流式媒体)或提供持续状态更新的任务,A2A 支持使用服务器发送事件 (SSE) 进行实时通信。当客户端能够与 A2A 服务器保持活动 HTTP 连接时,此方法是理想的选择。
以下关键特性详细说明了 SSE 流式传输如何在 A2A 协议中实现和管理
-
服务器能力: A2A 服务器必须通过在其 Agent Card 中设置
capabilities.streaming: true来表明其支持流式传输。 -
启动流: 客户端使用
message/streamRPC 方法发送初始消息(例如,提示或命令),并同时订阅该任务的更新。 -
服务器响应和连接: 如果订阅成功,服务器将响应 HTTP 200 OK 状态和
Content-Type: text/event-stream。此 HTTP 连接保持打开状态,以便服务器将事件推送到客户端。 -
事件结构和类型: 服务器通过此流发送事件。每个事件的
data字段都包含一个 JSON-RPC 2.0 响应对象,通常是SendStreamingMessageResponse。SendStreamingMessageResponse的result字段包含任务:表示工作的当前状态。TaskStatusUpdateEvent:传达任务生命周期状态的变化(例如,从working到input-required或completed)。它还提供来自代理的中间消息。TaskArtifactUpdateEvent:交付任务生成的新或更新的 Artifact。这用于分块流式传输大文件或数据结构,其中包含append和lastChunk等字段以帮助重新组装。
-
流终止: 服务器通过在
TaskStatusUpdateEvent中设置final: true来表示一个周期的更新结束。这通常发生在任务达到最终状态时。此后,服务器通常会关闭 SSE 连接。 -
重新订阅: 如果客户端的 SSE 连接在任务仍然处于活动状态时过早中断,客户端可以尝试使用
tasks/resubscribeRPC 方法重新连接到流。
何时使用流式传输¶
使用 SSE 进行流式传输最适合以下情况
- 长时间运行任务的实时进度监控。
- 增量接收大型结果(工件)。
- 交互式、对话式交流,其中即时反馈或部分响应是有益的。
- 需要从代理获取低延迟更新的应用程序。
协议规范参考¶
有关详细结构,请参阅协议规范
针对离线场景的推送通知¶
对于长时间运行的任务(例如,持续数分钟、数小时甚至数天)或当客户端无法或不愿保持持久连接(如移动客户端或无服务器函数)时,A2A 支持使用推送通知进行异步更新。这允许 A2A 服务器在发生重大任务更新时主动通知客户端提供的 webhook。
以下关键特性详细说明了推送通知如何在 A2A 协议中实现和管理
- 服务器能力: A2A 服务器必须通过在其 Agent Card 中设置
capabilities.pushNotifications: true来表明其支持此功能。 - 配置: 客户端向服务器提供
PushNotificationConfig。此配置在以下情况下提供- 在初始的
message/send或message/stream请求中,或 - 单独使用
tasks/pushNotificationConfig/setRPC 方法用于现有任务。PushNotificationConfig包括一个url(HTTPS webhook URL)、一个可选的token(用于客户端验证)和可选的authentication详细信息(用于 A2A 服务器向 webhook 进行身份验证)。
- 在初始的
- 通知触发: A2A 服务器决定何时发送推送通知,通常在任务达到重大状态变化时(例如,终止状态、
input-required或auth-required)。 - 通知负载: A2A 协议将 HTTP 正文负载定义为
StreamResponse对象,与流式操作中使用的格式匹配。负载包含以下之一:task、message、statusUpdate或artifactUpdate。有关详细结构,请参阅 推送通知负载。 - 客户端操作: 收到推送通知(并成功验证其真实性)后,客户端通常使用
tasks/getRPC 方法和通知中的taskId来检索完整的、已更新的Task对象,包括任何新工件。
何时使用推送通知¶
推送通知最适合以下情况
- 需要数分钟、数小时或数天才能完成的长时间运行任务。
- 无法或不愿保持持久连接的客户端,例如移动应用程序或无服务器函数。
- 客户端只需要收到重大状态更改通知,而不是持续更新的场景。
协议规范参考¶
有关详细结构,请参阅协议规范
客户端推送通知服务¶
PushNotificationConfig.url 中指定的 url 指向客户端推送通知服务。此服务负责接收来自 A2A 服务器的 HTTP POST 通知。其职责包括验证传入通知的真实性、验证其相关性,并将通知或其内容转发到相应的客户端应用程序逻辑或系统。
推送通知的安全注意事项¶
由于推送通知的异步性和服务器发起的出站性质,安全性至关重要。A2A 服务器(发送通知)和客户端的 webhook 接收器都负有关键责任。
A2A 服务器安全性(向客户端 webhook 发送通知时)¶
- Webhook URL 验证: 服务器不应盲目信任并向客户端提供的任何 URL 发送 POST 请求。恶意客户端可能会提供指向内部服务或不相关第三方系统的 URL,从而导致服务器端请求伪造 (SSRF) 攻击或充当分布式拒绝服务 (DDoS) 放大器。
- 缓解策略: 允许受信任域的白名单、所有权验证(例如,质询-响应机制)和网络控制(例如,出站防火墙)。
- 向客户端 Webhook 进行身份验证: A2A 服务器必须根据
PushNotificationConfig.authentication中指定的方案向客户端的 webhook URL 进行身份验证。常见方案包括不记名令牌 (OAuth 2.0)、API 密钥、HMAC 签名或相互 TLS (mTLS)。
客户端 Webhook 接收器安全性(从 A2A 服务器接收通知时)¶
- 验证 A2A 服务器: webhook 端点必须严格验证传入通知请求的真实性,以确保它们源自合法的 A2A 服务器,而不是冒名顶替者。
- 验证方法: 验证签名/令牌(例如,针对 A2A 服务器的受信任公钥的 JWT 签名、HMAC 签名或 API 密钥验证)。此外,如果提供了
PushNotificationConfig.token,也请对其进行验证。
- 验证方法: 验证签名/令牌(例如,针对 A2A 服务器的受信任公钥的 JWT 签名、HMAC 签名或 API 密钥验证)。此外,如果提供了
- 防止重放攻击
- 时间戳: 通知应包含时间戳。webhook 应拒绝过期的通知。
- 随机数/唯一 ID: 对于关键通知,请考虑使用唯一的、一次性使用的标识符(例如,JWT 的
jti声明或事件 ID)以防止处理重复通知。
- 安全密钥管理和轮换: 实施安全的密钥管理实践,包括定期密钥轮换,特别是对于加密密钥。JWKS(JSON Web Key Set)等协议有助于非对称密钥的密钥轮换。
非对称密钥流示例 (JWT + JWKS)¶
- 客户端设置
PushNotificationConfig,指定authentication.schemes: ["Bearer"],并可能为 JWT 指定预期的issuer或audience。 - A2A 服务器在发送通知时
- 生成一个 JWT,并使用其私钥进行签名。JWT 包含
iss(颁发者)、aud(受众)、iat(颁发时间)、exp(过期时间)、jti(JWT ID)和taskId等声明。 - JWT 标头指示签名算法和密钥 ID (
kid)。 - A2A 服务器通过 JWKS 端点提供其公钥。
- 生成一个 JWT,并使用其私钥进行签名。JWT 包含
- 客户端 Webhook 在收到通知后
- 从 Authorization 标头中提取 JWT。
- 检查 JWT 标头中的
kid(密钥 ID)。 - 从 A2A 服务器的 JWKS 端点获取相应的公钥(建议缓存密钥)。
- 使用公钥验证 JWT 签名。
- 验证声明 (
iss,aud,iat,exp,jti)。 - 检查
PushNotificationConfig.token(如果提供)。
这种全面、分层的推送通知安全方法有助于确保消息的真实性、完整性和及时性,保护发送 A2A 服务器和接收客户端 webhook 基础设施。