☰
A2A协议:智能体间协作的“普通话”,如何实现互操作?
2026/10/14 6:48:36 网站建设 项目流程

1. 为什么智能体间需要一套新协议:从单机智能到群体协作的转折点

如果你过去一年一直在跟AI智能体打交道,大概率会有一种感觉:单个智能体本身已经不难做了,真正难的是让多个智能体像人类团队一样协作起来。市面上有五花八门的智能体框架,有人用Coze、Dify这类平台拖拽搭建,有人直接用Python调LLM自己撸,还有人基于LangChain或AG2做编排。可一旦你想让“A平台的客服智能体”和“B平台的物流智能体”直接对话,就会发现彼此之间根本没有共同语言——大家都在说方言,谁也听不懂谁。

这正是2025年4月Google联合50多家合作伙伴推出A2A协议(Agent2Agent)时要解决的问题。A2A不是又一个智能体框架,而是一套通信协议,它就相当于给智能体之间定了一本“普通话手册”,规定了智能体该怎么自我介绍、怎么接收任务、怎么返回结果、怎么中途要更多信息。它解决的是互操作性问题:不管你的智能体是用什么语言写的、跑在什么框架上、部署在哪朵云里,只要实现了A2A协议,就能被其他智能体发现、调用、协作。

这篇文章不是协议文档的中文翻译,而是我从实际部署和调通一个A2A服务过程中沉淀下来的理解。我会拆解它的设计逻辑、核心数据结构、落地步骤,以及和MCP之间的分工边界。如果你正在做多智能体协作、想把自己的AI能力开放给外部Agent调用,或者只是想知道2025年智能体圈子里这条“新赛道上到底在跑什么车”,这篇文章值得你花15分钟读完。

1.1 智能体协作的真实痛点:能力有了,接口没了

先描述一个我反复遇到的场景。假设你手头有一个“行程规划智能体”,它能根据用户意图订机票、订酒店、生成日程。另一个团队做了一个“报销智能体”,能识别发票、填写报销单。老板说,把它们打通:用户规划完差旅,报销智能体自动根据行程单生成报销草稿。

听起来简单,做起来全是问题。行程智能体输出的是自然语言描述,报销智能体需要的是结构化字段;行程智能体希望“一问一答”式的对话,报销智能体希望“一次性提交、批量返回”;两个智能体都没有能力中间暂停去问用户“你要住哪个价位的酒店”。这些不是某个框架能解决的,而是缺乏一套双方都认可的任务交互规范。

A2A协议登场。它把智能体之间的交互抽象成“Agent Card + Task生命周期 + Message流”,从一个Agent能提供什么能力(Agent Card),到一次协作任务如何被创建和推进(Task),到中间每一步传输的数据单元(Message/Part),全部标准化。任何一个符合规范的智能体,接入另一个符合规范的智能体,不需要单独写适配代码。

1.2 智能体的“HTTP”:一个值得记住的定位

很多人问过我,A2A和HTTP到底什么关系?A2A是跑在HTTP之上的应用层协议,就像今天的Web服务跑在HTTP之上一样。它沿用了JSON-RPC风格的调用方式,用HTTP作为传输载体,但把所有智能体协作相关的语义都放进了协议层。

这个定位很关键。它意味着A2A不关心你的智能体内部用的是什么模型、什么框架、什么推理策略,只关心“对外暴露什么样的服务契约”以及“任务如何推进”。有人把Agent Card比作智能体的“OpenAPI文档”,我认为这个类比是准确的,而且A2A连动态能力协商都做了——不只告诉你“我有什么能力”,还能根据输入参数实际推理出“你这次任务我需要什么输入”。这就是它和传统API协议最本质的差别:传统API要求输入输出完全结构化预先定义,A2A支持开放式的多模态内容交换,运行过程中可以动态协商。

2. A2A协议的核心设计思路:原生智能体体验、企业级安全与开放标准

在一份协议设计里,最见功力的是“取舍”。A2A拿出来的三个设计原则,基本框定了它的适用范围和未来走向。

2.1 三项原则如何框定协议的边界

第一原则是“原生智能体体验”。这句话的意思是,协议不能强迫智能体按传统API接口的方式工作。智能体天然有这些特性:需要异步处理(大模型推理可能要几十秒甚至几分钟)、需要流式输出(效果好的应用一定是一边推理一边输出)、需要在运行中向人类或别的Agent索要额外信息(比如缺一个身份证号)、面对同一个目标可能用不同路径完成。A2A把这些都作为一等公民内置,而不是等到后来打补丁。

第二原则是“企业级安全与合规”。智能体协作一旦跨企业边界,身份认证、权限控制、审计日志就是底线问题。A2A没有重新发明一套安全机制,而是把企业已有的标准安全手段(如OAuth 2.0、OpenID Connect、mTLS)作为集成点挂在协议外层。这样企业在接入时不用抛弃已有的安全基座,安全团队也不会因为“新协议不透明”而否决技术方案。

第三原则是“开放标准”。A2A从一开始就是多个厂商一起制定的,不是为了某个云厂商的单边利益。这一点在实际落地时很重要——谁都不想被某个商业生态绑定。我在调研阶段专门确认过,目前微软、思科、LangChain、Salesforce等公司的智能体体系,都在陆续提供A2A兼容支持,这比某些封闭协议的前景要稳。

2.2 贯穿全流程的任务状态机:所有协作的基础骨架

A2A协议最核心的抽象是Task。一个Task就是一次完整的智能体协作单元。你可以把它理解成人类工作场景中的一张工单,它从创建开始,经历执行中、等待补充信息、完成或失败等状态,最终归档。

Task的生命周期用一张状态流转图可以看懂(这里不发图,用文字描述):初始状态是submitted(已提交),进入working(执行中);如果智能体需要更多输入,会转成input-required(等待输入),人类或者其他智能体提供补充后再回到working;最终走到completed(完成)、failed(失败)或canceled(已取消)。任何时刻客户端都可以查询Task状态,也可以主动取消。

这个状态机和普通REST API的关键差异在哪?传统API把每次请求都当成独立的一次性调用,你调一下它答一下,不行你换个参数再调一次。A2A把任务变成了一个持久的、可追踪的实体,服务器端能识别“这个任务是上次那个任务的延续”,中间的各种信息交换都是围绕同一个Task展开的。这种做法对长时运行的真实协作至关重要——比如要花20分钟完成的“跨部门申请审批”,任务挂在后台,用户可以离开,随时回来接着问进度。

3. 把协议翻译成代码:Agent Card、Task与Message的数据结构

任何协议最终都要落到字段级别,不然没法写代码。这一节我直接拆A2A最关键的数据结构,都是我在对接时逐个核对过的,尽量用白话解释清楚每个字段的作用。

3.1 Agent Card:智能体展示自己的“门牌号”

Agent Card是JSON格式的智能体描述文件,通常部署在/.well-known/agent.json路径下,通过HTTPS供给外界获取。它回答三个问题:你是谁?你能干什么?怎么联系你?

{ "identifier": "travel-agent-001", "name": "差旅规划助理", "description": "负责机票酒店查询预订、行程编排", "url": "https://agent.example.com/a2a", "version": "1.0.0", "capabilities": { "streaming": true, "pushNotifications": false, "stateTransitionHistory": true }, "security": { "schemes": ["bearer"], "credentials": "https://agent.example.com/.well-known/oauth2" }, "skills": [ { "id": "flight_booking", "name": "机票预订", "description": "根据出发地目的地日期查询并预订机票", "tags": ["travel", "flight"], "examples": ["帮我订下周一北京到上海的机票"] } ] }

我用一个类比来解释这份文件的作用。你新入职一家公司,公司给你一张工牌,上面写着你的名字、岗位、所属部门和分机号。别的同事看到这张工牌就知道能找你办什么事、怎么找到你。Agent Card就是智能体的工牌。skill数组是岗位职责列表,capabilities是“我是否支持实时输流、是否支持推送通知”的能力开关,security字段告诉调用方“你需要用什么方式认证才能访问我”。

这里有个容易忽略的点:Agent Card本身也是可以动态更新的。客户端有缓存机制,但协议允许服务端在Task运行过程中更新卡上的能力信息,比如某个时段预约功能暂时下架。设计Agent服务时,Card的生成建议从配置中心动态读,而不是写死在代码里。

3.2 Message与Part:数据传输的最小组成单元

Task内部流动的数据叫Message,Message内部由若干Part组成。Part可以是一段纯文本、一个结构化JSON片段、一张图片(或图片URL)、一个文件路径。这打破了传统API“只能传格式化字段”的限制。

{ "jsonrpc": "2.0", "method": "message/send", "params": { "taskId": "task-20250612-001", "message": { "role": "agent", "taskId": "task-20250612-001", "messageId": "msg-0007", "parts": [ { "kind": "text", "text": "旅客姓名或身份证号缺失,请补充。" }, { "kind": "file", "file": { "name": "需求说明.pdf", "mimeType": "application/pdf", "path": "https://..." } } ] } } }

我在实际调试时最常用的两个Part是text和file。text用于自然语言交互,file用于传文档、PDF、图片。这种“消息放内容、内容分类型”的模型,和人类发微信很像——你可以一句话加一张图,对方完整理解你的意图。多模态是智能体的刚需,A2A在这个层面直接做进了协议,不需要上层单独约定。

3.3 四个核心方法:messages/send、tasks/get、tasks/cancel、message/stream

A2A的客户端-服务端交互基于几个JSON-RPC方法展开,核心动作主要有四个:

  • messages/send:向Agent发送一条包含任务的消息,这是最常用的入口方法。
  • tasks/get:查询任务的当前状态。
  • tasks/cancel:取消一个尚未完成的任务。
  • message/stream:建立流式连接,让Agent持续把输出推给调用方。

这四个方法划出了整个协议的交互边界:一次agent-to-agent协作,本质上就是“发消息、查进度、收输出、可取消”。再加上一个可选的pushNotificationConfig机制——Agent处理完任务后主动推给回调地址,让调用方不用一直轮询。这一套组合下来,基本上把异步调用、流式返回、回调通知三种最常见交互模式都覆盖了。

4. 一个可运行的落地参考:用Python把现有Agent暴露成A2A服务

理解协议最好的方式,是让一个实例跑起来。我现在介绍一个参考实现思路,你可以照着自己做一遍。选型上,我建议先用Python生态做最小验证,原因是Python下A2A SDK和示例相对完整,调通成本最低。

4.1 环境准备与关键依赖

先说环境。硬件上普通开发机即可,无需GPU,因为Agent背后调的是云端大模型API。软件上推荐Python 3.10+,安装以下依赖:

pip install a2a-sdk fastapi uvicorn

安装完成后,工程目录可以保持简单,我把核心逻辑拆成两个文件:一个agent.py负责定义智能体能力和业务处理,一个server.py负责暴露HTTP服务并挂载A2A端点。

4.2 写一个最简Agent:返回明文答案的假数据版本

先跑通协议再填业务逻辑。第一步可以写一个“什么都能答”的假Agent,目的是验证A2A服务的发现、握手、任务下发、结果返回链路是否通畅。

from a2a.types import ( AgentCard, AgentCapabilities, Message, Task, TaskState, TextPart, TaskStatusUpdateEvent ) from a2a.server import InMemoryAgentServer, Agent class FakeAgent(Agent): def __init__(self): self.agent_card = AgentCard( name="FakeAssistant", description="一个用于协议验证的最小Agent", url="http://localhost:8000/", version="0.1.0", capabilities=AgentCapabilities(streaming=True), ) async def handle_message(self, message: Message) -> Task: task = Task( id="task-" + uuid.uuid4().hex[:8], status=TaskState.COMPLETED, messages=[Message( role="agent", task_id=..., parts=[TextPart(text="收到,我可以处理任何问题(当前为测试模式)。")] )] ) return task server = InMemoryAgentServer(agent=FakeAgent()) app = server.app

这里有三个注意点。第一,agent_card的url字段必须是外部可达的地址,客户端会拿这个地址去发起后续请求,写localhost会导致远端调用失败。第二,handle_message的返回类型是Task,不是Message,因为一次协作是一次任务,Task是比Message更高层的抽象。第三,状态直接设置成COMPLETED没问题,但实际业务中最好按真实执行进度流转,否则客户端侧看到的中间状态永远是“已完成”。

启动服务用uvicorn即可,SDK已经把A2A的HTTP路由挂载到了FastAPI的app上:

uvicorn server:app --host 0.0.0.0 --port 8000

启动后用curl访问http://localhost:8000/.well-known/agent.json,能看到Agent Card返回,说明发现机制已经工作了。

4.3 把真实LLM能力接入A2A服务

假数据跑通链路后,换成真实LLM调用。最简单的方式是直接用OpenAI SDK或任意大模型API,但有一种更省事的路子:用AG2框架(前AutoGen,是A2A协议的早期贡献者框架)封装Agent,再直接转换输出。

import asyncio from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.ui import Console from a2a.types import Message, TextPart, Task, TaskState from a2a.server import InMemoryAgentServer, Agent from autogen_ext.models.openai import OpenAIChatCompletionClient # 使用任何兼容OpenAI接口的大模型,也可以通过环境变量配置 client = OpenAIChatCompletionClient(model="qwen-max", api_key="YOUR_API_KEY") assistant = AssistantAgent( name="travel_assistant", model_client=client, system_message="你是差旅规划助理,负责解答行程相关的查询。", tools=[search_hotels, search_flights, book_ticket], ) class A2ACardAgent(Agent): def __init__(self): self.agent_card = AgentCard( name="TravelAssistant", description="差旅规划Agent,可查航班、酒店并生成行程建议", url="http://localhost:8000/", version="0.1.0", ) async def handle_message(self, message: Message) -> Task: user_content = " ".join( part.text for part in message.parts if isinstance(part, TextPart) ) result = await Console(assistant.run(task=user_content)) # 对执行结果做转换,这里取最后一条消息的文本作为回复 final_reply = result.messages[-1].content task = Task( id="task-autogen-" + uuid.uuid4().hex[:8], status=TaskState.COMPLETED, messages=[Message( role="agent", task_id=..., parts=[TextPart(text=final_reply)] )] ) return task server = InMemoryAgentServer(agent=A2ACardAgent()) app = server.app

打通这层之后,你的Agent就有了“通过A2A协议对外服务”的能力。外面任何一个了解A2A的客户端,拿到你的Agent Card后就能给这个“差旅助理”派活。这里最值得体会的是:A2A服务端实际上是把你已有的业务能力包了一层标准外壳,不需要为了接入协议重写业务逻辑。

5. 两条腿走路:A2A与MCP的分工、边界与选型建议

不夸张地说,“A2A是不是要取代MCP”这个问题,我在每个技术群里都见到过。结论是两条腿,不是二选一。MCP和A2A处理的是不同层级的问题。

5.1 MCP管“智能体怎么用工具”,A2A管“智能体之间怎么协作”

MCP(Model Context Protocol,模型上下文协议)解决的是单智能体内部“连接”问题:你的智能体要读数据库、查文件、调第三方API,MCP统一这些工具接入方式,让大模型能力与外部系统对接变得标准化。A2A解决的是多智能体之间的“对话”问题:一个智能体要委托另一个智能体做事,A2A统一了任务下发与状态同步的方式。

用一个生活类比勾勒二者边界:MCP是“一个人的手”,让这个人的手可以抓不同工具干不同的活;A2A是“人和人之间的沟通话术”,让不同岗位的人能顺畅交接工作。san一个AI应用里,既需要手干活,也需要人跟人交流,所以两个协议应用场景不冲突,相反而互补。

维度MCPA2A
解决层级智能体内部,模型与工具之间智能体之间,跨系统协作
核心抽象Tool/Resource/PromptAgent Card / Task / Message
典型场景让LLM调用数据库、HTTP API让两个独立智能体协同完成任务
复杂度定位工具接入标准化业务协作标准化
市场推动Anthropic主导,生态非常丰富Google主导,企业级互操作为核心

5.2 常见误区:不要一上来就想用A2A替代业务API

我踩过的最大的坑是试图用A2A替代所有内部系统API。A2A适合的场景是真正需要“语义化协作”的场景——比如动态目标协商、需要多轮澄清、结果不是单纯数据而是任务履约过程。如果你的流程是固定输入输出、高吞吐量的接口调用,直接用REST API比A2A高效得多,A2A的状态管理、异步回调带来的复杂度是纯亏的。

选型的判断标准很简单:调用双方是否都需要理解“任务”这个概念,而不仅仅是交换数据。如果是,A2A价值明显;如果不是,传统API方案更稳。

6. 把协议落地到生产环境前必须处理的四个问题

这一节是全文最重要的部分。协议本身的调通只是第一步,真正到了生产环境,那些文档不写、示例不覆盖的细节,才是决定项目成败的关键。

6.1 长任务超时与幂等设计

大模型Agent跑一个复杂任务动辄几分钟。如果你用同步HTTP请求去等结果,网关层的超时限制(通常是30秒或者60秒)会直接掐断连接。A2A的一大好处是支持异步任务,但前提是客户端和服务端都按异步模式实现,服务端收到请求后立刻返回Task ID,再通过轮询或push通知推结果。

幂等性同样要提前设计。你重试一次“创建任务”请求,不应该产生两个任务。我在实现中对消息生成task_id做幂等约束:同一个task_id只能创建一次Task,后续相同请求直接返回原Task,而不是新建。这个设计在弱网环境、客户端重试场景中能挡住大量脏数据。

6.2 Agent Card的可达性与版本管理

Agent Card的URL必须是公网可达的HTTPS地址,这是很多本地调试成功的开发者上线后遇到的第一个问题。第二是Agent Card一定要做版本管理。卡片字段的增删会影响所有客户端的兼容性判断,我见过上线第二天因为改了description字段导致对方智能体“不认识”这个Agent的情况(对方系统按描述做了行为匹配)。建议的方法是:给Agent Card增加version字段管理流程,改动前在测试环境验证兼容性,然后像发布API版本一样发布卡片。

6.3 安全:认证、授权与审计

生产环境的安全建议遵循“用现有基础设施,不重建轮子”的原则。服务端建议至少启用Bearer Token认证,复杂场景直接对接企业已有的OAuth2.0或OIDC体系;跨企业调用时用mTLS保证通道层双向认证。每个Task的创建、消息收发、状态变更都记审计日志,方便事后追溯“哪个智能体在什么时候让另一个智能体做了什么”。没有这层记录,出了责任纠纷很难说得清。

6.4 观察行业脉络:安全评估正在成为协议落地的前置条件

最后补充一个我在调研热搜趋势时注意到的信号:智能体安全评估标准正在同步演化。OWASP已经发布了2026年智能体应用Top 10风险清单(ASI01到ASI10),其中很多条目直接与智能体间通信有关,比如跨Agent的提示注入、任务状态操纵、敏感数据在Task/Message中被其他Agent过度读取等。而AgentDojo这类专门用于“测试智能体在不可信环境下行为是否安全”的评测框架,也开始被更多A2A实现引用。这侧面说明:A2A这类协议的普及,一定会伴随着“智能体行为审计”“跨Agent权限边界”等安全话题的爆发。如果你现在设计A2A服务,提前把鉴权、最小权限、审计三件套纳入架构,后续接任何合规要求都会从容很多。

以我个人的实操体会,A2A这套协议真正的价值天花板,不在协议本身,而在于它让“智能体团队”这个概念第一次有了统一的执行框架。跑通一个Demo只需要半小时,难的是把你的Agent卡设计得让别的Agent一眼懂、敢调用、不会被误导。这跟当年Web API普及时的道理一模一样:协议是基础设施,而基础设施之上的设计品味,才是拉开差距的地方。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询