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 协作时再学,就晚了。


参考来源:

相关推荐
渐儿17 小时前
第 05 章 · SQL 写法
后端
invicinble17 小时前
对于spring的bean应该有哪些领域的认识
java·后端·spring
Amazing530717 小时前
docker compose 漏一个参数全失效
后端·代码规范
ZengLiangYi17 小时前
从零实现 Embedding 服务:文本转向量
人工智能·后端
星栈17 小时前
订单状态机别写散:我在 Rust CRM 里把 6 个状态收进领域模型
后端·rust·全栈
韩小兔修媛史18 小时前
SpringBoot面试八股文(持续更新)
spring boot·后端·面试
码上出头18 小时前
地理围栏从0到1:我是怎么把轮询接口从每分钟2000次干到0次的
后端
神奇小汤圆18 小时前
搞懂数据库索引:它到底帮了什么忙,又埋了什么坑?
后端
浮游本尊18 小时前
Java学习第38天 - 企业级 REST API 设计、OpenAPI 契约与接口可靠性
后端
苍何18 小时前
分享最近高频用 Agent 提效的 4 大场景
后端