ARTICLE DETAIL

资讯详情

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

一文搞懂MCP、Function Calling和A2A:用TaoToken统一Key跑通三种Agent调用范式

一文搞懂MCP、Function Calling和A2A:用TaoToken统一Key跑通三种Agent调用范式 1. 三种 Agent 调用范式到底在解决什么问题如果你刚开始接触 AI Agent很容易被 MCP、Function Calling、A2A 这三个词绕晕。它们听起来都像“让模型调工具”但实际分工完全不同。我先把结论摆出来Function Calling 解决的是“模型怎么决定调哪个函数”MCP 解决的是“Agent 怎么发现和接入外部工具”A2A 解决的是“多个 Agent 之间怎么互相派活”。三者不是替代关系而是从模型层、工具层、协作层三个维度把 Agent 拼完整。举个具体场景。你做一个“帮我查杭州明天天气并决定要不要带伞”的 Agent。模型需要先判断“查天气”这个动作该调用哪个函数这是 Function Calling这个查天气的函数可能来自一个独立的天气服务Agent 通过 MCP 去发现并注册它如果任务再复杂一点比如查完天气还要让另一个专门负责“出行建议”的 Agent 给建议这两个 Agent 之间的通信就是 A2A。所以一个稍微像样的多工具 Agent三种范式往往同时存在。很多人卡住的地方不是概念而是落地时不知道从哪里下手。比如 Function Calling 需要你在请求里写 tools 数组MCP 需要你起一个 server 进程并配置 clientA2A 需要你暴露 agent card 和 JSON-RPC 端点。更麻烦的是这三套东西如果各自接不同的模型服务商Key 和 Base URL 会散落在四五个配置文件里调试时根本不知道是模型没返回 tool_calls还是 MCP server 没启动还是 A2A 的任务状态没轮询到。这篇就按“同一任务、三种范式、统一 Key”的思路来写。我会用 TaoToken 作为统一的 API 通道把 Function Calling、MCP、A2A 三种调用都指向同一个 Base URL 和同一个 Key这样你排障时只需要盯一个入口。任务统一用“查杭州天气并给出是否带伞建议”方便你对照三种范式的请求构造和返回校验。下面先讲 TaoToken 的前置配置再逐个给可复制的代码和配置片段最后附一份我实际踩过的报错清单。适合谁看已经能跑通一次大模型对话、想往多工具 Agent 方向走的开发者正在用 Cline、Claude Code、Codex 这类工具、想搞清底层调用链的人以及被 401、local proxy failed、reading choices 这些报错折磨过、想找统一排查路径的人。你不需要先精通 JSON-RPC但至少要能看懂 Python 和 JSON。2. TaoToken 统一 Key 与 API 通道前置配置在写三种范式之前先把“统一入口”这件事做掉。否则你会在 Function Calling 里填一个 Key在 MCP server 里填另一个在 A2A 的 agent 配置里再填一个最后出问题根本没法定位。TaoToken 的作用就是提供一个兼容 OpenAI 风格的 API 通道让你用同一个 Base URL 和同一个 Key 去访问不同模型三种范式都走这一个出口。先拿 Key。打开 https://taotoken.net/api-keys 登录后创建一个 API Key复制出来形如sk-xxxxxxxx。这个 Key 后面会出现在三个地方Function Calling 的客户端初始化、MCP server 里调用模型的配置、A2A agent 执行任务时的模型调用。建议你把它写进环境变量不要硬编码在代码里后面所有片段都按环境变量读取。# Linux / macOS export TAOTOKEN_API_KEYsk-你的key export TAOTOKEN_BASE_URLhttps://taotoken.net/api # Windows PowerShell $env:TAOTOKEN_API_KEYsk-你的key $env:TAOTOKEN_BASE_URLhttps://taotoken.net/apiBase URL 这里要特别注意TaoToken 的 API 入口是https://taotoken.net/api不要带任何多余路径。很多 OpenAI 兼容客户端会自动在末尾拼/v1/chat/completions所以你在配置里只写到/api就行。如果你用的是需要完整 endpoint 的场景那就是https://taotoken.net/api/v1/chat/completions。我试过在 Cline 和 Claude Code 里都只填 Base URL客户端自己拼路径没问题。模型 ID 怎么选Function Calling 场景建议用支持 tools 参数的模型比如gpt-4o、claude-3-5-sonnet这类。MCP 场景里模型只负责决策工具执行在 server 侧所以模型选择可以更宽松。A2A 场景因为涉及多轮任务状态建议用上下文窗口大一点的模型。你可以在 https://taotoken.net/models 看到当前可用的模型列表选一个支持 function calling 的即可。验证 Key 是否可用先用一条最简单的 curl 打一发curl -s https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -H Content-Type: application/json \ -d { model: gpt-4o, messages: [{role: user, content: 只回复两个字通了}] }如果返回里有choices[0].message.content且内容是“通了”说明 Key 和通道都正常。如果返回 401先检查 Key 有没有复制全、有没有多余空格如果返回 model not found去模型列表确认模型 ID 拼写。这一步过了再往下走能省掉后面一半的排障时间。还有一个容易忽略的点MCP server 如果跑在本地 stdio 模式它本身不直接调模型但你的 Agent 客户端比如 Cline会调模型。所以 MCP 场景下TaoToken 的 Key 是配在 Agent 客户端里的不是配在 MCP server 里的。这个区分很重要后面第 4 节会再强调。3. 三种范式的可复制配置与请求构造这一节是核心我按 Function Calling、MCP、A2A 的顺序各给一套可复制的最小配置。三套都指向同一个 TaoToken Base URL 和 Key任务都是“查杭州天气并给带伞建议”。你可以先跑通 Function Calling再跑 MCP最后跑 A2A逐层加复杂度。3.1 Function Calling模型侧的工具调用Function Calling 的本质是在请求里带上tools数组模型返回tool_calls你在本地执行函数后再把结果塞回对话。先写一个最小的 Python 脚本import os, json from openai import OpenAI client OpenAI( api_keyos.environ[TAOTOKEN_API_KEY], base_urlos.environ[TAOTOKEN_BASE_URL], ) tools [{ type: function, function: { name: get_forecast, description: 获取指定城市明天的天气, parameters: { type: object, properties: { city: {type: string, description: 城市名称} }, required: [city] } } }] def get_forecast(city: str) - str: return f{city}明天有大暴雨 resp client.chat.completions.create( modelgpt-4o, messages[{role: user, content: 杭州明天天气如何要带伞吗}], toolstools, tool_choiceauto, ) msg resp.choices[0].message if msg.tool_calls: call msg.tool_calls[0] args json.loads(call.function.arguments) result get_forecast(args[city]) print(工具返回:, result)跑通后你会看到工具返回: 杭州明天有大暴雨。这里的关键是tool_choiceauto让模型自己决定要不要调工具。如果你发现模型不调工具直接把tool_choice改成{type: function, function: {name: get_forecast}}强制调用先确认链路通再放开自动决策。3.2 MCP工具发现与注册MCP 和 Function Calling 最大的区别是Function Calling 的工具定义写在你的请求里MCP 的工具定义由独立的 server 提供client 通过 JSON-RPC 去发现。先建一个 MCP server# mcp_weather_server.py from mcp.server.fastmcp import FastMCP mcp FastMCP(weather) mcp.tool() def get_forecast(city: str) - str: 获取指定城市明天的天气 return f{city}明天有大暴雨 if __name__ __main__: mcp.run(transportstdio)然后在 Cline 或 Claude Code 的 MCP 配置里注册它。以 Cline 的cline_mcp_settings.json为例{ mcpServers: { weather: { command: uv, args: [run, mcp_weather_server.py], env: { TAOTOKEN_API_KEY: sk-你的key, TAOTOKEN_BASE_URL: https://taotoken.net/api } } } }注意这里的三件套Base URL 是https://taotoken.net/apiKey 是sk-你的keyModel ID 在 Agent 客户端的模型设置里单独选比如gpt-4o。MCP server 本身不调模型但 Agent 客户端调模型时用的就是这套配置。配置完重启客户端看到 weather 工具变绿就说明 MCP server 注册成功。3.3 A2AAgent 之间的任务派发A2A 的场景是“一个 Agent 把子任务派给另一个 Agent”。最小实现需要两个角色一个 A2A server 暴露 agent card 和任务端点一个 A2A client 发任务。先写 server# a2a_server.py from fastapi import FastAPI from pydantic import BaseModel import uuid app FastAPI() class TaskRequest(BaseModel): task: str app.get(/.well-known/agent.json) def agent_card(): return { name: weather-agent, description: 查询天气并给出带伞建议, url: http://localhost:8000, skills: [weather_query] } app.post(/tasks/send) def send_task(req: TaskRequest): task_id str(uuid.uuid4()) return { id: task_id, status: completed, artifacts: [{parts: [{type: text, text: f{req.task}建议带伞}]}] }client 侧发任务import requests card requests.get(http://localhost:8000/.well-known/agent.json).json() print(发现 Agent:, card[name]) resp requests.post(http://localhost:8000/tasks/send, json{task: 杭州明天天气}) print(任务结果:, resp.json()[artifacts][0][parts][0][text])A2A 的模型调用发生在 server 内部如果你要让 server 真正用模型生成建议就在 server 里用 TaoToken 的 Base URL 和 Key 初始化一个 OpenAI client。这样三种范式就都统一到同一个通道了。4. 验证请求与成功结果对照配置写完不算完得有一套统一的验证方法。我建议你按“先单点、再串联”的顺序验每一步都有明确的成功标志避免一上来就跑全链路然后不知道哪层挂了。第一步验 Function Calling。跑 3.1 的脚本成功标志是控制台打印工具返回: 杭州明天有大暴雨。如果只打印了模型的自然语言回复、没有工具调用说明模型没触发 tool_calls先把tool_choice改成强制调用再试。这一步验证的是“模型能不能正确决定调工具”。第二步验 MCP。启动 Cline 或 Claude Code在对话框输入“杭州明天天气如何”。成功标志是 Agent 主动调用get_forecast工具并返回带“大暴雨”的结果。你可以在 MCP server 的日志里看到tools/list和tools/call两条 JSON-RPC 记录。这一步验证的是“工具能不能被正确发现和注册”。第三步验 A2A。先起 serveruvicorn a2a_server:app --port 8000再跑 client 脚本。成功标志是打印发现 Agent: weather-agent和任务结果: 杭州明天天气建议带伞。这一步验证的是“Agent 之间能不能正确派发任务”。第四步做统一通道验证。把三个场景的 Base URL 都确认成https://taotoken.net/apiKey 都读同一个环境变量。然后故意改错 Key看三个场景是不是都报 401。如果只有某一个报错说明那个场景还在用旧的 Key 或旧的 Base URL没真正统一。这一步验证的是“排障入口是否收敛到一个”。成功结果的对照表可以这样记范式成功标志关键返回字段Function Calling打印工具返回choices[0].message.tool_callsMCPAgent 调用工具并返回结果JSON-RPCtools/call响应A2Aclient 打印任务结果artifacts[0].parts[0].text如果你在第三步发现 A2A 的 server 起来了但 client 连不上先确认端口没被占用再确认 agent card 的 URL 和实际监听地址一致。A2A 的发现机制依赖/.well-known/agent.json这个固定路径路径写错就发现不了。5. 常见报错排查清单这一节列我实际遇到过的报错按报错原文对照排查。你遇到问题时先在这里找找不到再去翻文档。401 Unauthorized。最常见的原因是 Key 没读到环境变量。检查echo $TAOTOKEN_API_KEY有没有输出Windows 下检查是不是在同一个终端会话里设的。另一个原因是 Base URL 写成了https://taotoken.net/api/带尾斜杠某些客户端会拼成//v1改成不带尾斜杠即可。如果 Key 是从网页复制的注意有没有把前后空格带进去。local proxy failed。这个报错通常出现在 Agent 客户端配置了本地代理但代理没起来。如果你在 Cline 或 Claude Code 里看到它先检查客户端设置里有没有填 proxy 地址清空后重试。TaoToken 的通道不需要额外代理配置Base URL 直接填https://taotoken.net/api就行。reading choices 相关报错。一般是返回体不是预期的 JSON 结构常见于 Base URL 拼错导致打到了网页而不是 API。确认你的 endpoint 是https://taotoken.net/api/v1/chat/completions返回的 content-type 是application/json。如果返回的是 HTML说明路径错了。OAuth 相关报错。如果你用的是 Claude Code 或 Codex 这类带 OAuth 流程的工具报 OAuth 失败时先确认你走的是 API Key 模式而不是账号登录模式。在配置里显式填 Base URL 和 Key不要依赖自动登录。Codex 的auth.json里要写全三件套Base URL、Key、Model ID缺一个都可能走到默认的登录流程。MCP server 启动失败。先单独在终端跑uv run mcp_weather_server.py看有没有 Python 报错。如果单独跑没问题但客户端里起不来检查配置里的command和args路径是不是绝对路径相对路径在不同工作目录下会找不到文件。A2A 任务一直 pending。检查 server 的/tasks/send是不是同步返回了 completed 状态。如果你用了流式或异步任务client 需要轮询tasks/get别只发一次就等结果。最小实现先用同步返回跑通再加流式。模型不调工具。Function Calling 场景下模型不返回 tool_calls先确认模型本身支持 function calling再把tool_choice改成强制调用。MCP 场景下 Agent 不调工具检查工具描述是不是太模糊把 description 写清楚“获取指定城市明天的天气”比“天气工具”更容易被选中。6. 把三种范式串成一条可维护的链路跑通三种范式之后真正要花心思的是怎么让它们在一个项目里共存而不互相打架。我的做法是所有模型调用都收敛到一个 client 工厂函数Base URL 和 Key 只在这里读一次环境变量Function Calling、MCP server 内部、A2A server 内部都调这个工厂。这样换 Key 或换模型只改一个地方。工具层用 MCP 统一注册Function Calling 的 tools 数组从 MCP 的tools/list结果动态生成避免手写两份定义导致不一致。A2A 的 agent card 里声明的 skills 也引用同一份工具清单。这样工具加一个三个范式自动都能用。排障时按“模型层 → 工具层 → 协作层”的顺序查先确认 TaoToken 通道通不通再确认 MCP 工具注册没注册上最后确认 A2A 任务状态流转对不对。因为三层共用同一个 Base URL 和 Key你只要盯一个入口就能快速定位是哪一层的问题。如果你要长期跑编码类或 Agent 类任务可以考虑用 Coding Plan 把调用额度固定下来避免按次计费时频繁关注余额。模型对话调试用 https://taotoken.net/model-chat 接入文档在 https://taotoken.net/doc API Key 管理在 https://taotoken.net/api-keys 。Claude Code 相关配置参考 https://taotoken.net/claude-code-anthropic 控制台在 https://taotoken.net/console 。把这些入口存成书签下次配新 Agent 时直接照着填三件套就行。
返回列表