1. 从 MCP 到 A2A:多厂商 Agent 协作到底缺了什么
如果你最近在折腾 Agent 开发,大概率已经被 MCP(Model Context Protocol)刷过屏。MCP 解决的是「Agent 怎么调用工具和上下文」的问题——把数据库、文件系统、搜索 API 包装成统一的 Server,模型侧通过标准协议去调用。但真正上手做多 Agent 系统时,你会发现一个更棘手的问题:不同厂商、不同框架构建的 Agent 之间,怎么互相通信、发现能力、协商任务?
这就是谷歌开源 A2A(Agent2Agent)协议要解决的事。简单说,MCP 是「Agent 连接工具」,A2A 是「Agent 连接 Agent」。前者让单个 Agent 变强,后者让一群 Agent 能组队干活。A2A 基于 HTTP、SSE、JSON-RPC 这些现有标准构建,核心概念包括 Agent Card(用 JSON 描述自身能力)、Task(有生命周期的任务对象)、Artifact(任务产出物),以及消息协商机制。它默认支持企业级认证授权,能跑长时间任务,模态无关。
那这跟 TaoToken 有什么关系?实际开发中,你往往需要同时对接多个模型厂商的 Agent——比如用 Claude 做规划、用 Gemini 做检索、用国产模型做本地化处理。每个厂商一套 Key、一套鉴权、一套计费,配置散落在各处,调试时切换成本极高。TaoToken 提供统一 API Key,把多厂商模型的调用收敛到一个入口,配合 A2A 的 Agent 协作场景,你可以在 settings.json 和 config.toml 里用同一套凭证驱动多个 Agent。下面我会给出可直接复制的配置骨架,以及多厂商 Agent 协作的验证步骤和排错清单。
2. TaoToken 前置准备:统一 Key 与接入信息
在开始配置 A2A Agent 之前,你需要先拿到 TaoToken 的 API Key,并确认接入地址。这一步不复杂,但有几个细节容易踩坑。
首先访问 TaoToken 官网注册并登录,进入控制台后创建 API Key。建议按用途分 Key,比如一个用于开发调试、一个用于生产 Agent 调用,方便后续排查问题时定位来源。创建完成后把 Key 复制保存,它只会完整显示一次。
接入地址方面,API 端点是https://taotoken.net/api,这个地址不加任何查询参数,直接作为 base_url 使用。官网地址是https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=,控制台和文档入口都在里面。
| 项目 | 值 | 说明 |
|---|---|---|
| API Base URL | https://taotoken.net/api | 所有模型调用的统一入口 |
| 鉴权方式 | Bearer Token | 请求头Authorization: Bearer <你的Key> |
| 控制台 | 官网内 console 入口 | 管理 Key、查看用量 |
| 接入文档 | 官网内 doc 入口 | 各语言 SDK 示例 |
| 模型对话 | 官网内模型对话入口 | 在线验证模型可用性 |
| Coding Plan | 官网内 coding-plan 入口 | 长期编码/Agent 场景套餐 |
拿到 Key 后,先别急着写 Agent 配置。建议用模型对话功能做一次最小验证,确认 Key 有效、网络可达、模型列表正常返回。这一步能帮你排除掉大部分「配置写了但跑不通」的问题。验证通过后再进入下面的配置文件环节。
注意:API Key 不要硬编码在会提交到 Git 的配置文件里。开发阶段可以用环境变量注入,生产环境建议走密钥管理服务。
3. 可复制配置:settings.json 与 config.toml 骨架
A2A Agent 的配置通常分两部分:一部分是 Agent 自身的运行参数(用 settings.json),另一部分是模型接入和工具链配置(用 config.toml)。下面给出的是骨架,你可以直接复制后替换 Key 和模型名。
3.1 settings.json:Agent 运行与 A2A 端点配置
{ "agent": { "name": "planner-agent", "version": "1.0.0", "description": "负责任务规划与分解的客户端 Agent", "capabilities": { "streaming": true, "pushNotifications": false, "longRunningTasks": true }, "defaultInputModes": ["text/plain"], "defaultOutputModes": ["text/plain", "application/json"], "skills": [ { "id": "task-decomposition", "name": "任务分解", "description": "将复杂任务拆解为可执行的子任务", "tags": ["planning", "decomposition"] } ] }, "a2a": { "endpoint": "http://localhost:8080/a2a", "agentCardPath": "/.well-known/agent.json", "auth": { "type": "bearer", "tokenEnv": "TAOTOKEN_API_KEY" }, "peerAgents": [ { "name": "retrieval-agent", "url": "http://localhost:8081/a2a", "description": "负责信息检索的远程 Agent" }, { "name": "executor-agent", "url": "http://localhost:8082/a2a", "description": "负责代码执行的远程 Agent" } ] }, "runtime": { "maxConcurrentTasks": 4, "taskTimeoutSeconds": 300, "logLevel": "info" } }这份配置里,agent段描述自身能力,对应 A2A 的 Agent Card 概念;a2a.peerAgents列出你要协作的远程 Agent 地址;auth.tokenEnv指向环境变量,避免 Key 明文落盘。
3.2 config.toml:模型接入与工具链配置
[model] provider = "taotoken" base_url = "https://taotoken.net/api" api_key_env = "TAOTOKEN_API_KEY" default_model = "claude-3-5-sonnet" fallback_model = "gemini-1.5-pro" timeout_seconds = 120 max_retries = 3 [model.routing] # 按任务类型路由到不同模型 planning = "claude-3-5-sonnet" retrieval = "gemini-1.5-pro" code_execution = "claude-3-5-sonnet" [mcp] enabled = true servers = [ { name = "filesystem", command = "npx", args = ["-y", "@modelcontextprotocol/server-filesystem", "./workspace"] }, { name = "fetch", command = "npx", args = ["-y", "@modelcontextprotocol/server-fetch"] } ] [a2a] enabled = true agent_card_ttl_seconds = 60 task_poll_interval_ms = 500 max_message_size_kb = 512 [logging] level = "info" format = "json" output = "./logs/agent.log"config.toml里最关键的是[model]段:base_url固定为 TaoToken 的 API 地址,api_key_env指向环境变量,default_model和fallback_model做容错。[model.routing]让你按任务类型把请求分发到不同模型,这在多 Agent 协作里很实用——规划类任务用推理强的模型,检索类任务用长上下文模型。
3.3 环境变量注入
export TAOTOKEN_API_KEY="sk-你的实际Key" export A2A_AGENT_PORT=8080 export LOG_LEVEL=infoWindows PowerShell 用$env:TAOTOKEN_API_KEY="sk-..."。设置完可以用echo $TAOTOKEN_API_KEY确认是否生效。
4. 验证请求:多厂商 Agent 协作跑通
配置写完后,需要分三步验证:先验证单模型调用,再验证 A2A Agent Card 发现,最后验证多 Agent 任务协作。
4.1 验证 TaoToken 模型调用
用 curl 发一个最小请求,确认 Key 和 base_url 正确:
curl -X POST https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "claude-3-5-sonnet", "messages": [{"role": "user", "content": "回复 OK 两个字母"}], "max_tokens": 10 }'如果返回 JSON 里choices[0].message.content包含 OK,说明模型接入正常。如果返回 401,检查 Key 是否复制完整;返回 404,检查 base_url 是否多了斜杠或路径。
4.2 验证 Agent Card 发现
启动你的 Agent 服务后,访问 Agent Card 端点:
curl http://localhost:8080/.well-known/agent.json正常应返回类似:
{ "name": "planner-agent", "version": "1.0.0", "capabilities": {"streaming": true, "longRunningTasks": true}, "skills": [{"id": "task-decomposition", "name": "任务分解"}] }这一步验证的是 A2A 的「能力发现」机制。如果返回 404,检查agentCardPath配置和路由注册;如果返回 500,看 Agent 启动日志里有没有序列化错误。
4.3 验证多 Agent 任务协作
用一个简单任务串起两个 Agent:planner-agent 接收任务后,通过 A2A 调用 retrieval-agent 获取信息,再返回结果。
import httpx import asyncio async def send_task(agent_url, task_text): async with httpx.AsyncClient(timeout=60) as client: resp = await client.post( f"{agent_url}/tasks", json={ "jsonrpc": "2.0", "method": "tasks/send", "params": { "id": "task-001", "message": { "role": "user", "parts": [{"type": "text", "text": task_text}] } }, "id": 1 } ) return resp.json() async def main(): result = await send_task("http://localhost:8080/a2a", "帮我检索 A2A 协议的核心概念") print(result) asyncio.run(main())预期返回里包含result.status.state为completed或working,以及artifacts字段。如果状态一直是submitted,说明任务没被消费,检查 Agent 的任务队列和 worker 是否启动。
实测下来,多 Agent 协作最容易出问题的地方是任务状态同步——客户端 Agent 发出任务后,远程 Agent 处理完但没回传 artifact,导致调用方一直轮询。建议在config.toml里把task_poll_interval_ms设小一点,同时给远程 Agent 加超时兜底。
5. 本篇常见错排查清单
下面这些报错是我在配置 A2A + TaoToken 时实际遇到过的,按出现频率排序。
401 Unauthorized / invalid api key最常见。原因通常是环境变量没生效、Key 复制时带了空格、或者用了错误的鉴权头格式。检查echo $TAOTOKEN_API_KEY输出是否完整,请求头是否为Authorization: Bearer sk-xxx。如果 Key 是在 Windows 下复制的,注意有没有隐藏的换行符。
404 Not Found on /a2a/tasksA2A 端点路径没注册对。检查 settings.json 里a2a.endpoint和实际路由是否一致。有些框架默认路径是/tasks而不是/a2a/tasks,需要显式配置。
Agent Card 返回空 skills 数组skills字段没填或格式不对。A2A 要求每个 skill 有id、name、description,缺一个都可能导致发现失败。另外capabilities里的布尔值别写成字符串。
任务一直处于 working 状态不结束远程 Agent 处理完了但没发tasks/completed事件。检查远程 Agent 的 SSE 推送是否正常,或者任务超时时间设得太长。可以在config.toml里把taskTimeoutSeconds调小做测试。
模型路由不生效,所有请求都走 default_model[model.routing]的 key 必须和代码里传入的 task type 完全匹配,大小写敏感。另外有些框架需要显式开启 routing 开关,检查文档里有没有routing.enabled之类的配置。
MCP Server 启动失败导致 Agent 起不来config.toml里[mcp]段的 command 和 args 要能在当前环境执行。npx需要 Node.js 环境,路径参数用相对路径时注意工作目录。建议先用命令行单独跑一遍 MCP Server 命令,确认能启动再写进配置。
多 Agent 之间消息格式不兼容A2A 的消息parts数组里每个 part 要有type字段。如果一方发text/plain,另一方只接受application/json,就会协商失败。在 Agent Card 的defaultInputModes和defaultOutputModes里把支持的格式都列上。
提示:排查时优先看 Agent 启动日志和请求日志,大部分问题在日志里都有明确线索。TaoToken 控制台也能看到 API 调用记录,方便区分是模型侧问题还是 Agent 侧问题。
6. 继续深入:从单 Agent 到多 Agent 协作的下一步
配置跑通只是起点。真正把 A2A 用起来,你还需要考虑几件事:Agent Card 的动态更新(能力变化时怎么通知 peer)、长任务的断点续传(任务跑到一半 Agent 重启了怎么办)、以及多厂商模型的路由策略(什么任务交给哪个模型性价比最高)。
如果你主要做长期编码或 Agent 开发,可以看看 Coding Plan,它针对高频调用场景做了额度优化。需要在线验证模型效果,直接用模型对话功能试不同厂商的模型输出。接入过程中遇到鉴权或配置问题,API Keys 管理页面和接入文档里有各语言的完整示例。
A2A 和 MCP 不是替代关系,而是互补。MCP 让 Agent 能调用工具,A2A 让 Agent 能调用 Agent。把这两层都配好,再配合 TaoToken 的统一 Key 收敛多厂商调用,你就能用一套配置驱动一个能协作的 Agent 团队,而不是维护一堆散落的凭证和端点。