Skip to content

A2A 协议

A2A(Agent-to-Agent)是 Google 在 2025 年发布的开放协议,解决的问题是:当你的系统里有多个 AI Agent 时,它们之间怎么互相发现和协作。

这页和 MCP 协议 是配对的——MCP 处理"Agent 怎么调用工具",A2A 处理"Agent 怎么调用另一个 Agent"。两者面向不同层级的集成需求。

先说清楚 A2A 解决的是什么问题

在单 Agent 系统里,一个 Agent 通过 Tool Calling 调用各种工具(搜索、数据库、API),MCP 提供了标准化的工具接入协议。但在更复杂的系统里,你可能有:

  • 一个专门处理客服对话的 Agent
  • 一个专门做数据分析的 Agent
  • 一个专门处理订单的 Agent

当用户问的问题同时涉及订单状态和数据分析时,一个 Agent 单独处理能力有限。最自然的解法是让 Agent 之间互相协作——但没有标准协议时,每个团队的 Agent 实现都不一样,跨系统集成的成本很高。

A2A 就是为了解决这个互联互通问题:让不同系统、不同团队构建的 Agent,能够通过标准接口互相发现和调用。

五个设计原则

A2A 的设计目标不是替你规定 Agent 内部怎么实现,而是让不同 Agent 能在边界上对齐。官方文档里经常出现的几个关键词,可以这样理解。

Agnostic

A2A 不绑定具体模型、框架或云厂商。远程 Agent 可以用 LangGraph 写,也可以是自研服务;可以调用 Gemini,也可以调用其他模型。调用方只依赖协议暴露出来的 Agent Card、Task、Message 和状态。

这一点对企业集成很关键。跨团队协作时,你通常无法要求对方换成你的 Agent 框架。

Async

Agent 处理的任务经常不是一次 HTTP 请求能马上结束的,比如生成报告、查询多系统数据、等待人工审批。A2A 把 Task 作为核心对象,就是为了支持长任务、状态轮询和流式进度。

同步返回适合简单任务;复杂任务至少要能查询 workingcompletedfailed 这类状态。

Multimodal

A2A 的 Message 不是只放一段纯文本,而是由多个 parts 组成。一个任务可以同时包含文本、结构化数据、文件或图片引用。对多模态 Agent 来说,这比“所有东西都塞进一段字符串”更容易扩展。

实际落地时,文件和图片通常不会直接塞进 JSON,而是用 URL、文件 ID 或对象存储引用传递。

Interoperability

互操作性是 A2A 最核心的价值。Agent Card 告诉调用方“我能做什么”,Task 和 Message 规定“怎么发任务”,状态和 artifacts 规定“怎么拿结果”。只要这些边界一致,内部实现可以完全不同。

它解决的不是“多 Agent 怎么规划任务”,而是“两个已经存在的 Agent 服务怎么互相理解”。

Security

A2A 默认面向跨服务、跨团队甚至跨组织调用,安全不能靠“大家都在内网”含糊带过。调用方是谁、能调用哪些 skill、能访问哪些用户数据、日志里能不能留下原始输入,都需要在协议边界之外配套实现。

这个原则也提醒你:Agent Card 可以公开能力描述,但不应该暴露内部 prompt、私有 endpoint、数据库字段或敏感业务规则。

A2A 的核心设计

Agent Card

每个支持 A2A 的 Agent 都需要发布一个 Agent Card,相当于 Agent 的"名片",通常放在 /.well-known/agent.json

json
{
  "name": "OrderAgent",
  "description": "处理订单查询、退款申请和物流跟踪",
  "url": "https://order-service.example.com/agent",
  "version": "1.0",
  "capabilities": {
    "streaming": true,
    "pushNotifications": false
  },
  "skills": [
    {
      "id": "query_order",
      "name": "查询订单",
      "description": "根据订单号查询订单状态和物流信息",
      "inputModes": ["text"],
      "outputModes": ["text", "data"]
    },
    {
      "id": "request_refund",
      "name": "申请退款",
      "description": "提交退款申请并返回处理进度",
      "inputModes": ["text"],
      "outputModes": ["text"]
    }
  ]
}

客户端 Agent 可以先读取这个 Card,了解目标 Agent 有什么能力,再决定要不要、怎么调用它。

Task 和 Message

A2A 的基本交互单元是 Task。客户端向远程 Agent 发送一个 Task,Agent 处理并返回结果。

json
POST /task
{
  "id": "task-123",
  "sessionId": "session-456",
  "message": {
    "role": "user",
    "parts": [
      {
        "type": "text",
        "text": "查询订单 ORD-20240315-001 的当前状态"
      }
    ]
  }
}

响应:

json
{
  "id": "task-123",
  "status": {
    "state": "completed"
  },
  "artifacts": [
    {
      "parts": [
        {
          "type": "text",
          "text": "订单 ORD-20240315-001 当前状态:已发货,预计明天到达"
        }
      ]
    }
  ]
}

流式响应

对于耗时较长的任务,A2A 支持 SSE 流式返回中间状态,客户端可以实时展示进度,不必等待完整结果。

认证与安全

A2A 本身描述的是 Agent 之间怎么通信,生产系统还要配认证和授权。常见做法有两类:

  • API Key:适合内部服务或早期集成,调用方在请求头里带固定密钥,例如 Authorization: Bearer <token>
  • OAuth2:适合跨组织或需要用户授权的场景,可以区分 client identity、scope、token 过期时间和刷新流程

如果只是系统间调用,API Key 容易落地,但要配合密钥轮换、调用来源限制和审计日志。只靠一个长期有效的 key,很容易在泄露后失控。

OAuth2 更重,但适合回答“这个 Orchestrator 是否有权让订单 Agent 查询某个用户的数据”。这时权限不只是服务级别,还要带上用户身份、租户、scope 等上下文。

在 Agent Card 里,可以公开认证方式和安全 scheme,但不要把真实密钥写进去:

json
{
  "name": "OrderAgent",
  "url": "https://order-service.example.com/agent",
  "securitySchemes": {
    "bearer": {
      "type": "http",
      "scheme": "bearer"
    }
  }
}

服务端还需要做几件事:校验调用方身份、检查 skill 权限、限制输入大小、过滤敏感日志、给长任务设置超时。Agent 间调用一旦能触发真实业务动作,安全边界要按普通生产 API 的标准来做。

一个端到端调用示例

下面的例子展示一个 Orchestrator Agent 如何发现并调用远程订单 Agent。为了让代码短一点,这里没有实现真实模型决策,而是用关键词选择 skill;实际项目里可以把 Agent Card 的能力描述交给模型,让模型决定是否委托远程 Agent。

python
import requests

BASE_URL = "https://order-service.example.com"
API_TOKEN = "replace-with-service-token"


def fetch_agent_card() -> dict:
    response = requests.get(f"{BASE_URL}/.well-known/agent.json", timeout=10)
    response.raise_for_status()
    return response.json()


def call_remote_agent(message: str) -> dict:
    headers = {
        "Authorization": f"Bearer {API_TOKEN}",
        "Content-Type": "application/json",
    }
    payload = {
        "id": "task-ord-001",
        "sessionId": "session-web-001",
        "message": {
            "role": "user",
            "parts": [{"type": "text", "text": message}],
        },
    }
    response = requests.post(
        f"{BASE_URL}/task",
        json=payload,
        headers=headers,
        timeout=30,
    )
    response.raise_for_status()
    return response.json()


card = fetch_agent_card()
skill_names = [skill["name"] for skill in card.get("skills", [])]
print("remote skills:", skill_names)

result = call_remote_agent("查询订单 ORD-20240315-001 的当前状态")
print(result["status"]["state"])
print(result["artifacts"][0]["parts"][0]["text"])

这个 demo 的关键点有两个:先读 Agent Card 再调用,不要硬编码对方能力;请求里带认证信息,不要把 Agent 间调用当成普通函数调用。

A2A 和 MCP 的区别

这两个协议经常一起出现,容易混淆:

维度MCPA2A
解决的问题Agent 怎么调用工具Agent 怎么调用 Agent
通信对象工具服务(数据库、API、文件系统)另一个 AI Agent
典型场景Agent 查询数据库、调用搜索 APIOrchestrator Agent 委托专业 Agent 处理子任务
协议设计者AnthropicGoogle

两者可以同时使用:一个 Orchestrator Agent 通过 A2A 调用专业 Agent,专业 Agent 内部通过 MCP 调用工具。

当前的实际状态

A2A 协议发布于 2025 年,目前整体还处于早期阶段:

已经有的

  • Google 发布了官方规范和参考实现
  • LangGraph 和部分框架开始支持 A2A
  • 有社区实现的 SDK(Python、JS)

还在发展中的

  • 生态系统仍在建立,大多数生产系统还是自定义集成
  • 安全和权限控制机制还在完善
  • 跨组织的 Agent 发现机制(类似 DNS 的 Agent 目录)还没有标准

对于现在正在做多 Agent 系统的开发者来说,了解 A2A 协议是值得的,但不必急着在所有系统里落地。如果你的多 Agent 协调在单个代码库里,用 LangGraph 或者自定义调用已经够用;A2A 在跨系统、跨团队的 Agent 集成场景里更有价值。

和多 Agent 协调的关系

A2A 是多 Agent 系统的通信层,解决"怎么连接"的问题。但连接之后怎么协调工作——谁是 Orchestrator、任务怎么拆分、结果怎么聚合——这些是系统设计层面的问题,A2A 本身不规定。

这部分的工程设计在 复杂 Agent 系统解析 里有更详细的讨论。

和 LangGraph 怎么集成

LangGraph 负责把一个 Agent 系统内部的流程编排成图,A2A 负责跨服务调用。两者可以放在同一套系统里,但位置不同。

一种常见做法是:

  1. LangGraph 里的 Orchestrator 节点分析用户任务
  2. 某个节点读取远程 Agent Card,判断是否有合适 skill
  3. 如果需要委托,就调用 A2A Task 接口
  4. 远程 Agent 返回 artifacts 后,写回 LangGraph state
  5. 后续节点继续汇总、追问或调用其他工具

在代码层面,A2A 调用可以被包成一个 LangChain tool,也可以直接写成 LangGraph 节点。选择取决于你想让模型自由决定调用,还是由图里的条件边明确控制。

如果远程 Agent 调用涉及真实业务动作,我更倾向放在显式节点里。这样可以在调用前加权限检查、人审、幂等键和超时处理。把它包装成一个普通工具虽然方便,但模型可能在不合适的时候重复调用。

一个简化的节点大概是这样:

python
def call_order_agent_node(state: dict) -> dict:
    task = call_remote_agent(state["user_message"])
    if task["status"]["state"] != "completed":
        return {"remote_error": task["status"]}

    answer = task["artifacts"][0]["parts"][0]["text"]
    return {"order_agent_answer": answer}

这个节点不关心远程 Agent 内部是怎么推理的。它只关心协议返回的状态和 artifacts,这正是 A2A 适合放在系统边界的原因。

常见面试考点

A2A 题目数量不多,但容易和 MCP 混在一起。准备时先把层级关系讲清楚:

  1. 五大设计原则:Agnostic 不绑定模型和框架;Async 支持长任务;Multimodal 支持多类型消息;Interoperability 保证跨系统互通;Security 要求认证、授权和审计。
  2. A2A vs MCP:MCP 连接工具和数据源,A2A 连接另一个 Agent;前者偏能力接入,后者偏 Agent 间协作。
  3. Agent Card:它是远程 Agent 的能力说明,调用方要通过它了解名称、地址、技能、输入输出模式、流式能力和认证方式。
  4. Task / Message 模型:A2A 的基本交互单元是任务,消息和 artifacts 承载输入输出,适合长任务、异步状态和多模态结果。
  5. 认证机制:内部集成可用 API Key,但要有轮换和审计;跨组织或用户授权场景更适合 OAuth2 和 scope 控制。
  6. 流式与状态更新:耗时任务不能只等最终结果,SSE 进度返回有助于调用方展示中间状态和处理超时。
  7. LangGraph 集成:LangGraph 做内部流程编排,A2A 做远程 Agent 通信;A2A 调用可以封装成 tool,也可以作为显式图节点。
  8. 适用边界:单个系统内部的多 Agent 不一定需要 A2A;跨团队、跨系统、跨组织的 Agent 集成才更能体现价值。

下一章:多 Agent 协调——A2A 解决 Agent 之间怎么通信,协调章节继续讨论任务怎么拆、结果怎么汇总、冲突怎么处理。

面向开发者系统学习 AI 应用开发、RAG、Agent 与 Vibe Coding。