A2A(Agent-to-Agent)协议可以把它理解成:**让多个 Agent 之间以标准化方式“互相发现、互相调用、互相协作并可观测”**的一套约定。
如果 MCP 更像“模型 ↔ 工具/资源”的接口规范,那么 A2A 更关注“Agent ↔ Agent”的交互:我怎么知道你是谁、你会什么、我把一个任务交给你你怎么汇报进度、失败了如何恢复、长任务如何流式回传、以及整个协作怎么被状态机可靠托管。

新人学习 A2A,抓住四个关键词就够了:AgentCard(发现与能力画像)Skill(能力单位与调用契约)流式任务(长任务的增量回传)状态机(可靠编排与可恢复性)


1. AgentCard

这是Agent的“公开名片”,用于服务发现和握手。它以JSON格式描述了Agent的身份、能力、技能列表、支持的认证方式、端点URL等。客户端通过读取AgentCard来了解它能做什么,以及如何与之交互。

在多 Agent 系统里,最开始的痛点不是“怎么调用”,而是“怎么发现”。

没有 AgentCard 时,你通常只能靠:

  • 硬编码路由(写死某个 agent 的地址)
  • 人肉文档(某个 Confluence 页面写“某某 agent 能干啥”)
  • 试错调用(发个请求看看对方回不回)

AgentCard 的作用就是把这些变成机器可理解的“名片/能力说明书”。一个合格的 AgentCard 通常包含:

  • 身份信息nameversiondescriptionowner
  • 接入信息endpoint(或 transport)、鉴权方式、超时/重试建议
  • 能力列表:有哪些 skills、每个 skill 的输入/输出 schema、限制条件
  • 运行特性:是否支持流式、是否支持幂等、并发上限、成本提示
  • 安全与边界:数据范围、可访问的系统、敏感操作要求确认等

直觉类比:AgentCard ≈ “可请求的 OpenAPI + README”,但面向的是“Agent 能力协作”。

AgentCard 的工程建议

  • 描述要“可选对”:别写空泛的“我可以帮助你”,要写清“适用场景/不适用场景”
  • 把“限制”写出来:例如“只读”“不处理 PII”“只处理 2024 之后数据”
  • 版本化:多 Agent 一旦上线,不可避免要做兼容与灰度

2. Skill

定义在AgentCard中,描述Agent的具体功能。每个Skill包含名称、描述、输入/输出示例以及是否支持流式输出等信息。例如“天气查询技能”会说明需要城市参数,返回温度。这让客户端知道可以调用该Agent执行哪些具体任务。

Skill 是 A2A 体系里最关键的“能力接口”。你可以把一个 Agent 看成“很多技能的集合”,而不是一个“什么都能问”的黑盒。

一个 good skill 往往具备:

  • 明确的目标:例如 search_docstriage_ticketdraft_reply
  • 清晰的输入 schema(强约束):字段类型、必填、枚举、长度范围
  • 结构化输出:让上游 agent 能继续决策(比如 id/status/next_action
  • 明确的副作用标记:只读 / 写入 / 发消息 / 触发部署 等
  • 权限与确认策略:高风险 skill 需要上游确认或双人审批

直觉类比:Skill ≈ “函数/工具”,但在 A2A 里它属于“另一个 Agent 的能力”,因此更强调契约、治理与可观测

Skill 设计常见坑

  1. 把 skill 做成万能入口(比如 run_sqldo_anything)——短期爽,长期不可控
  2. 输入 schema 太松,导致调用方(或模型)传参随意,最终“靠人肉兜底”
  3. 输出只有长文本,导致上游无法可靠做分支与恢复

3. 流式任务

指Agent在处理长耗时任务时,不等待全部完成,而是将中间结果、进度或初步答案以流的方式逐步推送给客户端的能力。这能提升用户体验(如实时看到生成过程),并通过streaming标志在Skill或任务请求中协商是否启用。

Agent 与 Agent 的协作经常是长任务:检索、爬取、代码分析、跑评估、生成报告……如果你只能“请求→等待→一次性返回”,体验和可靠性都会很差:

  • 用户/上游 agent 不知道在干嘛(误判卡死)
  • 中间产物无法复用(失败就全盘重来)
  • 无法做“边生成边消费”(例如先拿到大纲就开始下一步)

所以 A2A 通常会强调流式任务(streaming task):把一个任务的执行过程拆成连续事件流,例如:

  • task.started:任务启动、分配了 task_id
  • task.progress:阶段进度(百分比/step)
  • task.delta:增量输出(token stream / 文本片段 / 结构化片段)
  • task.artifact:产物引用(文件链接、资源 URI、结果对象)
  • task.warning:可忽略但需要知晓的问题(降级策略)
  • task.completed:成功结束,给最终结果摘要
  • task.failed:失败结束,给错误码、可重试性、建议动作

流式任务的关键价值

  • 可观测:上游能做超时、重试、报警、用户提示
  • 可中断/可恢复:状态机可以在“已完成阶段”继续,而不是重跑
  • 可组合:上游 agent 可以拿到 partial result 就触发下游 agent

4. 状态机

描述一个任务从创建到终态的生命周期变化。典型状态包括:submitted(已提交)、working(处理中)、completed(成功完成)、failed(失败)、cancelled(取消)等。客户端可查询任务状态,状态机确保了任务流程的可追踪性和一致性。

新人做多 Agent 最大的误区是:把协作当成“多轮对话”就够了。
但一旦涉及真实系统(工单/发布/财务/生产数据),你会立刻需要:

  • 重试与幂等:网络抖动、对方超时怎么办?
  • 分支与回滚:某个阶段失败了,怎么补偿?
  • 人工介入:某些节点要审批或二次确认
  • 观测与审计:谁触发了什么、结果是什么

这些都指向同一个工程答案:状态机(State Machine)

4.1 一个典型 A2A 协作状态机长什么样?

以“生成周报”为例(上游 agent 协调多个下游 agent):

  1. INIT:收到请求,生成 task_id
  2. DISCOVER_AGENTS:读取 AgentCard,选择合适 agent(文档/数据/写作)
  3. PLAN:拆解子任务(拉数据、找亮点、写草稿、润色、排版)
  4. EXECUTE_SUBTASKS:并行调用 skills(支持流式回传)
  5. AGGREGATE:汇总 artifacts、去重、对齐口径
  6. REVIEW:规则校验(敏感信息、格式、缺失字段)
  7. DELIVER:输出最终产物(文档链接/消息发送)
  8. DONE / FAILED:终态

4.2 状态机落地的 4 个要点(新人友好)

  • 每个状态都要可重入:同一状态重跑不会把事情搞重复(幂等)
  • 把外部调用当成不可靠:超时、部分失败是常态
  • 将“产物”单独存储并可引用:配合流式任务的 artifacts
  • 把人工确认也当成状态:例如 WAITING_FOR_APPROVAL
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐