A2A(Agent-to-Agent)协议:Agent 之间的下一个标准

"MCP 解决了 Agent 和工具之间的通信,但 Agent 和 Agent 之间呢?"


一个真实的问题

你用 Claude 写了一个财务分析 Agent,同事用 Gemini 写了一个数据采集 Agent。财务分析 Agent 需要数据采集 Agent 提供最新的市场数据。

怎么对接?

最直觉的做法:开一个 REST API,财务 Agent 调采集 Agent 的接口。但问题来了------

  1. 接口要自己定义:你俩得坐下来商量请求/响应格式,写一份接口文档
  2. 状态要自己管:数据采集是个长任务(可能要跑 5 分钟),你得自己实现轮询或回调
  3. 能力发现要自己做:财务 Agent 怎么知道采集 Agent 能做什么?硬编码?
  4. 换一个 Agent 要重来:明天采集 Agent 从 Gemini 换成 Llama,所有对接代码全改

这就是 2024 年多 Agent 系统的现状:每一对 Agent 之间的对接,都是一次定制开发。

如果你的系统里有 5 个 Agent,两两互通需要 C(5,2) = 10 条定制管道。有 20 个 Agent 呢?190 条。这个 N² 爆炸问题,和微服务早期没有 gRPC / OpenAPI 时一模一样。


A2A 是什么:一句话版本

A2A(Agent-to-Agent Protocol)是 Agent 之间的 HTTP------一个标准化的通信协议,让任何框架、任何模型构建的 Agent 都能互相发现、互相委托任务、互相交换结果。

Linux Foundation 2026 年 4 月公告,A2A 发布一年内已有 150+ 组织支持,包括 Google、Microsoft、AWS、Salesforce、SAP、ServiceNow、IBM 等,Google ADK、LangGraph、CrewAI、LlamaIndex、Semantic Kernel 均已原生集成。

它的时间线:

时间 事件
2025 年 4 月 Google 发布 A2A 协议
2025 年 6 月 捐献给 Linux Foundation,成为厂商中立标准
2026 年初 v1.0 正式发布,进入生产可用阶段
2026 年 3 月 v1.2 发布,新增签名 Agent Card、公开 RFC 流程
2026 年 4 月 150+ 组织支持,多个行业进入生产部署

先搞清楚:A2A 和 MCP 不是竞争关系

这是最常被问的问题,答案很简单------它们在不同的层

css 复制代码
┌──────────────────────────────────────────┐
│           多 Agent 系统                   │
│                                          │
│   Agent A ◄──── A2A ────► Agent B        │  ← Agent 之间:用 A2A
│     │                       │            │
│    MCP                     MCP           │  ← Agent 到工具:用 MCP
│     │                       │            │
│   数据库    API    文件    搜索引擎        │
└──────────────────────────────────────────┘
维度 MCP A2A
解决什么 Agent 怎么调工具 Agent 怎么委托另一个 Agent
类比 USB 接口(连接外设) HTTP 协议(服务之间通信)
交互模式 无状态请求/响应 有状态长任务(submitted → working → completed)
是否知道对方 MCP Server 对 Agent 透明 Agent 有自己的"想法",是黑盒
规范维护 Anthropic Linux Foundation

一句话:MCP 让 Agent 有工具可用,A2A 让 Agent 有同事可用。 生产系统两个都需要。

Augment Code 2026 年分析,2026 年的主流多 Agent 架构已经形成 MCP + A2A 双层模型:单 Agent 用 MCP 访问工具和数据,多 Agent 协作用 A2A 做任务委托和结果交换。


A2A 的三个核心概念

1. Agent Card:Agent 的"简历"

每个支持 A2A 的 Agent 都在 /.well-known/agent-card.json 发布一份 JSON 描述符(据 A2A 官方规范 v1.2),告诉世界"我是谁、我能做什么、怎么跟我说话"。

json 复制代码
{
  "name": "market-data-collector",
  "description": "实时采集全球主要交易所的市场数据",
  "version": "2.1.0",
  "url": "https://agents.example.com/market-data",
  "capabilities": {
    "streaming": true,
    "pushNotifications": true
  },
  "skills": [
    {
      "id": "fetch-realtime-quotes",
      "name": "实时行情采集",
      "description": "获取指定交易对的最新价格、成交量、深度",
      "inputModes": ["text"],
      "outputModes": ["text", "application/json"]
    },
    {
      "id": "historical-klines",
      "name": "历史K线数据",
      "description": "获取指定时间范围的OHLCV K线数据",
      "inputModes": ["text"],
      "outputModes": ["application/json"]
    }
  ],
  "authentication": {
    "schemes": ["Bearer"]
  }
}

这和微服务的 OpenAPI Spec 是一个思路------先发现,再调用。客户端 Agent 读取 Agent Card 后,就知道对方有哪些 skill、接受什么输入格式、返回什么输出。不需要任何硬编码。

一个常见问题:Client Agent 怎么知道去哪里找 Agent Card?

A2A 规范本身只定义了路径格式(/.well-known/agent-card.json),不规定你如何初次发现对方的域名 ------这和 HTTP 不规定"你怎么知道服务器 IP"是同一个设计哲学。据 A2A 官方 Agent Discovery 文档,有三种实际做法:

发现方式 机制 适用场景
Well-Known URI 已知对方域名,直接 GET https://domain/.well-known/agent-card.json 公开部署、有独立域名的 Agent
注册表(Registry) Agent 启动时把自己的 Card 注册到中心注册表,调用方按 skill 查询 内部系统有几十个 Agent,需要动态发现
直接配置 把 Agent Card URL 写进环境变量 / 配置文件 开发调试、已知合作方、数量少

注意 :A2A 规范没有标准化 Registry API ,注册表的查询接口由各平台自己定义。目前有社区项目在做(如 a2a-registry.dev),尚未成为标准的一部分。

实际工程中最常见的路径是:开发期用直接配置,生产系统 Agent 多了再引入 Registry

2. Task:有状态的工作单元

A2A 里的核心交互单元是 Task,不是简单的 request/response。因为 Agent 之间的工作往往是长时间的------数据采集要跑 5 分钟,代码审查要跑 3 分钟,你不能干等着。

Task 有一个标准状态机(据 A2A 规范):

css 复制代码
submitted → working → completed
                   → failed
                   → canceled
            ↕
       input-required    ← Agent 需要更多信息时回到这个状态

这个设计很关键:input-required 状态让 Agent 之间可以"对话" ,而不只是单向发指令。比如数据采集 Agent 发现你要的交易对不存在,它可以把任务设为 input-required,附上"请确认交易对名称"的消息。调用方看到后补充信息,任务继续执行。

3. JSON-RPC 2.0:传输层

A2A 在传输层选择了 HTTP + JSON-RPC 2.0。这个选择很务实------几乎所有语言和平台都支持 HTTP 和 JSON,没有额外的依赖。

三种交互方式:

方式 方法 适用场景
同步 message/send 快速任务(< 30s)
流式 message/stream 需要实时进度反馈
推送 Push Notification 超长任务,客户端不想保持连接

跑一个完整的例子

下面用 Python 实现一个最小的 A2A 交互:一个"翻译 Agent"作为 A2A Server,一个"调用方"作为 A2A Client。

python 复制代码
"""
A2A 协议最小完整示例

演示 Agent Card 发布 → Agent 发现 → Task 发送 → 结果接收的完整流程。

运行前提:
  pip install a2a-python uvicorn httpx
"""
import asyncio
import json
import httpx
from dataclasses import dataclass, field, asdict
from typing import Optional


# ============================================================
# 第一部分:A2A Server(翻译 Agent)
# ============================================================

AGENT_CARD = {
    "name": "translator-agent",
    "description": "将任意文本翻译为目标语言",
    "version": "1.0.0",
    "url": "http://localhost:8000",
    "capabilities": {"streaming": False, "pushNotifications": False},
    "skills": [
        {
            "id": "translate",
            "name": "文本翻译",
            "description": "将输入文本翻译为指定的目标语言",
            "inputModes": ["text"],
            "outputModes": ["text"],
        }
    ],
}


@dataclass
class Task:
    id: str
    status: str = "submitted"
    artifacts: list = field(default_factory=list)
    messages: list = field(default_factory=list)


tasks: dict[str, Task] = {}


def handle_jsonrpc(request: dict) -> dict:
    """处理 JSON-RPC 2.0 请求"""
    method = request.get("method")
    params = request.get("params", {})
    req_id = request.get("id")

    if method == "message/send":
        task_id = params.get("message", {}).get("taskId", f"task-{len(tasks)+1}")
        user_text = ""
        for part in params.get("message", {}).get("parts", []):
            if part.get("kind") == "text":
                user_text = part["text"]

        task = Task(id=task_id, status="working")
        tasks[task_id] = task

        # 模拟翻译(生产环境调用 LLM)
        translated = f"[Translated] {user_text}"

        task.status = "completed"
        task.artifacts = [
            {"parts": [{"kind": "text", "text": translated}]}
        ]

        return {
            "jsonrpc": "2.0",
            "id": req_id,
            "result": asdict(task),
        }

    return {
        "jsonrpc": "2.0",
        "id": req_id,
        "error": {"code": -32601, "message": f"Method not found: {method}"},
    }


# ============================================================
# 第二部分:A2A Client(调用方)
# ============================================================

async def discover_agent(base_url: str) -> dict:
    """第一步:读取 Agent Card,了解对方能做什么"""
    async with httpx.AsyncClient() as client:
        resp = await client.get(f"{base_url}/.well-known/agent-card.json")
        return resp.json()


async def send_task(base_url: str, text: str) -> dict:
    """第二步:发送 JSON-RPC 请求,委托翻译任务"""
    payload = {
        "jsonrpc": "2.0",
        "id": 1,
        "method": "message/send",
        "params": {
            "message": {
                "role": "user",
                "parts": [{"kind": "text", "text": text}],
            }
        },
    }
    async with httpx.AsyncClient() as client:
        resp = await client.post(base_url, json=payload)
        return resp.json()


async def demo_client():
    """完整客户端流程:发现 → 委托 → 获取结果"""
    base_url = "http://localhost:8000"

    # Step 1: 发现
    card = await discover_agent(base_url)
    print(f"发现 Agent: {card['name']}")
    print(f"  技能: {[s['name'] for s in card['skills']]}")

    # Step 2: 委托任务
    result = await send_task(base_url, "今天天气真好,适合写代码")
    task = result.get("result", {})
    print(f"  任务状态: {task['status']}")
    print(f"  翻译结果: {task['artifacts'][0]['parts'][0]['text']}")


# ============================================================
# 第三部分:用 uvicorn 启动 Server(简易版)
# ============================================================

if __name__ == "__main__":
    import uvicorn
    from starlette.applications import Starlette
    from starlette.requests import Request
    from starlette.responses import JSONResponse
    from starlette.routing import Route

    async def agent_card_endpoint(request: Request):
        return JSONResponse(AGENT_CARD)

    async def jsonrpc_endpoint(request: Request):
        body = await request.json()
        return JSONResponse(handle_jsonrpc(body))

    app = Starlette(routes=[
        Route("/.well-known/agent-card.json", agent_card_endpoint),
        Route("/", jsonrpc_endpoint, methods=["POST"]),
    ])

    print("A2A Server 启动: http://localhost:8000")
    print("Agent Card: http://localhost:8000/.well-known/agent-card.json")
    print("\n另开终端运行客户端: python -c 'import asyncio; from a2a_demo import demo_client; asyncio.run(demo_client())'")
    uvicorn.run(app, host="0.0.0.0", port=8000)

运行后你会看到:

ini 复制代码
发现 Agent: translator-agent
  技能: ['文本翻译']
  任务状态: completed
  翻译结果: [Translated] 今天天气真好,适合写代码

整个流程的关键点:Client 不需要知道 Server 内部用的是什么模型、什么框架。它只需要读 Agent Card、发 JSON-RPC 请求、等 Task 完成。明天 Server 从 Claude 换成 Gemini,Client 代码一行不用改。


生产环境的四个工程要点

1. 签名 Agent Card:防止冒充

v1.2 引入了签名 Agent Card (据 A2A 规范 v1.2),用加密签名做域名验证。生产环境必须启用------否则任何人都可以伪造一个 Agent Card,声称自己是你的"财务分析 Agent"。

2. Task 超时和重试

Agent 任务不像 API 调用那样快速返回。数据采集可能要跑 10 分钟,代码审查可能要跑 5 分钟。你需要:

  • 设定合理的超时阈值(建议按 skill 粒度配置)
  • task/get 轮询状态,或用 message/stream 获取实时进度
  • 处理 failed 状态的重试逻辑

3. 认证和授权

Agent Card 的 authentication 字段声明了支持的认证方式。生产环境至少用 Bearer Token,企业内网可以用 mTLS。关键原则:Agent 之间的信任不应该比微服务之间更低。

4. 多 Agent 编排

当系统有超过 3 个 Agent 时,建议引入一个编排 Agent(Orchestrator),负责:

  • 维护所有 Agent Card 的注册表
  • 根据任务描述匹配最合适的 Agent
  • 管理 Task 的依赖关系和执行顺序
  • 处理失败 Agent 的降级策略

这和微服务架构里的 API Gateway / Service Mesh 是同一个思路。


哪些场景该用 A2A,哪些不该

场景 用 A2A? 理由
两个不同团队的 Agent 需要协作 跨团队 = 接口标准化 = A2A 的核心价值
一个 Agent 调外部搜索引擎 不用,用 MCP 搜索引擎是工具,不是 Agent
Agent 需要长时间执行并报告进度 Task 状态机 + 流式反馈
同一个进程内的两个 Agent 函数 不用 直接函数调用,加协议只是增加延迟
跨公司的 Agent 互操作 A2A 是厂商中立标准,双方不需要用同一框架
Agent 读写数据库 不用,用 MCP 数据库是资源,不是自主决策的 Agent

判断标准很简单:对方有没有自己的"想法"? 有自己的推理能力、能自主决策的用 A2A;只是被动执行指令的用 MCP。


工程结论

  1. A2A 解决了多 Agent 系统的 N² 互联问题------标准协议让 N 个 Agent 只需要 N 次适配,而不是 N(N-1)/2 次定制对接。这和 HTTP 之于 Web、gRPC 之于微服务的意义完全一样。

  2. A2A 和 MCP 是互补关系,不是替代关系------MCP 是 Agent 到工具的"USB 接口",A2A 是 Agent 到 Agent 的"HTTP 协议"。2026 年的主流多 Agent 架构已经形成 MCP + A2A 双层标准模型。

  3. 协议已经生产可用------据 Linux Foundation 2026 年 4 月数据,150+ 组织支持 A2A,Google ADK、LangGraph、CrewAI 等主流框架均已原生集成,金融、供应链、IT 运维等行业已有生产部署案例。v1.2 引入的签名 Agent Card 解决了生产环境的身份验证问题。

  4. 现在就该学------A2A 的核心概念只有三个(Agent Card、Task、JSON-RPC),比学 Kubernetes 简单一个数量级。等你需要跨团队、跨公司的 Agent 协作时再学,就晚了。


参考来源:

相关推荐
千里码aicood5 小时前
flask-基于注意力机制的异常流量检测与自动防御系统
后端·python·flask
李迟5 小时前
Golang实践录:工程框架实践:搭建工程模板
开发语言·后端·golang
Lynko5 小时前
C语言指针高阶
后端
the局外人5 小时前
学习 FastAPI 的 Day 2:用异步 ORM 完成增删改查
后端·python·fastapi
SamDeepThinking5 小时前
if嵌套最好控制在3层以内
java·后端·程序员
苏渡苇5 小时前
Spring Insight 里上报 Span 为什么用 JDK HttpClient 而不是 RestTemplate
java·后端·spring·spring cloud·springboot·性能监控
tonydf5 小时前
AI驱动历史项目安全审查
后端·ai编程
她的男孩6 小时前
同一个接口,为什么销售只看到自己的订单?我拆了 681 行数据权限拦截器的源码
java·后端·架构
元界metalite6 小时前
SpringBoot接口通用响应对象设计 - 一个 Resp 管理五种责任
后端
对象存储与RustFS6 小时前
把 RustFS 跑在 Kubernetes 上:官方 Helm Chart 从单机到分布式
后端·rust·开源