资讯动态

A2A 1.0与MCP对比:从Agent Card到Task生命周期与Java互操作

发布时间:2026/10/14 12:47:55 来源:尧图企业网站定制
最近一忙完手里的演示项目朋友圈里又开始讨论 A2A 1.0 和 MCP 的对比。作为两边都实际写过代码、做过联调的人我先给个直接结论别把 A2A 1.0 当成 MCP 的替代品它俩根本不在同一层。MCP 解决的是单个 Agent 如何拿到工具和数据A2A 1.0 解决的是多个 Agent 之间如何互相发现、派活、追踪任务并收回结果。要讲清这一点抓住 Agent Card、Task 生命周期和 Java 最小互操作这三个视角就够了。这篇内容适合正在做 Agent 架构选型、或者已经在用 MCP 想评估要不要引入 A2A 的读者。我会把协议层面的差异拆到数据模型、状态机、发现机制这些细节上最后用一段能直接跑起来的 Java 代码演示两个 Agent 是怎么完成一次最小互操作的。1. 别再问谁取代谁A2A 和 MCP 解决的是完全不同的两件事1.1 协议分层的根本差异工具面与协作面MCP 的全称是 Model Context Protocol设计目标很朴素给大模型提供一个标准化的方式去连接外部数据源和工具。它的核心关系是模型 → 工具。一个模型在回答用户问题时通过 MCP 客户端调用 MCP 服务端暴露的 tools、resources、prompts拿到结果再接着推理。你可以把它理解成给 AI 插上了手和眼。A2A 1.0 的全称是 Agent-to-Agent设计目标则是代理人 → 代理人。它约束的是两个独立的 Agent 实体之间怎么交换消息、怎么把一个任务委托出去、怎么追踪这个任务的执行进度、最终怎么把成果收回。它关心的是协作流程是 agent 层面的分工而不是底层工具接入。这两个目标最本质的区别在于MCP 的调用是单向的、面向资源侧的A2A 的调用是双向的、面向任务侧的。MCP 里永远是我这个 agent 去调你的工具A2A 里则是我这个 agent 把活儿交给你那个 agent你干完把成果还给我。1.2 一个让我办事一个替我办事直观类比拿现实中的公司举个例。MCP 像是公司内部给每个员工配的办公软件和小工具库。我要写方案直接调用文档模板、查数据库、找价格表——这些动作都是一次性的、即取即用不需要对方理解我背后整体目标是什么。A2A 则像是跨部门的工单系统。我把一个整理客户需求文档的任务整体扔给另一个部门的同事他会接单、开始处理、中途可能要回来问我一句预算范围是多少最后把一份写好的文档交付给我。这个过程中对方不需要我把所有动作都拆成最小步骤给他他拥有自己的判断能力整个任务是有状态、有进度、可以中途沟通的。所以别再问谁取代谁了。工具面和协作面是叠加关系一个 agent 既能通过 MCP 自己动手也能通过 A2A 请别的 agent 帮忙。1.3 对内用 MCP对外用 A2A兼容互补才是主旋律在我完成的项目架构里两者的分工很清晰。主调度 Agent 内部通过 MCP 连接知识库、数据库、搜索服务这些能力一旦它发现自己处理不了某个专业子任务就会通过 A2A 把任务转给对应的专家 Agent。专家 Agent 自己再去用 MCP 调自己的那套工具。任务完成后专家 Agent 通过 A2A 把成果作为 artifact 交回给调度 Agent。这个模式我见过团队用一句话总结得非常好对内用 MCP对外用 A2A。所以技术选型时完全不用纠结二选一而是要确认你的系统里哪一层缺协议。缺工具接入层上 MCP缺 agent 协作层上 A2A。2. Agent Card 才是 A2A 的门脸它和 MCP 的能力发现有什么本质区别2.1 MCP 的能力发现连接后现场问一遍用 MCP 时一个客户端要了解服务端能干什么流程是走 JSON-RPC 的 initialize然后调 tools/list。也就是说能力信息是动态的、随连接产生的你必须先建立一个连接然后像面试官一样逐个问询。这个模型的好处是信息实时服务端可以在每次会话中动态决定暴露哪些工具坏处是发现成本高——想要知道一个服务端是否适合自己你必须先发起连接、完成握手、拉取工具清单人肉去判断。2.2 Agent Card 的静态声明模型卡面上到底写了什么A2A 的能力发现完全不同。每个 A2A Agent 都会暴露一个标准入口通常放在/.well-known/agent.json路径下文件名和路径是约定的。这个 JSON 文件就是 Agent Card它有点像简历也是一个代理的名片。一个典型的 Agent Card 会包含这些关键字段name、description这个 agent 叫什么、是干什么的方便发起方快速判断要不要合作url后面所有 JSON-RPC 请求往哪个端点发authentication它支持哪种认证方式、需要什么凭据capabilities它支持流式输出还是推送通知defaultInputModes、defaultOutputModes它接受什么格式的输入、输出什么格式的产物skills可选的技能列表比 description 更结构化地列出专长。这张卡片是静态的、可缓存的。调度 Agent 在做任务路由时可以先把各个候选 agent 的卡片拉回来缓存起来按名字、描述、技能字段做匹配然后再决定把任务派给谁。这个过程不要求两边先建立长连接非常适合大规模 agent 之间的服务发现。2.3 卡面里的认证信息MCP 标准没管的A2A 用 JSON 管了MCP 对认证的描述非常薄标准层面基本就是把认证甩给传输层去解决。你在 HTTP 头上带 Authorization具体是什么方案、用什么 token协议不管两边私下约定就好。A2A 则把认证当作一等公民写进了 Agent Card。卡面上直接声明我这个 agent 需要什么认证可以是不需要认证、OAuth2、API Key 等。调用方拿到卡片后就能提前知道要不要准备凭据、该调哪种认证流程。这一点在跨团队、跨系统的协作里特别重要。两个 agent 属于不同的权限域时发起方必须先解决认证问题不然任务根本派不出去。卡片把这个问题显式化之后认证协商才变得可自动化、可提前处理。3. Task 是把一次调用变成一个工单A2A 生命周期为什么是必要的3.1 Task 状态机一项长活儿的完整生命周期MCP 的工具调用是典型的 request-response发一个请求立刻拿一个结果状态就结束了。但 agent 和 agent 协作时任务往往不是一次函数调用能完成的。A2A 因此设计了 Task 这一层抽象并给它配了明确的状态机。一个任务的生命周期大致是submitted任务刚被提交给服务端 agent还没开始处理working服务端 agent 正在执行中input-required执行过程中需要更多信息任务暂时挂起等待发起方补充completed任务完成成果以 artifact 形式挂在任务上canceled任务被显式取消failed任务执行失败错误信息会附在任务上。这套状态机最大的价值是让长任务变得可追踪。发起方随时可以调 tasks/get 查看任务当前状态而不需要守着一次 HTTP 请求等结果。3.2 input-required协议级回环不是报错我特别喜欢 A2A 里的input-required状态因为它是协议层面的中途要资料机制而不是通过报错来打断。举个例子。我让 A 调度 Agent 去订会议室它发现没有收到具体时间和人数这时候它不是返回一个参数不足的错误而是把任务置为input-required同时在任务上挂一条 Message说明请提供日期、时间段、参会人数。发起方看到这个状态后可以再次往同一任务发消息补充信息任务会回到working继续执行。这本质上是在协议层实现了 agent 之间的多轮澄清而且每一次澄清都有迹可循。相比工具调一次失败、再调一次这种笨办法它更接近真实工作中同事之间的来回沟通。3.3 Artifacts 和 Part任务产出怎么结构化交给下一个 agent任务完成后成果并不只是一句成功状态。A2A 用 Artifacts 来承载任务产物每个 artifact 可以是文件、文本块、结构化数据等通过 parts 组织成更细的片段。这种结构对 agent 协作意义很大上层 agent 拿到的不是一段无格式的文本而是明确定义了 mime type 的一批产物。比如一个生成项目周报的任务产出的 artifact 可以是一个 markdown 文件下层的专家 agent 可以直接解析这个文件继续加工或者在日志里结构化管理产线。对比 MCP 的工具返回值多数时候就是一个字符串或一个 JSON 对象适合给模型直接看但不太适合作为一个交付物被另一个 agent 系统性地接收、校验和归档。A2A 的 artifact 明显是冲着工作产品传递去的。3.4 没有 Task 的 MCP 调用适合干什么、不适合干什么所以该怎么判断MCP 的调用模型适合那些短、平、快的操作比如查一个数据库记录、调一次搜索接口、往某个系统里写一条数据。这些操作秒级完成不需要中间状态。A2A 的 Task 模型则适合那些运行时间可能以分钟计、甚至更长的任务且任务进程中有可能需要交互澄清、产出产物、支持取消的场景。比如分析整份合同并生成摘要、跑一个数据管道、帮我起草一份方案初稿——这些明显不是一次 tool call 能装下的。如果非要用 MCP 实现长任务你只能自己在工具返回值里塞 job id、自己设计查询接口、自己做状态存储。这也行但你等于在 MCP 之上又造了一套 A2A——与其自己造不如直接用标准协议。4. 跑通 Java 最小互操作一个 Server Agent 和一个 Client Agent 的完整闭环4.1 为什么用 Java 做最小互操作SDK 能力和工程适配A2A 1.0 生态里Java 和 Python 都有对应的参考 SDK。我这次用 Java 来演示有两个考虑一是 Java 在企业级 agent 基础设施里出现频率很高很多团队本来就有大量 Java 服务能直接复用二是 Java SDK 对 Agent Card 的构建、Task 的状态流转封装得比较完整写起来更像是在搭一个有状态的流程而不是在拼字符串。参考实现中的核心类大概是AgentCard、Task、Artifact、Part、Message服务端会用A2AServer起一个 HTTP 端点并注册任务处理器客户端用A2AClient去连接。下面代码以当前 1.0 版本的 SDK 思路为准具体 API 名称略有差异时以你项目里依赖的实际版本为准。4.2 Server 侧最小实现一张卡、一个 handler、一个端口先写服务端。我做一个最小的回声 agent收到什么文本就把它原样包成 artifact 返回。核心在于 handler 里的处理逻辑和 task 状态转换。public class EchoTaskHandler implements TaskHandler { Override public Task handleTask(Task task, Message message) { // 1. 从入站消息里提取文本内容 String text message.parts().stream() .filter(part - part.hasText()) .map(part - part.text()) .findFirst() .orElse(); // 2. 构造一个 text artifact作为任务产物 Artifact artifact Artifact.newBuilder() .setName(echo-result) .setMimeType(text/plain) .addPart(Part.newBuilder().setText(Echo: text)) .build(); // 3. 把任务标记为 completed并带上 artifact return task.toCompleted() .withArtifact(artifact); } }服务端装配只需要三样东西Agent Card、handler、端口。public class EchoAgentServer { public static void main(String[] args) { AgentCard card AgentCard.newBuilder() .setName(echo-agent) .setDescription(a minimal echo agent for interoperability testing) .setUrl(http://localhost:8080/a2a) .setAuthentication(AuthenticationInfo.newBuilder() .addScheme(none)) .build(); A2AServer server new A2AServer.Builder() .port(8080) .agentCard(card) .handler(new EchoTaskHandler()) .build(); server.start(); } }启动之后访问http://localhost:8080/.well-known/agent.json就能看到这张卡。注意我配置的认证方案是none这仅供最小互操作测试使用千万别在生产环境照抄。4.3 Client 侧最小实现拉卡、派单、轮询、收件客户端要完成四步拉取卡片、创建任务、轮询状态、读取产物。public class EchoAgentClient { public static void main(String[] args) throws Exception { // 1. 获取 Server Agent 的 Agent Card A2AClient client new A2AClient(http://localhost:8080); AgentCard card client.getAgentCard(); // 2. 构造一条消息并创建任务 Message message Message.newBuilder() .setRole(user) .addPart(Part.newBuilder().setText(你好A2A)) .build(); Task task client.sendTask(card, message); // 3. 轮询任务状态直到非运行中 while (task.getStatus() TaskStatus.SUBMITTED || task.getStatus() TaskStatus.WORKING) { Thread.sleep(300); task client.getTask(task.getTaskId()); } // 4. 任务完成后读取 artifact if (task.getStatus() TaskStatus.COMPLETED) { Artifact artifact task.getArtifacts().get(0); System.out.println(artifact.getParts(0).getText()); } else { System.out.println(任务未完成状态 task.getStatus()); } } }这段代码背后的协议动作分别是getAgentCard走 HTTP GET 拉 JSONsendTask走 JSON-RPC 的tasks/sendgetTask走tasks/get。协议上的往返就这几步非常清晰。4.4 最小互操作最小在哪传输、编码、认证、ID 四件事所谓最小互操作就是让两个 agent 在不依赖任何中间平台的前提下把一套最基础的协作跑通。整理一下无非这四件事传输两边都要能通过 HTTP 访问对方暴露的端点编码消息符合 JSON-RPC 2.0 规范类型字段能正确解析认证Agent Card 里声明了none测试时两边都不校验凭据ID任务 ID 全局唯一消息上要正确关联 task id否则状态轮询会错位。我建议团队在联调前先用下面这张清单过一遍基础链路检查项验证方法Agent Card 可访问浏览器打开/.well-known/agent.json看能否解析能力描述准确卡片的 name、description、skills 是否反映真实能力任务创建调 tasks/send 后能拿到 valid task id状态流转任务能经历 submitted → working → completed产物可读completed 后 artifacts 非空part 类型与 mode 匹配取消动作对长任务调 tasks/cancel能进入 canceled认证协商卡片声明的认证方式与实际握手流程一致这七项跑通了你的两个 agent 之间才算真正互操作起来了后面加再复杂的业务逻辑都是在这层管道上叠加。5. 实际项目落地选型判断与我在真实环境里踩过的坑5.1 什么时候继续用 MCP 就够了如果你只有一个主 agent它并不需要把任务委托给其他独立部署的 agent那么 MCP 完全够用。典型场景是一个智能体 一堆工具接企业内部知识库、接 CRM 查单、接数据库跑查询。这种情况下引入 A2A 纯粹是过度设计。我见过不少团队被新协议的热度推着走明明连 MCP 的工具层都没跑顺就开始搭 A2A 的协作层结果联调成本翻了好几倍。我的建议是工具层的问题先用 MCP 解决等你真的遇到多个 agent 要互相派活时再上 A2A 也不迟。5.2 什么场景值得把 A2A 提到架构层有几类场景A2A 带来的价值是显而易见的多个独立团队各自维护自己的 agent需要跨系统协作任务执行时间长发起方不能一直占着一个 HTTP 连接业务天然具有分工结构比如报价 agent和审批 agent本来就是两套逻辑你需要把 agent 能力作为一种可发现的服务开放给别人而不只是给自己用。在这些场景里Agent Card 加 Task 的组合比手写 HTTP 接口可靠得多。卡片让服务发现标准化任务状态机让协作长流程变得可追踪产物结构让交付可程序化校验。5.3 联调踩坑实录超时、幂等与认证传递这个环节分享一下我实际踩过的坑每一个都是血的教训。第一个坑是超时。最早做联调时server agent 处理任务要跑 3 秒但入口网关默认读超时只有 2 秒客户端在轮询前就收到了一堆 504。后来把长任务的 HTTP 连接关闭改为轮询tasks/get问题才解决。如果你用流式输出还要注意 SSE 连接的空闲超时别让事件流被中间层掐断。第二个坑是幂等。客户端一旦断线重连很容易把同一条消息重复tasks/send。结果就是同一份任务被服务端执行了两次。A2A 规范里对重复消息有一定约束但服务端 handler 本身也要做防御按 task id 做去重用判断任务已存在就直接返回已有状态不要再起新流程。第三个坑是认证传递。Agent A 调用 Agent B 时B 要求的认证凭据从哪来如果 A 只是拿着用户的 session token 去调 B跨权限域时会非常危险。正确做法是建立服务身份的映射和令牌代理而不是把用户凭据到处转发。这不在协议标准里强制约束但架构上必须早做设计。第四个坑是日志。agent 协作是多跳的一次业务请求可能跨三个 agent。排查问题时如果没有统一的 task id 贯穿所有日志你根本不知道某个任务在哪个环节卡住了。我后来强制要求所有服务在日志里带task_id字段联调调试效率立刻上了一个台阶。5.4 一个值得坚持的落地验证顺序如果让我给一套落地建议我的顺序是这样的先在本地起两个最小 agent跑通 Agent Card 发现、tasks/send、tasks/get、artifact 读取四条链路然后加一个长任务场景验证状态轮询和取消接着引入认证验证卡片上的认证声明与实际握手一致最后再做错误注入比如让 handler 抛异常看任务会不会走到failed、错误信息是否完整。为什么顺序要这样排因为前面任何一层没有打牢后面都容易出一些看起来像 bug 但其实是你根本连协议都没走对的问题。先把最小闭环跑稳再逐步往上加复杂度这是我在多个协议集成项目里验证过最省时间的做法。我在本地还会同时准备一套 Python 的 client用来对接 Java 的 server专门验证跨语言互操作。毕竟 agent 生态最终不可能只跑一种语言能尽早暴露 SDK 之间的细节差异总是比上线后才发现要好。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑