A2A 生产就绪检查:测试、观测与回滚

A2A 生产就绪检查:测试、观测与回滚

一个服务能成功响应一次 A2A 请求,并不代表它已经适合生产环境。公开 Agent Card 可能与实际部署的端点发生偏移;通过认证的调用方仍可能读到别人的任务;流式连接中断后可能没有恢复路径;Webhook 能力也可能变成 SSRF 入口。

本指南把这些风险转化为一次明确的发布判断。它假设服务端已经实现 A2A v1.0.1。构建和校验卡片请使用 Agent Card 实现指南 ,校验任务轨迹请使用 Task 运行时指南 。这里要完成的是另一件事:证明已部署系统、公开契约和恢复控制彼此一致。

发布判定

不要用一次健康检查代替生产就绪判断。下面每个适用的门禁,都应保留一份可复现证据。

门禁应保留的证据阻止发布的情况
发现公开卡片 URL、响应头、卡片摘要和校验输出卡片不可访问、无效,或指向不同的版本、绑定、端点
传输每个生产接口的 TLS 结果生产 HTTP 绑定使用明文,或证书校验失败
认证正常凭据,以及缺失、无效、过期凭据的测试受保护端点接受错误凭据,或挑战响应不正确
授权跨用户、跨租户的任务读取、取消、订阅及推送配置测试调用方能推断或访问权限边界外的任务
任务生命周期直接完成、中断、失败、取消和重试行为的轨迹状态转换或终态行为与协议、产品契约不一致
流式传输初始结果、有序更新、终态事件、断连和重新订阅证据卡片声明支持流式传输,但重连不能安全恢复
推送通知URL 校验、出站认证、重复投递和重放测试可以访问私有或链路本地地址,或重复投递破坏状态
可观测性可关联的请求、任务、上下文、追踪标识,以及指标和脱敏日志运维人员无法解释失败任务,或排查依赖凭据、消息正文
过载与恢复超时、限流、依赖故障和重启测试负载导致工作无界增长、已接收状态丢失或重试失控
回滚上一版本制品/配置标识,以及演练过的能力下线顺序无法撤销故障能力,或回滚后 Agent Card 仍在做错误声明

协议定义的是互操作与安全要求,不会替你的部署做认证。检查通过只是你自己的发布证据,不是“A2A 官方认证”。

1. 执行公开发现预检

请从生产网络之外执行下面的脚本。它检查的是公开响应,而不是构建目录中的本地文件。脚本依赖 curl 和 jq。

#!/usr/bin/env bash
set -euo pipefail

: "${A2A_CARD_URL:?Set A2A_CARD_URL to the public Agent Card URL}"

case "$A2A_CARD_URL" in
  https://*) ;;
  *) printf 'ERROR: production Agent Card URL must use HTTPS\n' >&2; exit 1 ;;
esac

work_dir="$(mktemp -d)"
cleanup() { rm -rf "$work_dir"; }
trap cleanup EXIT HUP INT TERM

status="$({ curl --silent --show-error --location \
  --proto '=https' --tlsv1.2 \
  --connect-timeout 5 --max-time 15 \
  --dump-header "$work_dir/headers" \
  --output "$work_dir/card.json" \
  --write-out '%{http_code}' \
  "$A2A_CARD_URL"; } 2>"$work_dir/curl.error")" || {
    cat "$work_dir/curl.error" >&2
    exit 1
  }

if [[ "$status" != "200" ]]; then
  printf 'ERROR: Agent Card returned HTTP %s\n' "$status" >&2
  exit 1
fi

content_type="$(tr -d '\r' < "$work_dir/headers" \
  | awk -F ': *' 'tolower($1) == "content-type" {print tolower($2)}' \
  | tail -n 1)"
case "$content_type" in
  application/json*) ;;
  *) printf 'ERROR: expected application/json, got %s\n' "${content_type:-missing}" >&2; exit 1 ;;
esac

jq -e '
  type == "object"
  and ([.name, .description, .version] | all(type == "string" and length > 0))
  and (.supportedInterfaces | type == "array" and length > 0)
  and (.skills | type == "array" and length > 0)
  and all(.supportedInterfaces[];
    (.protocolBinding == "GRPC" and (.url | test("^([^/:]+|\\[[0-9A-Fa-f:]+\\]):[0-9]+$")))
    or (.protocolBinding != "GRPC" and (.url | startswith("https://"))))
  and ((.securitySchemes // {}) as $schemes
    | [(.securityRequirements // [])[]?.schemes? | keys[]] as $refs
    | ($refs | all(. as $name | $schemes | has($name))))
' "$work_dir/card.json" >/dev/null

digest="$(shasum -a 256 "$work_dir/card.json" | awk '{print $1}')"
printf 'OK: HTTP 200, JSON contract and production interfaces passed\n'
printf 'card_sha256=%s\n' "$digest"
jq -r '.supportedInterfaces[] | "interface=\(.protocolBinding) \(.protocolVersion) \(.url)"' \
  "$work_dir/card.json"

调用示例:

A2A_CARD_URL='https://agent.example/.well-known/agent-card.json' \
  bash production-preflight.sh

脚本检查可访问性、仅用 TLS 获取、媒体类型、卡片基本结构、生产接口地址,以及卡片级安全要求对安全方案的引用。它不能证明端点真正实现了声明的操作,也不会验证密码学签名。还要运行 Agent Card 指南里的完整校验器,并把输出与本次预检结果放在一起。

把卡片摘要和部署标识一起记录。如果同一个发布版本后来返回了不同摘要,即使两份卡片分别都合法,也已经发生配置漂移。

2. 证明认证与隔离有效

对公开的每一种绑定都执行测试,不要只经过内部 SDK。对于受保护端点,至少保留下列请求及状态:

场景预期结果
未提供凭据按未认证拒绝;HTTP 通常返回 401,并带恰当的 WWW-Authenticate 挑战
凭据格式错误、已过期或 audience 错误按未认证拒绝,并且不执行智能体工作
身份有效但缺少所需权限按禁止访问拒绝;HTTP 通常返回 403
身份有效且具有所需权限接受请求,并把行为归属到该身份

认证只是第一道边界。先由调用方 A 创建任务,再让调用方 B 尝试 GetTask、ListTasks、CancelTask、SubscribeToTask,以及管理任务的推送通知配置。使用 AgentInterface.tenant 时,再跨租户执行同一组测试。拒绝响应不应通过响应文本、耗时或分页数量暴露隐藏任务是否存在。

A2A 安全规范要求任务结果和操作都限制在调用方的授权边界内。协议有意把授权模型留给实现,因此发布证据必须注明每次结果对应的身份、租户、权限范围和策略版本。详见认证、授权与安全注意事项 。

3. 逐项验证声明的能力

Agent Card 是对外运行契约。每项能力都要覆盖支持路径和不支持路径:

声明正向测试负向或恢复测试
streaming: true收到初始 Task 或 Message、有序更新和终态结果在任务中途断开,再用 SubscribeToTask 连接,证明终态不会静默丢失
streaming: false 或缺省普通非流式请求正常流式操作返回 UnsupportedOperationError
pushNotifications: true创建、读取、列出、删除配置,并收到通过认证的通知拒绝不安全目的地址;制造重复投递并证明幂等处理
pushNotifications: false 或缺省任务处理仍然正常四个配置操作都返回 PushNotificationNotSupportedError
extendedAgentCard: true已授权调用方取得配置好的扩展卡片缺少凭据、权限不足时拒绝,并且不泄露卡片
必需扩展声明支持扩展的客户端能完成操作未声明支持的客户端收到 ExtensionSupportRequiredError

把采集的任务与流式事件交给 Task 运行时指南 中的校验器。至少保留完成、失败、取消三种任务轨迹;产品包含 INPUT_REQUIRED、AUTH_REQUIRED 路径时,也要分别保留。

处理推送通知时,每次重定向之后、真正连接之前都要重新解析并校验目的地址。在应用层和网络出口同时阻止回环、私有、链路本地及其他不允许的地址。对出站调用做认证,对入站调用做验证,并以幂等方式处理重复通知。完整的责任边界见流式传输与异步操作 。

4. 让故障可以解释

一个生产任务会经过多种标识。日志要能关联各层,但不能记录秘密或完整消息正文:

timestamp, release_id, protocol_version, binding, operation,
request_id, trace_id, task_id, context_id, tenant_id,
caller_subject_hash, outcome, protocol_error, duration_ms

边缘代理与 A2A 服务使用一致的字段名。默认脱敏授权头、Cookie、Webhook 凭据、文件内容、Part、Artifact 和自由文本消息。任务 ID 只适合关联,不是授权证明。

至少监控请求量、延迟、协议错误、任务终态、中断任务、活跃流连接、重连次数、Webhook 投递与重试时长、依赖故障、被拒绝的不安全地址。告警应针对用户影响和停滞工作,而不是每个单独失败。

5. 测试过载、重启与重试边界

使用有明确上限的压力测试,并包含慢依赖和长任务。放量前逐项确认:

  1. 新工作在既定上限处被拒绝或排队;内存和线程/协程数量不会无界增长;
  2. 客户端超时不会自动取消服务端工作,除非产品明确实现并约定了该行为;
  3. 进程重启后,已接收任务会按照产品契约保留,或以明确结果失败;
  4. 对超时请求的重试不会制造失控的重复副作用;业务操作需要 exactly-once 效果时,要由应用定义幂等策略,A2A 不会替业务行为自动提供这一保证;
  5. 下游依赖故障会形成有界协议错误或可恢复任务状态,而不是永远停在 WORKING。

保留负载模型、发布标识、限制参数和结果。“端点返回了 200”不能作为这一门禁的充分证据。

6. 准备不破坏能力契约的回滚

回滚顺序很重要。如果接口已经撤销,公开卡片却仍声明对应能力,遵循协议的客户端就会继续调用不存在的路径。

单项能力发生故障时:

  1. 在流量或功能开关处阻止新请求使用该能力;
  2. 发布不再声明该能力或受影响接口的 Agent Card;
  3. 遵守卡片的缓存行为,为发现缓存留出刷新时间;
  4. 排空在途工作,或以明确结果终止;
  5. 回滚服务制品或配置;
  6. 重新执行公开预检和受影响的负向测试。

完整版本回滚时,把上一版服务制品、配置标识、Agent Card、数据库兼容性决策和回滚负责人放在一起。某个部署步骤的远端结果未知时,不要自动重试;先回读已部署身份和当前卡片摘要。

故障到行动的映射

观察结果更可能出问题的边界第一行动
卡片在本地校验通过,但公开摘要不同CDN、部署配置或旧源站不依赖本地文件重新获取,检查缓存头,并比较部署版本标识
有效令牌收到 401认证配置先检查 issuer、audience、时间和绑定对应的凭据传输,再调整授权
调用方 B 可以看到 A 的任务授权/数据查询冻结发布;在返回存在性或内容之前先按调用方范围查询
流结束在 SUBMITTED 或 WORKING连接或服务端故障使用 SubscribeToTask 或 GetTask,不能假设任务已完成或失败
推送只对内部地址可用测试设计不安全或存在 SSRF 暴露关闭推送配置创建,落实公开地址策略与出口控制,再测重定向和 DNS 变化
代码已回滚,但客户端仍调用已移除操作发现契约漂移修正公开 Agent Card,并等待它声明的缓存窗口结束

证据清单

随发布保留一份小型清单,不要把证据散落在聊天截图中:

release_id: "git-sha-or-artifact-digest"
protocol_version: "1.0"
tested_at: "2026-10-25T12:00:00Z"
agent_card_url: "https://agent.example/.well-known/agent-card.json"
agent_card_sha256: "..."
bindings: ["HTTP+JSON"]
capabilities: ["streaming"]
checks:
  discovery: pass
  authentication: pass
  authorization_isolation: pass
  task_lifecycle: pass
  streaming_recovery: pass
  push_security: not_applicable
  overload_restart: pass
rollback_artifact: "previous-release-id"
owner: "team-or-role"

清单只是索引,不是证据本身。把它链接到机器可读测试结果和脱敏轨迹,与发布版本一起保存。只要 Agent Card、认证策略、协议绑定、能力开关、存储模型或边缘路由发生变化,就重新执行受影响的门禁。

来源:A2A v1.0.1 规范 、A2A 认证、授权与安全注意事项 、A2A 智能体发现 与A2A 企业级特性 。