
1. 从招聘自动化卡壳说起A2A协议到底解决什么问题先看一个真实场景。某公司想用 AI 把招聘流程串起来简历筛选用一个智能体面试排期用另一个背调再换一个。三个智能体各自跑得挺好但一到交接就崩——筛选完的候选人信息要人工复制到排期系统排期结果又要手动喂给背调服务。自动化做了一半剩下全靠人肉搬运。这不是模型不够强而是智能体之间没有“通用语”。每个智能体都有自己的接口格式、认证方式、任务描述习惯A 说的话 B 听不懂B 返回的结果 C 解析不了。行业里管这叫“能力孤岛”。A2AAgent2Agent协议就是冲着这个来的。它是一套开放标准让不同厂商、不同框架、不同部署环境下的 AI 智能体能够互相发现、互相派活、互相交付结果。你可以把它理解成智能体世界的 HTTP不关心你内部怎么实现只规定“怎么打招呼、怎么下单、怎么交货”。2025 年 4 月谷歌联合 50 多家厂商推出 A2A两个月后把它捐给了 Linux 基金会。这个动作的信号很明确A2A 不想做谷歌的私有协议它要做整个行业的公共基础设施。对开发者来说这意味着你现在学的 A2A 接口规范未来大概率不会因为某家公司的商业决策而作废。这篇文章面向想快速搞懂 A2A 的开发者。我会先讲清楚 A2A 的核心概念和它与 MCP 的分工然后给出一份可复制的配置用 TaoToken 的统一 Key 和 API 通道跑通一个最小智能体互操作示例最后把常见的报错和排查路径列出来。你跟着做能亲手验证 A2A 的“发现—派活—交付”闭环。2. A2A 与 MCP 的分工一张对比表 官方规范关键字段清单很多人第一次听到 A2A 会问不是已经有 MCP 了吗这两个是不是重复了不重复而且分工很清晰。我用一个类比MCP 是“工具使用手册”解决的是一个智能体怎么调用外部工具API、数据库、函数A2A 是“团队协作规范”解决的是多个智能体之间怎么对话、派活、交付。一个管“人怎么用工具”一个管“人怎么跟人合作”。下面这张表把两者的定位、核心对象、典型场景列清楚维度MCPA2A全称Model Context ProtocolAgent2Agent Protocol解决什么智能体如何调用外部工具/数据智能体之间如何协作完成任务核心对象Tool、Resource、PromptAgent Card、Task、Artifact通信方向智能体 → 工具单向调用智能体 ↔ 智能体双向协作发现机制工具列表由宿主注入Agent Card 通过标准路径暴露典型场景让模型查数据库、调天气 API让排期智能体把任务派给背调智能体治理Anthropic 主导Linux 基金会托管两者不是竞争而是叠加。一个复杂流程里A2A 负责智能体之间的任务流转MCP 负责每个智能体内部调用工具。比如排期智能体通过 A2A 收到“安排面试”任务它内部再用 MCP 去调日历 API 查空闲时段。接下来是 A2A 官方规范里你必须记住的关键字段。这些字段决定了你的智能体能不能被别的智能体“读懂”Agent Card智能体名片通常放在/.well-known/agent.json路径下是一个 JSON 文件核心字段包括name智能体名称description功能简介url通信端点地址version协议版本capabilities支持的能力比如是否支持流式、是否支持推送通知skills技能列表每个技能有id、name、description、inputModes、outputModesauthentication认证方式比如 API Key、OAuthTask任务发起方发给执行方的标准对象核心字段id任务唯一标识sessionId会话标识用于多轮message任务描述包含role和partsstatus任务状态取值包括submitted、working、input-required、completed、failed、canceledArtifact成果执行方返回的交付物核心字段name成果名称parts成果内容支持文本、文件、结构化数据index多成果时的序号Push Notification推送通知用于长任务异步更新核心字段url回调地址token验证令牌记住这几个字段后面写配置和排查报错时你会反复用到。A2A 的设计哲学是“能力自描述 任务标准化 成果结构化”这三件事做到了智能体之间才能真正即插即用。3. 可复制配置用 TaoToken 统一通道跑通最小 A2A 互操作理论讲完动手。这一节的目标是用 TaoToken 的统一 Key 和 API 通道让两个最小智能体通过 A2A 协议完成一次“发现—派活—交付”。为什么用 TaoToken因为 A2A 示例里两个智能体各自要调模型来理解任务和生成回复如果每个智能体都去配一套模型 Key光是环境变量就能把你绕晕。TaoToken 提供统一的 API 通道一个 Key 走通多个模型省掉重复配置。先准备环境。你需要一个 TaoToken 的 API Key去控制台创建https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contenta2a_linux_foundation创建完 Key记下你的 Base URLhttps://taotoken.net/api。注意这个地址不带 UTM是纯 API 端点。接下来建项目目录写两个智能体的配置。我用 Python 的 FastAPI 做演示因为 A2A 的通信本质是 HTTP JSON。先装依赖pip install fastapi uvicorn httpx openai然后写第一个智能体天气智能体。它的职责是收到“查天气”任务后调模型生成结构化天气数据返回 Artifact。# weather_agent.py import json from fastapi import FastAPI, Request from openai import OpenAI app FastAPI() client OpenAI( api_key你的TaoToken_Key, base_urlhttps://taotoken.net/api ) AGENT_CARD { name: weather-agent, description: 查询指定城市指定日期的天气, url: http://localhost:8001, version: 1.0, capabilities: {streaming: False, pushNotifications: False}, skills: [ { id: query-weather, name: 查询天气, description: 输入城市和日期返回天气状况, inputModes: [application/json], outputModes: [application/json] } ], authentication: {schemes: [apiKey]} } app.get(/.well-known/agent.json) def agent_card(): return AGENT_CARD app.post(/tasks) async def handle_task(request: Request): body await request.json() task_id body.get(id) message body.get(message, {}) parts message.get(parts, []) user_text parts[0].get(text, ) if parts else resp client.chat.completions.create( modelgpt-4o-mini, messages[ {role: system, content: 你是天气智能体根据用户请求返回JSON格式天气数据字段包括city、date、condition、temperature。}, {role: user, content: user_text} ] ) content resp.choices[0].message.content return { id: task_id, status: completed, artifacts: [ { name: weather-result, parts: [{type: text, text: content}], index: 0 } ] }再写第二个智能体排期智能体。它先通过 A2A 发现天气智能体然后派发任务最后接收成果。# scheduler_agent.py import httpx from fastapi import FastAPI app FastAPI() WEATHER_AGENT_URL http://localhost:8001 app.get(/.well-known/agent.json) def agent_card(): return { name: scheduler-agent, description: 安排面试并参考天气, url: http://localhost:8002, version: 1.0, capabilities: {streaming: False, pushNotifications: False}, skills: [ { id: schedule-interview, name: 安排面试, description: 根据候选人和日期安排面试, inputModes: [application/json], outputModes: [application/json] } ], authentication: {schemes: [apiKey]} } app.post(/run) async def run(): async with httpx.AsyncClient() as c: card (await c.get(f{WEATHER_AGENT_URL}/.well-known/agent.json)).json() task { id: task-001, sessionId: session-001, message: { role: user, parts: [{type: text, text: 查询北京2025-10-01的天气}] } } result (await c.post(f{card[url]}/tasks, jsontask)).json() return {discovered_agent: card[name], task_result: result}启动两个服务uvicorn weather_agent:app --port 8001 uvicorn scheduler_agent:app --port 8002 然后触发排期智能体curl -X POST http://localhost:8002/run你会看到返回里包含discovered_agent: weather-agent和task_result里面是天气智能体生成的 JSON 天气数据。这就是一次完整的 A2A 互操作发现 Agent Card、派发 Task、接收 Artifact。如果你想把模型换成 Claude 系列TaoToken 的通道同样支持只需要把model参数改成对应的模型 IDBase URL 和 Key 不用动。模型对话入口在这里可以试https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contenta2a_linux_foundation4. 验证请求与成功结果怎么确认 A2A 闭环真的跑通了上一节的 curl 返回只是“看起来对了”但你要确认三件事Agent Card 能被正确发现、Task 状态是 completed、Artifact 内容符合预期。先单独验证 Agent Cardcurl http://localhost:8001/.well-known/agent.json | python -m json.tool你应该看到完整的 JSON包含skills数组和authentication字段。如果这里返回 404说明路径写错了A2A 规范要求 Agent Card 放在/.well-known/agent.json不是/agent.json。再验证 Task 提交。手动构造一个任务发给天气智能体curl -X POST http://localhost:8001/tasks \ -H Content-Type: application/json \ -d { id: task-verify-001, sessionId: session-verify, message: { role: user, parts: [{type: text, text: 查询上海2025-10-02的天气}] } }成功的返回应该长这样{ id: task-verify-001, status: completed, artifacts: [ { name: weather-result, parts: [ { type: text, text: {\city\: \上海\, \date\: \2025-10-02\, \condition\: \多云\, \temperature\: \22-28C\} } ], index: 0 } ] }重点看status字段。A2A 规范里任务状态有明确取值submitted表示已接收working表示处理中completed表示完成failed表示失败input-required表示需要补充输入。如果你拿到的是working说明你的处理逻辑没有同步返回需要改成异步加推送通知。最后验证端到端的发现链路。排期智能体的/run接口返回里discovered_agent应该是weather-agenttask_result.status应该是completed。如果discovered_agent是空的说明 Agent Card 请求失败回去检查WEATHER_AGENT_URL和端口。实测下来这套最小闭环跑通后你可以把天气智能体换成任何符合 A2A 规范的第三方智能体只要它的 Agent Card 可访问你的排期智能体就能发现并调用它。这就是 A2A 的价值不用改代码换一个 URL 就能接入新能力。如果你要跑更复杂的多智能体流程比如三个以上智能体串联建议用 Coding Plan 来管理模型调用配额避免频繁切换 Keyhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contenta2a_linux_foundation5. 本篇常见错排查401、local proxy failed、reading choices、OAuth这一节把我踩过的坑和社区里高频出现的报错列出来你对照着排查。报错一401 Unauthorized这是最常见的。A2A 示例里两个智能体都要调模型如果你的 TaoToken Key 没配好模型调用会直接 401。检查三处api_key是否填了完整 Key、base_url是否是https://taotoken.net/api不要多加斜杠或路径、Key 是否过期。如果你用的是环境变量确认变量名没拼错。报错二local proxy failed这个报错通常出现在你本地起了代理或者网络层有拦截。A2A 的通信是 HTTP如果你的环境里配了额外的网络转发规则请求可能到不了localhost:8001。排查方法先用curl http://localhost:8001/.well-known/agent.json确认本地服务本身可访问如果这个都失败问题在服务没起来或者端口被占。如果本地 curl 成功但智能体之间调用失败检查httpx是否走了系统代理可以在代码里显式设置trust_envFalse。报错三reading choices of undefined这个报错来自 OpenAI SDK 解析响应时。原因通常是模型返回的结构不是你预期的 chat completion 格式。两种可能一是model参数填了一个 TaoToken 通道不支持的模型 ID返回了错误结构二是base_url配错请求打到了别的端点。解决方法是先单独用一段最小代码测试模型调用from openai import OpenAI client OpenAI(api_key你的Key, base_urlhttps://taotoken.net/api) resp client.chat.completions.create( modelgpt-4o-mini, messages[{role: user, content: hi}] ) print(resp.choices[0].message.content)这段跑通再回到 A2A 示例里。报错四OAuth 认证失败A2A 的 Agent Card 里authentication字段如果声明了 OAuth但你的请求没带 token执行方会拒绝。最小示例里我用的是apiKey方案比较简单。如果你要接的第三方智能体要求 OAuth需要在请求头里带Authorization: Bearer token并且确保 token 没过期。OAuth 的 scope 也要对有些智能体要求特定 scope 才能调特定 skill。报错五Task 状态一直是 submitted这说明执行方收到了任务但没有推进。检查执行方的/tasks处理逻辑是否真的执行了有没有异常被吞掉。建议在处理函数里加日志把task_id和message打出来。另一个可能是任务需要input-required状态补充信息但发起方没处理这个状态导致卡住。报错六Agent Card 返回 404A2A 规范要求 Agent Card 放在/.well-known/agent.json。如果你用的是 FastAPI路由要写成app.get(/.well-known/agent.json)注意前面的点。有些框架对以点开头的路径处理不同测试时先用 curl 确认。排查顺序建议先确认模型调用通排除 Key 和 Base URL 问题再确认 Agent Card 可访问排除路径问题再确认 Task 提交返回 completed排除处理逻辑问题最后确认端到端发现链路排除 URL 配置问题。这个顺序能帮你快速定位问题在哪一层。6. 语义一致 CTA从跑通示例到接入真实智能体生态A2A 捐给 Linux 基金会这件事对开发者的实际意义是你学的接口规范、写的 Agent Card、实现的 Task 处理逻辑未来会有一个中立的治理机构来维护版本演进。你不用赌某家公司的商业策略。回到动手层面你现在已经有一个能跑的最小 A2A 闭环。下一步可以做的把天气智能体换成你真正需要的服务比如内部的知识库查询、订单系统、工单系统。只要按 A2A 规范暴露 Agent Card 和 Task 端点其他智能体就能发现并调用它。如果你要接更多模型来驱动不同智能体TaoToken 的统一通道可以省掉多 Key 管理的麻烦。API Key 在这里创建https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contenta2a_linux_foundation接入文档里有各语言 SDK 的配置示例包括 Base URL、Key、Model ID 三件套的完整写法https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contenta2a_linux_foundation如果你在跑 A2A 示例时遇到模型调用报错先用模型对话页面单独验证 Key 和模型 ID 是否匹配https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contenta2a_linux_foundation最后留一个实用技巧A2A 的 Agent Card 里skills字段的inputModes和outputModes建议显式写清楚不要留空。我试过留空的情况有些客户端会默认按text/plain处理导致结构化数据被当字符串传解析时多一层麻烦。把application/json写明确对接方少踩坑。