
1. 从一次多 Agent 联调失败说起A2A 协议到底解决什么问题如果你正在做多智能体协作大概率遇到过这种场景一个负责检索的 Agent 和一个负责写作的 Agent 各自跑得好好的一旦要让它们串起来干活就得手写一堆 HTTP 胶水代码字段对不上、状态不同步、认证各搞一套。A2AAgent-to-Agent Protocol就是 Google 针对这个问题推出的开源协议它给 Agent 之间的通信定了一套标准能力怎么声明、任务怎么下发、状态怎么流转、结果怎么回传。简单说A2A 让「Agent 调用 Agent」变得像调用一个规范化的 REST 服务而不是每次重新发明轮子。它适合谁如果你在做编排型应用一个主控 Agent 调度多个专业 Agent、跨团队共享 Agent 能力、或者想把内部 Agent 暴露成可被发现的服务A2A 就是那层你迟早要补上的协议。它和 MCP 是互补关系MCP 管「模型怎么调工具和数据源」A2A 管「Agent 之间怎么协作」。一个典型的完整技术栈是上层用 A2A 做 Agent 编排下层用 MCP 接工具。我试过把两个自研 Agent 用裸 HTTP 对接光是任务状态机就写了两百多行还漏洞百出。换成 A2A 的 Agent Card 任务生命周期模型后协议层的事情基本不用自己操心了。这篇就按「概念 → 配置 → 联调 → 排障 → 凭证统一管理」的顺序把可复制的片段都给你重点放在能直接跑起来的部分。核心检索词先明确A2A 协议是什么、能做什么、适合谁。A2A 是 Agent-to-Agent 的标准化通信框架核心产物是 Agent Card能力声明 JSON和任务Task模型适合多智能体协作场景。下面所有配置都围绕这两个概念展开。2. TaoToken 统一 Key 通道多 Agent 调用凭证的前置准备多 Agent 协作有个容易被忽略的痛点每个 Agent 背后都要调大模型如果每个 Agent 各配一套 Key凭证管理会迅速失控——轮换、限额、审计全乱套。TaoToken 在这里的角色是统一 Key/API 通道把多个 Agent 的模型调用凭证收敛到一处集中管理。官网入口是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 基址是 https://taotoken.net/api 这个不加 UTM。为什么要在 A2A 场景里先讲这个因为 A2A 的 Agent Card 里有一块authentication字段声明的是 Agent 之间怎么认证而 Agent 内部调模型用的是另一套凭证。这两层要分开管Agent 间认证用 A2A 自己的 bearer/oauth2模型调用统一走 TaoToken 的 Key。这样你换模型、加 Agent、做限额都只动一个地方。前置准备分三步。第一步拿到统一 Key登录后在控制台创建 API Key路径是 console 页面下的 api-keys 管理。第二步确认你要用的模型 ID比如做编排的主控 Agent 用推理强的模型做格式化的子 Agent 用轻量模型模型 ID 在模型对话页面能查到。第三步把 Base URL 和 Key 写进各 Agent 的环境变量不要硬编码进 Agent Card。这里有个关键区分要讲清楚A2A 协议里的authentication.schemes是给「别的 Agent 来调我这个 Agent」用的不是给「我调模型」用的。很多人第一次配会混。正确的分层是——Agent Card 声明对外认证方式bearer tokenAgent 内部代码用 TaoToken 的 Base URL Key Model ID 去请求模型。两层各管各的互不干扰。如果你打算长期跑多 Agent 编排或 Agent 类编码任务可以考虑 Coding Plan它更适合持续性的 Agent 调用场景只是临时验证模型连通性用模型对话就够了。接入细节和字段说明看接入文档避免自己猜参数。3. 可复制的 A2A 服务端配置片段这一节给可直接粘贴的配置。先看 Agent Card这是 A2A 的核心用 JSON 描述能力、端点、认证和技能。下面这份是服务端要暴露的agent-card.json路径放在服务根目录由/.well-known/agent.json对外提供{ name: EmailAnalyzerAgent, description: 邮件内容分析与摘要生成 Agent, url: http://localhost:8080, version: 1.0.0, capabilities: { streaming: true, pushNotifications: false, stateTransitionHistory: true }, authentication: { schemes: [bearer] }, defaultInputModes: [text], defaultOutputModes: [text, structured], skills: [ { id: email_summarization, name: 邮件摘要, description: 提取邮件关键信息和行动项, inputSchema: { type: object, properties: { emailContent: { type: string } }, required: [emailContent] } } ] }注意url字段本地联调写http://localhost:8080上线换成真实域名。authentication.schemes只写bearer表示别的 Agent 调你时带 Bearer Token。接着是 Agent 内部调模型的配置。用 TOML 写一份agent-config.toml把 TaoToken 的 Base URL、Key、Model ID 三件套集中管理[model] base_url https://taotoken.net/api api_key ${TAOTOKEN_API_KEY} model_id your-model-id timeout_seconds 60 max_retries 3 [a2a] agent_card_path ./agent-card.json listen_host 0.0.0.0 listen_port 8080 auth_token ${A2A_BEARER_TOKEN} [task] max_concurrent 10 state_history true三件套对应关系要记牢Base URL 是https://taotoken.net/apiKey 从环境变量TAOTOKEN_API_KEY注入Model ID 填你在模型对话里确认过的那个。auth_token是 A2A 层对外认证用的和模型 Key 完全独立。如果你用 Claude Code 或类似工具做 Agent 开发配置通常落在settings.json里结构类似{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: ${TAOTOKEN_API_KEY}, ANTHROPIC_MODEL: your-model-id } }这里同样三件套齐全Base URL、Key、Model ID。用 Cline 或带 MCP 的客户端时MCP 配置里也要把这三件套写全否则会出现「连上了但模型不响应」的情况。Codex 用户如果走auth.json字段名可能是base_url/api_key/model本质还是这三样。配置写完启动服务前先做一次静态检查Agent Card 的 JSON 能不能被解析、TOML 里的环境变量有没有真的注入、端口有没有被占用。这三步能挡掉后面一大半报错。4. 本地联调验证从发任务到拿到结果配置就绪后联调分四步起服务、拉 Agent Card、发任务、查状态。先起服务假设你用 Python 的 HTTP transportexport TAOTOKEN_API_KEY你的Key export A2A_BEARER_TOKEN本地联调用的token python -m your_agent.server --config ./agent-config.toml服务起来后第一件事是验证 Agent Card 能被发现curl -s http://localhost:8080/.well-known/agent.json | python -m json.tool预期返回就是第 3 节那份 JSONname、skills、capabilities字段都在。如果这里返回 404说明 Agent Card 的暴露路径没配对检查服务端路由。第二步发一个任务。A2A 的任务下发走POST /tasks/sendcurl -s -X POST http://localhost:8080/tasks/send \ -H Authorization: Bearer 本地联调用的token \ -H Content-Type: application/json \ -d { id: task-001, message: { role: user, parts: [ { type: text, text: 请分析这封邮件的情感倾向 } ] }, metadata: { action: email_summarization, trace_id: trace-001 } } | python -m json.tool预期返回里status.state先是submitted或working任务完成后变completedartifacts里带结果。如果开了 streaming会先收到若干 chunk 再收到 complete 信号。第三步查任务状态curl -s -X POST http://localhost:8080/tasks/get \ -H Authorization: Bearer 本地联调用的token \ -H Content-Type: application/json \ -d {id: task-001} | python -m json.tool预期state字段在submitted → working → completed之间流转stateTransitionHistory为 true 时还能看到完整转换记录。第四步验证模型调用真的通了。这一步最容易出问题因为 A2A 层通了不代表模型层通了。单独打一次模型请求curl -s https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -H Content-Type: application/json \ -d { model: your-model-id, messages: [{role: user, content: ping}] } | python -m json.tool预期返回choices数组里面有模型回复。如果这一步失败问题在模型凭证层跟 A2A 无关先修这里。四步都过说明 A2A 协议层和模型调用层都通了可以开始接第二个 Agent 做真正的多 Agent 协作。5. 常见报错排查401、local proxy failed、reading choices、OAuth联调阶段报错集中在四类逐个对照。401 Unauthorized。两种可能A2A 层的 bearer token 不对或者模型层的 Key 不对。区分方法——如果/.well-known/agent.json能拉到但/tasks/send返回 401是 A2A 层 token 问题检查A2A_BEARER_TOKEN和请求头是否一致如果 A2A 全通但模型请求 401是 TaoToken Key 问题检查TAOTOKEN_API_KEY是否注入、有没有多余空格。注意 Key 不要写进 Agent Card那是给别的 Agent 看的不是放密钥的地方。local proxy failed。这个报错通常出现在客户端配置了本地代理但代理没起来或者 Base URL 写成了本地地址。检查你的base_url是不是https://taotoken.net/api别写成http://localhost之类。如果客户端有代理相关配置项确认它指向的是正确的 API 基址而不是一个不存在的本地端口。reading choices 相关报错类似cannot read property choices of undefined。这是模型返回体结构不符合预期常见原因是 Model ID 写错导致返回了错误对象或者请求根本没到模型层。排查顺序先确认 Model ID 和模型对话页面里的一致再确认 Base URL 结尾没有多余斜杠最后看返回体原始内容——如果返回的是{error: ...}说明请求被拒不是解析问题。OAuth 相关报错。A2A 的authentication.schemes如果声明了oauth2但服务端没实现对应的 token 校验就会在握手阶段失败。本地联调建议先用bearer简化等协议层跑通再上 OAuth。如果必须用 OAuth检查 clientId、clientSecret、scopes 三件套是否齐全scopes 要和 Agent Card 里声明的一致。排查通用动作把请求的原始返回体打出来看别只看封装后的异常信息。A2A 的错误经常被客户端包装过原始体里才有真正的 error_code。另外任务卡在working不动的多半是模型调用超时把timeout_seconds调大或检查网络到 API 基址的连通性。6. 把凭证收敛到一处多 Agent 场景的长期做法多 Agent 跑起来之后凭证管理会变成主要矛盾。假设你有五个 Agent每个都调模型如果每个 Agent 各配一套 Key轮换一次要改五处限额也没法统一看。正确做法是所有 Agent 的模型调用都走同一个 TaoToken 通道Key 只在环境变量里注入一次Agent Card 里只声明 A2A 层的认证不碰模型 Key。具体落地每个 Agent 的agent-config.toml里base_url和api_key都指向同一套model_id按 Agent 职责区分。这样你换模型只改配置轮换 Key 只改环境变量审计时所有调用都从一个出口走。Agent 之间用 A2A 的 bearer token 互相认证和模型凭证彻底解耦。验证模型连通性用模型对话页面长期跑 Agent 编排或编码任务用 Coding Plan接入参数和字段说明查接入文档Key 的创建和轮换在 api-keys 管理。这套组合下来你的多 Agent 系统在凭证层就是收敛的不会随着 Agent 数量增长而失控。最后给一个实用技巧给每个 Agent 的请求都带上trace_id从 A2A 任务层一路透传到模型调用层。这样出问题时你能从一条 trace 串起「哪个 Agent 发的任务 → 任务状态怎么流转 → 模型调用返回了什么」排查效率比翻多个日志文件高得多。A2A 的metadata字段就是干这个用的别浪费。