A2A 是什么,不是什么

A2A 是 Agent-to-Agent 的缩写,为一个 Agent 服务请求另一个 Agent 服务完成工作提供互操作词汇。Google 在 2025 年公开宣布了这一协议,之后它在开放生态中持续演进。应将规范版本、Transport Binding、SDK 和治理位置视为部署依赖,而不是永恒事实。

A2A 可以帮助实现:

  • 通过 Agent Card 发现能力;
  • 结构化 Message 和 Artifact;
  • 短任务或长任务的生命周期;
  • 状态更新,以及版本支持时的 Streaming 或 Push Delivery;
  • 在独立运营的 Agent 服务间进行委派。

不能提供业务授权、Tenant 隔离、可信目录、安全 Tool 执行、准确模型输出或只发生一次的副作用。这些仍是应用职责。

先确定边界,再选择协议

如果工作由同一服务拥有且契约很窄、可确定,优先使用 Local Function。只有远程服务具有独立生命周期、Policy 或能力边界时,才考虑 A2A。

问题 合理答案
谁拥有 Task State? 一个有持久存储和 Retention Policy 的明确服务。
谁认证 Caller? 远程服务,使用可信身份机制。
谁授权数据和副作用? 拥有对象和动作的服务。
Retry Identity 是什么? 应用生成的 Idempotency Key,而不是模型语句。
断连时发生什么? 明确 Polling、Callback、Resume 或 Cancellation 契约。
保留什么证据? 脱敏的生命周期 Event、Policy Decision、Artifact Reference 和 Error Class。

不要只是为了让线性 Workflow 看起来“自治”而引入 Agent 协议。

A2A 与 MCP

两个协议面对不同边界,但“A2A 是 Agent-to-Agent、MCP 是 Agent-to-Tool”的口号并不完整。

边界 常见目的 协议外仍需完成
A2A 向远程 Agent 服务委派 Task 服务身份、Task/Object 授权、Budget
MCP 为 AI 应用暴露 Tool、Resource、Prompt User 身份、Object 授权、副作用 Policy
Application Workflow 协调本地与远程工作 Approval、补偿、Audit、业务 Invariant

A2A Delegate 可以在内部使用 MCP;MCP Host 也可以不使用 A2A 而调用远程服务。两种安排都不会授予模型读取对象或执行外部写入的权限。

固定规范表面

实现前记录已测试的精确输入:

json
{
  "a2a_specification": "pinned-release-or-commit",
  "transport_binding": "pinned-profile",
  "agent_card_location": "deployment-defined",
  "sdk": "package-and-version",
  "authentication": "deployment-specific",
  "task_retention": "policy-reference",
  "artifact_store": "approved-store",
  "checked_at": "recorded-time"
}

Agent Card Schema、发现位置、Transport、Streaming 行为和 SDK API 都可能变化。应根据固定规范和运行中的 Endpoint 核对,不能直接把博客里的 Package Name 复制到生产环境。

Agent Card 是发现 Metadata

Agent Card 可能描述服务名称、Endpoint、Skill、输入输出 Mode 和 Capability。它适合 Routing,但在系统验证来源前均不可信。

需要验证:

  1. Transport Endpoint 是否来自 Allowlist 或可信 Registry;
  2. 使用 Token 时的服务身份、Issuer、Audience、Expiry 和 Key Rotation;
  3. Card Schema 与 Version;
  4. Requested Skill 是否被本地 Policy 允许;
  5. 每个 Task 的 Caller、Tenant 和 Target Object;
  6. Result Size、Artifact Type 与 Callback Destination。

Description、Skill Name、URL 和 Example 都可能包含 Prompt Injection 或误导声明。不能将 Card Text 变成可执行 Policy、自动安装或 Tool Permission。

Task 生命周期是状态机

规范使用 Task 和 Status 概念。具体状态名称和合法迁移依赖版本;生产服务应在固定协议外定义自己的持久化状态机。

text
accepted -> running -> waiting_for_input -> running -> terminal
                         |                         |
                         +-> canceled              +-> succeeded | failed | rejected

同时记录 Protocol-facing Status 与 Application Status。Terminal Response 应区分:被 Policy 拒绝、作用前失败、作用结果不确定,或带证据完成。

幂等与取消

Retry、重复 Message、Timeout 和 Callback 都是分布式系统的常见行为。对于会产生副作用的 Task:

  • 将 Idempotency Key 绑定 Principal、Tenant、Action 与规范化参数;
  • 执行副作用前持久化 Decision;
  • 让 Cancellation 可协作且感知 State;
  • 无法证明副作用时返回“结果不确定”;
  • 仅在业务操作支持时使用 Compensation。

不能将模型拒答或 completed 标签视为付款、删除或通知只执行一次的证据。

Message、Artifact 与不可信内容

Message Part 和 Artifact 可以承载 Text、Structured Data、File、Reference 或 URL。包括其他 Agent 输出的内容在内,都应视为不可信输入。

限制:

  • Byte、Item Count、Nesting Depth 和 Decompression;
  • MIME Allowlist 与 Parser 行为;
  • Artifact Storage Location、Expiry、Access Scope 和 Deletion;
  • Outbound Fetch Destination 与 Redirect Count;
  • Telemetry Field 与原始 Payload 留存。

比起将大量敏感内容嵌入 Task Message,更适合使用经过认证访问的 Reference Artifact。File Reference 不是访问许可,Retrieval 时仍须验证。

Streaming 与 Push Delivery

Streaming 和异步通知是传递选择,并不代替 Task Durability。无论版本/Binding 使用 Server-Sent Events、Callback、Polling 或其他机制,都应定义:

  • Reconnect 与 Resume;
  • Event Ordering 与 Deduplication;
  • Token Expiry 与重新认证;
  • Callback 注册与 Destination Allowlist;
  • Timeout、Backpressure 与 Result Size Budget;
  • 谁可以观察或取消 Task。

Callback URL 是 SSRF 边界。验证 Destination Ownership,不能让模型或远程 Agent 选择无限制 Callback Target。

授权逐 Task、逐对象执行

OAuth、Bearer Token、mTLS、Workload Identity、RBAC 和 ABAC 都是可能的部署控制。它们并不都是 A2A 的必选功能;已经认证的 Caller 也不自动拥有全部 Skill 权限。

python
from dataclasses import dataclass
from enum import Enum
from typing import Callable

class Verdict(str, Enum):
    ALLOW = "allow"
    DENY = "deny"
    CONFIRM = "confirm"

@dataclass(frozen=True)
class TaskRequest:
    skill: str
    object_id: str | None

@dataclass(frozen=True)
class AuthenticatedContext:
    tenant_id: str
    principal_id: str

def authorize(
    context: AuthenticatedContext,
    request: TaskRequest,
    *,
    allowed_skills: set[str],
    can_access_object: Callable[[str, str, str], bool],
    effect_class: str,
) -> Verdict:
    if request.skill not in allowed_skills:
        return Verdict.DENY
    if request.object_id and not can_access_object(
        context.tenant_id, context.principal_id, request.object_id
    ):
        return Verdict.DENY
    if effect_class in {"external_write", "destructive"}:
        return Verdict.CONFIRM
    return Verdict.ALLOW

这是应用层 Policy 片段,不是 A2A SDK 实现。可信 Caller Context 必须来自 Authentication Middleware,不能来自模型生成的 Task Field。effect_class 应来自服务端 Skill Registry,而不是请求体;真实的 CONFIRM 结果还需要明确的审批和审计流程。

最小生产架构

text
caller
  -> authenticate and authorize
  -> validate task shape and budget
  -> persist idempotency + lifecycle event
  -> remote A2A service
       -> independently authenticate, authorize, and validate
       -> use bounded local tools and data access
       -> store artifacts in an approved scoped store
  -> collect redacted result evidence
  -> apply local approval / compensation / user response

每个服务都应重新检查 Policy,不能只相信上游执行。跨 Tenant Test 必须证明:Tenant A 的有效 Token 和 Task ID 无法读取或修改 Tenant B 数据。

测试失败路径

测试 应证明什么
Card Validation Unknown Issuer、Endpoint、Schema Revision、Skill 被拒绝
Task Contract Malformed Part、Oversized Artifact、Unsupported Mode 安全失败
Authorization Tenant、Object、Action Policy 独立于 Description 执行
Lifecycle 重复投递、Restart、Timeout、Cancellation、Late Callback 可确定处理
Side Effects Retry 不重复执行;不确定性会暴露
Streaming Reconnect、Replay、Ordering、Expiry、Backpressure 有边界
Abuse 阻止注入、投毒 Artifact、SSRF Callback、Artifact Exfiltration
Operations 可观察延迟、Queue Depth、Task Cost、Retention 与 Deletion

Policy 和副作用优先用确定性 Oracle。语言模型 Judge 可以审查答案质量,但不能证明授权、来源或财务正确性。

常见失败模式

  • 将 Agent Card、Registry Listing、Badge 或 SDK Adapter 当作信任决策;
  • 假设所有 A2A 实现共享同一个发现路径或 Streaming Transport;
  • 接受 Task Content 中提供的 Caller Identity;
  • 将 Task Completion 当作副作用只执行一次的证据;
  • 未验证地转发远程 Artifact 或 Callback URL;
  • 将远程 Agent 输出当作指令或授权;
  • 无期限保留原始 Task Payload;
  • 未测试固定 Version/Transport 就宣传 Framework 支持;
  • 本地确定性 Workflow 更清晰时仍调用远程 Agent。

实现清单

  • [ ] 固定 Protocol、Binding、SDK 与 Agent Card Schema Revision。
  • [ ] 获取或信任 Card 前验证远程 Endpoint 来源。
  • [ ] 在部署需要时双向认证。
  • [ ] 在拥有服务处授权每个 Skill、Tenant、Object 和副作用。
  • [ ] 持久化 Idempotency、生命周期迁移和不确定状态。
  • [ ] 限制 Message、Artifact、Callback、Streaming、Retry 与 Telemetry。
  • [ ] 将远程 Message、Artifact 与 Card Content 视为不可信。
  • [ ] 测试 Restart、重复投递、Cancellation、Expiry、跨 Tenant 与 SSRF。
  • [ ] 定义 Task、Artifact、Index、Cache、Export 的 Retention 与 Deletion。
  • [ ] 使用明确 Scope、Budget 与 Rollback Control 逐步发布。

总结

A2A 可以使独立 Agent 服务实现互操作,但它不是自治的信任网络。固定运行的版本,将发现视为不可信 Metadata,使 Task State 可持久化,并在模型外执行身份、对象访问和副作用控制。最安全的引入方式是从一个窄小、只读的委派 Task 开始,只有生命周期、授权和失败证据充分时再扩展。

一手来源