A2A:让独立 Agent 以任务而非函数互操作
核验日期:2026-07-16。本文以 Linux Foundation
a2aproject/A2A主规范为观察点。规范与 SDK 仍演进,部署必须固定支持版本/绑定并以 Agent Card 声明能力,不能依赖未协商特性。
Agent2Agent(A2A)协议面向独立、可能不透明的 Agent 系统互操作。客户端发现远程 Agent 的能力,发送 Message;服务端可以直接返回 Message,也可以建立有生命周期的 Task,通过轮询、流或 push 提供状态与 Artifact。A2A 适合跨进程、跨团队或跨组织的委托,不适合把本地函数包装成“多 Agent”。
核心对象
Agent Card 描述 Agent 名称、入口、能力、认证要求、输入/输出模式和 skills,供客户端发现与兼容检查。Message 表达一次通信,由一个或多个 Part 组成;Part 可承载文本、文件引用或结构化数据。Artifact 是任务产生的输出集合,也由 Parts 组成。Task 是异步工作的持久状态容器,可关联 context 以组织多轮关系。
Message 是交流输入/直接输出,Artifact 是任务产物,Task 是生命周期;不要把三者都塞进一个自由文本字段。文件 Part 需要媒体类型、大小、完整性与访问期限,结构化 Part 仍需 Schema 和版本。
Task 生命周期
当前规范定义 submitted/working/input-required/completed/failed/canceled/rejected 等语义(具体枚举以采用版本为准)。终态任务不能继续接收普通消息。input-required 表示服务端需要更多信息,不等于失败;客户端应向用户展示问题并把后续 Message 关联原 task/context。
状态持久化在服务端,客户端保存远程 task id、context id、请求幂等键和最后事件游标。HTTP 连接断开不等于任务取消;取消是显式、受权、可能失败的业务操作。客户端重试发送前先按协议/实现能力查询任务,防止重复启动昂贵工作。
三种更新方式
轮询 Get Task 实现简单,适合低频或受防火墙限制的集成;流提供低延迟状态/Artifact 更新,要求 Agent Card 声明 streaming;push notification 用 webhook 向断开的客户端发送更新,适合长任务,要求声明 push capability。
流的事件保持生成顺序,客户端按 task/artifact/update 标识去重,处理重连与重复。Webhook 是新的入站信任边界:验证 TLS、服务身份/签名、目标 allowlist、重放窗口、事件 ID、body 大小与速率;快速持久化后异步处理。Agent 不能把用户提供的任意 webhook URL 当成合法目标,否则产生 SSRF。
发现不等于信任
Agent Card 是能力声明,不是安全证明。通过受控目录、DNS/URL allowlist 或组织注册表发现;缓存有 TTL 与版本;验证 HTTPS、域名与可选签名;扩展和 skill 只在客户端理解时启用。Card 改变认证/endpoint/required extension 时重新评估,不能在进行中的高风险任务静默切换。
客户端先按输入/输出媒体类型、stream/push/extended card 与扩展能力做兼容检查,再发送任务。服务端仍验证真实 payload,不相信客户端“已根据 Card 检查”。
认证、授权与委托
跨 Agent 调用至少有三种身份:发起用户、调用方 Agent/服务、远程 Agent。不要把用户的通用 bearer token 原样转发。使用目标 audience 的受限 token,明确代表用户(on-behalf-of)还是服务自身;远端按 tenant/resource/action 授权并审计。需要下游再委托时限制 delegation chain、scope、期限和次数。
远程 Agent 的自然语言请求不能扩大调用方权限。调用方只发送完成任务必要的数据;敏感 Part 做分类、加密、保留和删除约定。跨区域/组织前核对合规与模型供应商数据政策。
A2A 与 MCP 的边界
| 问题 | MCP | A2A |
|---|---|---|
| 主要关系 | Host 连接工具、资源、Prompt Server | Agent 客户端委托远程 Agent |
| 工作单位 | request/notification、tool/resource 操作 | Message 与持久 Task/Artifact |
| 透明度 | Host 通常知道具体工具 Schema | 远程 Agent 可内部不透明 |
| 长任务 | 可由工具自行建任务,但非核心抽象 | Task 生命周期、流/push 是核心 |
| 适用 | 能力接入与上下文 | 独立自治服务之间协作 |
一个系统可同时使用:主 Agent 通过 MCP 访问数据库工具,通过 A2A 委托另一个组织的研究 Agent。二者的身份、trace 和数据边界仍分开。不要把 A2A 当“更高级 MCP”,也不要为同进程两个函数引入远程协议。
Client 端口设计
SDK/绑定变化快,领域层可依赖稳定端口:
type RemoteTaskRef = { agent: string; taskId: string; contextId?: string };
interface ResearchAgentPort {
start(input: { question: string; sourceIds: string[]; idempotencyKey: string }):
Promise<RemoteTaskRef>;
get(ref: RemoteTaskRef): Promise<{ state: string; artifacts: unknown[] }>;
cancel(ref: RemoteTaskRef): Promise<void>;
}Adapter 负责 Agent Card、协议绑定、认证和事件映射;应用工作流负责何时委托、如何等待、预算、审批与结果验证。远程 Artifact 是不可信结果,要校验媒体类型、Schema、大小、来源和恶意内容,不能直接变成本地工具指令。
幂等、重试与一致性
发送 Message 可能在服务端创建任务后响应丢失。实现需要客户端 message/request id 或业务 idempotency key;若当前绑定没有完整幂等语义,在上层登记 operation 与远端 task 映射。重试只在能证明不会重复任务时执行。Artifact 增量以 artifact id、append/last 或采用版本规定的字段合并,重复事件不重复写入。
跨 Agent 没有分布式 ACID。每个 Agent 提交自身状态,调用方用 saga/补偿处理后续失败。高价值操作将远程建议与本地执行分离:远程 Agent 产出计划/Artifact,本地系统重新验证并审批。
错误与降级
区分发现/Agent Card 错误、认证授权、能力不支持、content type、task not found/不可见、终态冲突、超时、远程失败和本地解析。错误映射保留 retryable 与 safe details。远端 completed 不代表业务结果正确,只代表其生命周期成功;本地仍做验收。
远端不可用时,可排队等待、换经评测的等价 Agent、降级为人工或稳定失败。不能未经用户/合规允许把敏感任务自动路由到另一供应商。路由决策记录候选、版本、理由、成本和数据地域。
可观测性与 SLO
关联本地 trace 与 remote task/context/message,遵循 Trace Context 时也不盲信对方 span。记录 Agent identity/Card version、skill、媒体类型、task 状态时间线、更新方式、attempt、Artifact bytes、费用与终止。跨组织 trace 只传最少关联字段,不泄露内部 Prompt 或 PII。
SLO 包括发现成功、任务接受、排队、首次更新、完成时间、input-required 等待、失败/取消、重复任务和 Artifact 验证。长任务用完成时间分布与 deadline,不用普通 HTTP p99 代替。
契约与互操作测试
用本地假 Agent 覆盖:Card 正常/缺字段/能力不匹配/变化;直接 Message;Task 完成、失败、拒绝、需要输入、取消;轮询/流断线/重复/乱序防护;push 签名/重放/SSRF;大/未知 Part;终态追加;认证过期;响应丢失后幂等恢复。保存 golden protocol messages 但对可扩展字段保持版本策略。
跨实现测试比 SDK 单测重要:至少选择两个独立实现做协议 smoke,固定协议版本和绑定,记录差异。主规范变更先跑 compatibility suite,再 canary Agent Card;保留旧版兼容/网关或明确拒绝。
采用门槛
只有当远程能力有独立生命周期、所有者、安全域或部署边界,并且任务/Artifact 互操作带来价值时采用 A2A。同团队内部固定步骤优先函数、队列或工作流;仅共享工具优先 API/MCP。协议不会自动提高智能,只会标准化边界。
验收应能从一次 Message 追踪到 Task、状态更新和 Artifact,证明认证、授权、幂等、重连、取消、结果验证和降级;也要能解释为何某个本地“子 Agent”没有使用 A2A。