A2A协议入门:构建Agent之间的通信标准

A2A协议

什么是A2A协议?

A2A(Agent-to-Agent)协议是一种让智能代理(Agent)之间进行通信的标准方式。你可以把它想象成两个Agent之间的交流方式,让它们能够互相理解和协作。

协议:不同系统,不同个体之间能够有效沟通和协作的一套规则和标准。

为什么需要A2A协议?

你可能会问:这跟我自己写个脚本,手写提示词调几次大模型 API,最后把结果拼起来返回,有什么区别?

如果是写一次性脚本,确实没区别。但 A2A 的关键在于连接性 ------它能让你的 Agent 直接暴露给外部使用,从"写一个工具给自己用 "转变为"开发一个 Agent 供生态使用"。

这就好比你自己写个工具函数,和发布一个标准的三方包的区别:

以前你得把代码复制给别人,或者写一堆文档告诉别人怎么调你的接口;现在,遵循 A2A 协议,你的 Agent 就像发布到中央仓库的包一样,任何 Agent 都能自动发现、下载并调用它 (你需要知道对方的 URL(Endpoint) 。拿到 URL 后,请求这个地址,Agent 会返回一个标准的 Agent Card(名片)),无需额外适配。

Prompt 是给 Agent 一个"聪明的大脑",让它知道"该怎么做";
A2A 协议是给 Agent 一套"通用的语言和社交礼仪",让它知道"该怎么与人合作"。

A2A协议的核心概念

1. Agent Card(代理名片)

就像人的名片一样,告诉别人"我是谁,我能做什么"。

2. Task(任务)

代表一个具体的工作单元,比如"查询北京天气"

3. TaskStatus(任务状态)

任务执行过程中会有不同状态:

  • submitted:已提交
  • working:正在处理(流式输出)
  • completed:已完成
  • failed:失败

4. EventQueue(事件队列)

初始化 -> 干活 -> 发Artifact(结果) -> 发Status(完结) 这是A2A协议的关键机制,代理通过事件队列不断向外发送状态和结果:

  1. 先推送Task(我接到活了)
  2. 再推送WORKING状态(我正在干...)
  3. 推送Artifact(这是我干出来的成果/半成品)
  4. 最后推送final=True的COMPLETED(我干完了)

5. JSON-RPC

一种特定格式的JSON传输协议,用于代理间的标准化通信。JSON-RPC本质上就是把RESTful的"动词(GET/POST)+路径(/api/weather)"压缩成了"method: getWeather"一个字段。

最小可运行代码

后端(main.py)- 天气助手代理

python 复制代码
# main.py
"""
最简单的 A2A Agent 后端示例
"""
from a2a.server.request_handlers import DefaultRequestHandler
from a2a.server.apps import A2AStarletteApplication
from a2a.server.events import EventQueue
from a2a.server.agent_execution import AgentExecutor, RequestContext
from a2a.server.tasks import InMemoryTaskStore
from a2a.types import AgentCard, AgentSkill
from a2a.types import (
    AgentCapabilities,
    AgentCard,
    AgentInterface,
    AgentSkill,
)
import uvicorn

from agent_executor import WeatherAgentExecutor

def main():
    # 1. 声明技能
    skill = AgentSkill(
        id='check_weather', 
        name='查询天气', 
        description='根据用户提供的城市名称,查询该城市的实时天气情况', 
        tags=['天气', '查天气', '气温'], 
        # examples=['北京今天天气怎么样?', '帮我查一下上海的天气', '广州冷不冷']
    )

    # 2. 定义能力(你的硬件配置,全用默认的就行)
    capabilities = AgentCapabilities(streaming=False)

    # 3. Agent 卡片信息
    agent_card = AgentCard(
        name='天气助手', 
        version='1.0.0',
        description='一个能够根据城市名称查询实时天气的智能代理',
        capabilities=capabilities,
        preferred_transport='JSONRPC', # default='JSONRPC', examples=['JSONRPC', 'GRPC', 'HTTP+JSON']
        url='http://localhost:8000',
        defaultInputModes=["text"],      # 必需字段
        defaultOutputModes=["text"],
        skills=[skill],
    )

    # 4. 创建执行器和事件队列
    executor = WeatherAgentExecutor()
    request_handler = DefaultRequestHandler(agent_executor=executor,task_store=InMemoryTaskStore())

    # 5. 创建应用
    app = A2AStarletteApplication(agent_card=agent_card, http_handler=request_handler)

    # 6. 启动应用
    print("🚀 A2A Agent 启动在 http://localhost:8000")
    uvicorn.run(app.build(), host="0.0.0.0", port=8000)

if __name__ == "__main__":
    main()

执行器(agent_executor.py)- 实际工作逻辑

这是 A2A 的精髓,初始化 -> 干活 -> 发Artifact -> 发Status

python 复制代码
# agent_executor.py
from a2a.server.agent_execution import AgentExecutor, RequestContext
from a2a.server.events import EventQueue
from a2a.utils import new_task, new_text_artifact
from a2a.types import TaskArtifactUpdateEvent, TaskStatusUpdateEvent, TaskStatus, TaskState

class WeatherAgentExecutor(AgentExecutor):
    async def execute(self, context: RequestContext, event_queue: EventQueue):
        
        # 1. 初始化任务(应对并发:多用户同时来,各拿各的 task_id)
        task = context.current_task or new_task(context.message)
        await event_queue.enqueue_event(task)

        # 2. 获取用户发来的文本
        query = context.message.parts[0].root.text

        # ================= 核心业务区 =================
        # 实际工作中,这里可能是调用大模型、查外部 API 等
        result_text = f"问题:{query}\n答案:北京今天晴天,气温 25°C。"
        # ==============================================

        # 3. 发送结果文本(把最终答案放进包裹里)
        await event_queue.enqueue_event(
            TaskArtifactUpdateEvent(
                task_id=task.id,
                context_id=task.context_id,
                artifact=new_text_artifact(name='response', text=result_text),
            )
        )

        # 4. 标记任务完成(告诉客户端:包裹发完了,结束吧)
        await event_queue.enqueue_event(
            TaskStatusUpdateEvent(
                task_id=task.id,
                context_id=task.context_id,
                status=TaskStatus(state=TaskState.completed),
                final=True # 👈 非常关键,代表这次交互彻底结束
            )
        )

前端(test.py)- 客户端调用

python 复制代码
# test.py
"""
测试 A2A Agent
"""
import httpx
import asyncio
import json
from uuid import uuid4

from a2a.client import A2ACardResolver
from a2a.client.client import ClientConfig
from a2a.client.client_factory import ClientFactory
from a2a.types import (
    Message,
    Part,
    Role,
)
from a2a.utils.constants import AGENT_CARD_WELL_KNOWN_PATH

async def main():
    base_url = "http://localhost:8000"
    # 打通一个电话线路,不用的时候自动断开,httpx相当于requests的升级版,支持异步
    async with httpx.AsyncClient() as httpx_client:
        # 初始化 A2ACardResolver,用来接收和解析 Agent Card(名片)
        resolver = A2ACardResolver(
            httpx_client=httpx_client,
            base_url=base_url,
        )

        _public_card = (await resolver.get_agent_card()) 
        # print(f'_public_card: {json.dumps(_public_card.dict(), indent=2, ensure_ascii=False)}') # 名片信息
        
        # 封装好的客户端,用于发请求
        client_factory = ClientFactory(config=ClientConfig(streaming=False))
        client = client_factory.create(_public_card)

        # 组建消息
        parts = [Part(text='我要查看北京的天气')]
        message = Message(
            role=Role.user,
            parts=parts,
            message_id=uuid4().hex,
        )
        # request = SendMessageRequest(id=uuid4().hex, params=MessageSendParams(message=message))

        # 发送消息,接收响应
        response = client.send_message(message)
        async for task, update in response:
            # print(json.dumps(task.model_dump(), indent=2, ensure_ascii=False)) # 完整json
            if task and task.artifacts:
                for artifact in task.artifacts:
                    for part in artifact.parts:
                        # 直接打印纯文本
                        print("Agent 回复:", part.root.text)

if __name__ == "__main__":
    asyncio.run(main())

A2A vs MCP协议

  • A2A协议:Agent与Agent之间的交流方式
  • MCP协议:Agent与Tool(工具)之间的交流方式

gRPC vs HTTP + JSON-RPC

  • HTTP + JSON-RPC :传的是明文 JSON。优点 是人眼能直接看懂,前后端对接极其方便,不用依赖任何特殊工具;缺点是数据体积大,解析相对较慢。
  • gRPC :传的是 Protobuf(二进制格式)。优点 是体积小 3-10 倍,解析速度快几倍到几十倍,性能拉满;缺点是肉眼看着全是乱码,调试极其痛苦,必须用专门的工具才能解码。

总结

前端拿着你的 Endpoint (URL) 找到你,获取你的 Agent Card(名片,功能),通过 JSON-RPC 给你发了一个 Task。你开始干活,通过 EventQueue 不断往外扔状态和产出物,最后扔出一个带 final=True 的完成状态,结束这次与Agent的交流。

相关推荐
大学有意思2 小时前
广西英华国际职业学院新能源汽车技术专业2026年权威解析
人工智能·机器人
枫叶林FYL2 小时前
【自然语言处理 NLP】 大语言模型(LLM)系统工程(Large Language Model Engineering)5.1.2 ZeRO与显存优化技术
人工智能·深度学习·机器学习
Flying pigs~~2 小时前
基于huggingface库Trainer实现Bert文本分类实战
人工智能·自然语言处理·bert·文本分类·huggingface·trainer
Gale2World2 小时前
专题九:【终局演进】从“单体网关”到去中心化集群:分布式数字员工(Swarm)的宏大涌现
人工智能·agent
天天代码码天天2 小时前
C# OnnxRuntime BEN2 前景分割
人工智能
moers2 小时前
从cosh到AgentSecCore:拆解阿里云Agentic OS的四个技术决策
人工智能
饼干哥哥2 小时前
RPA也被AI干死了!!一键生成监听100个小红书博主的工作流
人工智能
前端付豪2 小时前
实现消息级操作栏
前端·人工智能·后端
HarryPoint2 小时前
🔥Claude Code 源码分析报告新鲜出炉了
人工智能