ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

A2A协议从入门到实践:多智能体协作的标准通信指南

A2A协议从入门到实践:多智能体协作的标准通信指南 最近总有朋友问我A2A协议到底是个啥网上资料怎么全是英文说实话我接触A2A协议也有一段时间了从最初对着官方文档一头雾水到现在能在项目里把多个Agent串起来干活中间踩过的坑不算少。这个协议虽然挂着小白友好的旗号但真要学起来如果没找对路径很容易被一堆术语劝退。这篇文章就从一个学习者的角度把我自己的学习路线、踩坑经验、以及动手实践的关键步骤都拆开揉碎讲一遍。我不会堆概念只讲怎么从零开始把A2A协议跑起来并真正理解它到底解决了什么问题。不管是刚入门的技术爱好者还是已经在做Agent开发的工程师按这条路线走至少能省下一两个月瞎摸索的时间。1. 堆概念之前先搞懂A2A到底在解决什么问题1.1 从一个A到多个A智能体协作的现实困境如果你做过AI应用开发应该能感受到一个趋势2024年到2025年行业里突然从单机版智能体转向了多智能体协作。单机版是什么概念就是一个Agent自己调用工具、自己读文档、自己完成任务。但现实世界里很多任务根本不是单一Agent能搞定的。举个例子你让一个旅行规划Agent帮你安排出差它需要查天气、订机票、订酒店、看日程冲突这些能力可能分散在不同团队、不同系统里。如果让一个Agent全包要么它的上下文窗口爆炸要么它对于专业系统的调用权限不够。这时候最自然的想法是让擅长不同领域的Agent各干各的互相通信。但问题来了市面上Agent框架五花八门Autogen、LangChain、CrewAI你用你的我用我的彼此之间怎么通信总不能每个框架都写一套适配代码吧。A2A协议就是Google在2025年4月牵头搞的一个开放协议目标非常朴素让不同厂商、不同框架的Agent能够像人和人发邮件一样标准、互通地完成协作。后来这个项目捐给了Linux基金会成了真正的开放标准。1.2 A2A和MCP的分工别再把它们搞混了几乎所有刚开始学A2A的人第一个问题都是它和MCP有什么区别这种问题我回答过不下十次。你可以这么理解MCP是Agent访问工具的协议A2A是Agent调用Agent的协议。我自己做的一个类比是MCP像是给一个员工发了一堆工具箱让他自己会用电钻、会拧螺丝A2A则是让这个员工去和另一个员工对接协作比如你把墙刷了我来装开关。从技术形态上看也是如此。MCP走的是Client-Server一个Agent作为一个MCP客户端去连接工具服务器。A2A走的也是Client-Agent模式但是对端是一个完整的智能体而不是一个工具。这带来的复杂度完全不是一个量级的工具是无状态的执行完返回结果就行Agent是有状态的它可能要在对话中来回确认信息任务执行过程也分阶段。这也是A2A协议里为什么会有Task状态机、Message轮次这种设计的原因。搞清楚了这一层你再看官方文档就会觉得那些抽象概念突然有了落地的方向。学习A2A协议拼的不是死记硬背接口而是理解为什么要这么设计。1.3 版本情况与学习资料的选择策略还有一个比较坑的地方A2A协议的版本更新速度非常快。我刚开始学的时候还是0.1.0版本现在官方文档已经是0.2.x甚至更新的内容了。结构上其实变化不大核心机制稳定主要是一些字段细节和认证扩展。这里给你一个很实在的建议别追最新的commit直接盯住Linux基金会下的A2A项目文档以稳定发布版本为准。遇到网上教程里说的接口和官方文档对不上九成是版本问题。2. 上手第一步把核心概念压缩成一听就懂的版本2.1 Agent Card智能体的简历学习A2A协议第一个要认识的概念就是Agent Card。你完全可以把它理解为智能体挂在门口的名片或者简历。一个Agent如果想要被别人调用首先要对外发布一个JSON格式的卡片里面写清楚自己是谁、能干什么、怎么联系。通常访问路径放在根目录下规则和很多网站的标准约定一样。下面是一个很典型的Agent Card长什么样我用一个小示例给你感受一下{ name: weather-agent, description: 为其他智能体提供实时天气查询与预警服务, url: https://agent.example.com/, protocolVersion: 0.2.0, capabilities: { streaming: true, pushNotifications: false }, skills: [ { id: weather_query, name: 天气查询, description: 输入所在城市名称返回当天与未来三天的天气 } ] }你看这里的字段其实都不难protocolVersion是协议版本capabilities声明了能力比如是否支持流式输出skills列的是这个Agent具体会干的活。对于小白来说只要理解了Agent Card的发布位置和字段作用后续的一切调用都是从找到简历开始的。2.2 核心对象Task、Message、Part接下来是A2A协议的数据模型这部分是理解协议的关键。我当年被一堆英文术语绕晕了后来画了一下关系发现就三层Task任务、Message消息、Part内容片段。Task是整个协作的执行单元比如帮我查天气就是一个Task。Task有状态机流转一般是submitted - working - completed或者failed当然也可能进入input-required状态代表Agent需要更多的输入信息。Message是在Task执行过程中传递的信息。每条Message有role要么是user角色要么是agent角色它在Task的上下文里不能乱传必须和Task绑定。Part则是Message的组成片段。为什么有Part这个概念因为一条消息里可能既有文字文本又有文件图片甚至是结构化的代码数据。Part分成几种类型比如文本片段、文件片段、数据片段。举个例子你让一个报告助手Agent总结PDF它的返回可能是文字总结TextPart加一个输出PDF文件FilePart。如果这两样东西用传统的RPC语义去做数据格式必须预先约定死非常僵硬。A2A把消息内容用Part组织起来协作双方便有了极大的灵活性。2.3 传输方式与关键API拆掉JSON-RPC这堵墙看协议文档时很多人会被JSON-RPC这个名词吓到。其实它没有多高深就是一个基于JSON的远程调用规范规定了这次调用要执行什么方法、传什么参数、返回什么结果。A2A建立在JSON-RPC之上常用的方法也就那么几个message/task/send向目标Agent发消息并创建任务。message/task/get按ID查询当前任务状态。message/task/cancel取消任务。message/stream以流式方式推送任务过程中的增量消息。A2A支持普通同步调用也支持流式调用。同步调用是发出去然后等结果流式则是在任务处理过程中把中间的消息一条一条推给客户端。流式场景下A2A底层用的是SSEServer-Sent Events一种基于HTTP的单向推送技术服务端可以向客户端持续推送数据。搞懂这几类传输方式你的学习进度其实已经过半了。3. 动手从零搭建一个能跑的最小A2A协作3.1 别一上来就上框架先手写一次HTTP调用我之前走了条弯路一开始就直接用官方SDK结果被封装搞得很懵出了错也不知道是协议问题还是SDK问题。后来我换了个思路先用最原始的工具把A2A握手流程跑通再回头看SDK就豁然开朗了。第一步我们先手动获取一个Agent Card。假设对方Agent的地址是https://remote-agent.example.com它的Agent Card就放在https://remote-agent.example.com/.well-known/agent.json。用curl拉一下curl -s https://remote-agent.example.com/.well-known/agent.json拿到这个JSON文件后你会看到对方协议版本、通知方式、技能列表等。到这里你就相当于拿到了一张简历知道了对方的能力边界和调用惯例。3.2 发送一个最简单的任务请求接着我们尝试发送第一个Task。A2A的端点通常就是Agent Card里的url字段。假设我们就要调起上面那个天气Agent让它查询北京天气。一条最朴素的JSON-RPC请求长这样{ jsonrpc: 2.0, id: 1, method: message/task/send, params: { context: { threadId: my-thread-001 }, message: { role: user, parts: [ { kind: text, text: 查一下北京明天的天气 } ] } } }用curl把它发过去curl -s -X POST https://remote-agent.example.com/ \ -H Content-Type: application/json \ -d {jsonrpc:2.0,id:1,method:message/task/send,params:{context:{threadId:my-thread-001},message:{role:user,parts:[{kind:text,text:查一下北京明天的天气}]}}}这步看起来简单但意义重大——你已经在用标准的A2A协议和另一个Agent通信了。等返回结果通常是一条带taskId和taskStatus的响应。拿到taskId就代表任务状态被对方托管起来了后续可以通过message/task/get反复查询进度。3.3 选择主流框架跑一个完整Demo手写完一次调用后就可以接入官方SDK跑一个端到端的Demo了。目前社区里对小白比较友好的SDK有Python版本的a2a-sdkGoogle那边也把A2A集成到了Agent Development KitADK里。这一阶段你最好在本地起两个服务一个是Agent端一个是客户端让客户端通过A2A协议去调用Agent端。一个最小的Agent端核心逻辑其实就接一个回调处理接收到的任务返回结果from a2a.agent import Agent agent Agent( nameecho-agent, description回声助手原样返回收到的消息, ) # 这个装饰器代表此方法会处理文本类请求 agent.handler(text) def handle_text(text, context): # 业务逻辑把用户内容原样返回 return f你发送的消息是: {text} if __name__ __main__: agent.serve(port8080)我建议你跑通这一步时一定要做一件事用抓包工具或者直接打印HTTP请求日志对比自己手写的请求和SDK发出的请求有什么不同。这样你才会真正理解框架帮我们封装了什么底层到底是怎么传输的。这比看十遍文档都管用。跑通一次端到端之后你会发现A2A其实没有想象中复杂。它就是一种约定核心就是找到对方简历发JSON-RPC消息轮询或流式获取结果。4. 小白最容易踩的五个坑我帮你先踩过了4.1 Agent Card的URL配置错误导致一切调用失败这是我见过的第一大类问题连我自己都跳过。很多人会把Agent Card里的url字段填成Agent Card自身的JSON文件地址比如某个很常见的错误写法。但实际上这个字段应该是Agent服务本身的API地址也就是你发JSON-RPC请求的目标端点。如果填错了客户端能拉到简历但发送任务请求时就会打到不存在的路径上。排查思路也简单先手动curl一下卡片里的url看返回是正常响应还是网页内容。如果访问之后返回HTML那一定是配错了这个地址不是API端点而是某个欢迎页。4.2 上下文轮次管理混乱直接把Agent搞失忆A2A和普通HTTP接口最大的不同它是有上下文、有对话轮次的。很多小白一开始会犯一个错误每发一条消息就开一个新的threadId或者干脆不传threadId。结果就是Agent根本记不住之前聊过什么多轮对话断掉最终出来的东西驴唇不对马嘴。正确做法是同一个多轮协作流程从第一轮到最后结果出来始终使用同一个threadId。用生活类比来说这就像你给同一个客服专员打电话每次都应该报同一个工单号而不是每次都换号重开。当然A2A协议里面Task和Message并不是我们理解的标准聊天对话如果你需要做长期记忆层次还要再往业务数据库里做一些扩展这个话题后面进阶篇再说。4.3 流式场景的半截消息问题SSE读不完就断开A2A支持流式任务结果底层用SSE推送。我刚开始调试的时候用requests库去读流式接口读了一部分就连接断开了当时以为是协议问题后来查了才发现是自己在客户端直接用了普通的POST请求去发message/stream方法。这就有个关键点流式方法必须用支持SSE的HTTP客户端来调用普通的requests.post会一直挂在那里等完整响应而服务端早就开始推流了。比较合适的方案是用httpx并开启流式读取逐步解析服务端推送的事件。如果不想从底层实现那就用官方SDK它已经帮你处理好了。但目的还是要理解一件事A2A的流式传输并不是一套自己发明的协议它就是标准的SSE流该换客户端就必须换。4.4 把A2A当作普通RPC来设计结果陷入死等还有一个认识层面的大坑不少开发者会把A2A调用的结果当作一次性返回的JSON等不到结果就认为服务出了问题。但A2A协议的一个核心哲理是任务的生命周期是异步的。调用方发起一个Task后被调的Agent可能瞬间返回一个taskStatus: submitted然后这个任务就在后台执行了。如果你严格只做一个同步调用的设计那么当任务处理时间变长、Agent需要向你确认信息时你的程序会卡在等待里。更聪明的做法是把每次调用都当作异步任务处理通过状态轮询或配合服务端主动通知比如Webhook来获得最终结果。提早把这个心态建立起来你的架构不会在任务复杂化之后轰然倒塌。4.5 官方文档中迭代太快的字段变动别被迁移通知吓到这个问题非常影响新手心态。A2A从0.1到0.2之间部分字段被改名比如capabilities的结构调整等社区里的老教程可能会失效。我自己的处理办法是锁定三个稳定参考——Linux基金会仓库里的协议文档、Google ADK对应版本的A2A实现、以及官方SDK源码。当教程和这些参考矛盾的时候以参考为准不用浪费时间在找为什么教程不对上面。5. 进阶思考从Demo走向生产级应用还差哪些修炼5.1 跨智能体的语义能力匹配跑通了Demo只是学会语法要让Agent真正在业务里干活还得理解怎么选Agent。实际场景里你面对的不是一个而是几十个Agent这时候不能傻乎乎地拿一份Agent Card挨个试。比较有效的办法是维护一份本地Agent目录定期拉取更新并基于每个Agent的skills描述做向量检索匹配让任务自动路由到最合适的Agent上。我目前在做的一个内部项目就是这样把公司内部的数据分析Agent、文案Agent、客服Agent都注册到目录里上游任务进来后先做一次embedding匹配选出top几的Agent候选再由一个路由Agent最终裁决。这套系统起来之后整个协作效率明显提升。5.2 认证授权隔离企业落地绕不过的坎另一个生产级必聊的话题就是安全。A2A协议本身定义了标准的认证扩展目前主流的方式还是基于OAuth 2.0体系比较常见的流程是客户端获取Agent Card的同时可以从卡片中读取到对方的authentication信息然后按OAuth流程换取access token后续的每一个JSON-RPC请求都带上token。如果你要把A2A引入企业环境一定要尽早考虑权限隔离问题。比如同一个Agent对不同部门返回的数据粒度可能不同或者有些Agent只允许内网调用。这个在协议层面没有魔法它就是一个HTTP服务服务端该怎么鉴权就怎么鉴权。但有个细节值得注意当Agent A去调用Agent B的时候权限到底是以A的身份还是以最终用户的身份来算这就引申出身份传播问题。A2A协议目前在鼓励这种跨Agent身份透传但最终实现往往要结合你所在企业的身份网关来做。5.3 人机协作闭环别忘了还有人在任务环里最后我想强调一点A2A并不是把所有东西都做成纯机器对机器协作。协议的Task状态机里专门设计了input-required状态也就是说一个Agent在执行任务过程中可能需要向人类用户询问信息。比如一个订票Agent在安排行程时不确定你是要靠窗还是过道它会停在这个状态把问题抛给用户拿到答复后才继续执行。我在设计业务时往往会把人这个环节纳入流程考虑人类作为特殊角色出现在协作链路里既能兜底处理异常又能提供更人性化的判断。这一点很多技术狂热者会忽略但恰好是落地时的加分项。回头看我的A2A学习路最关键的转折不是看了某篇神文而是坚持手写一遍协议调用和锁定稳定版本文档这两个笨方法。A2A协议本质上没那么复杂它唯一复杂的地方是和分布式协作这件事纠缠在一起。你只要不急着跳过原理一步步把卡片、消息模型、任务状态、流式传输这四块地基打牢后面的功能无论怎么演进都不会把你甩下车。如果你正在学A2A卡在某个环节不妨回归到最笨的方法打开终端拉一次别人的Agent Card发一条最简单的任务看看返回包里到底有什么。协议这东西跑通一次比看十篇解读都有用。等到你有了一定经验之后再回头看看官方定义相信也会有和我一样的感觉原来每个设计都没那么玄乎全是为了解决现实协作里的真问题。
返回列表