1. 概念混战:Agent Skills、Tool、MCP、Function Call 到底谁管谁
如果你最近在搭 AI Agent,大概率被这四个词轮番轰炸过:Function Call、Tool、MCP、Agent Skills。我第一次听到 Agent Skills 时,下意识以为它是 MCP 的竞品,结果翻完文档才发现方向完全错了——它跟 Tool 更像一家人,跟 MCP 根本不在一个维度上。
先把结论摆出来,方便你带着框架往下读:Function Call 是模型的原生能力,Tool 是 Function Call 的工程封装,MCP 是跨系统调用 Tool 的协议,Agent Skills 是把 Tool 组合成可复用能力的更高层抽象。一句话串起来就是:Agent 通过 MCP 协议,借助 Skills 组织,最终调用 Tool,而这一切都跑在 Function Call 之上。
为什么容易混?因为这四个词经常出现在同一段介绍里,但它们描述的层次完全不同。Function Call 说的是"模型能不能输出结构化调用意图",Tool 说的是"这个意图对应哪段可执行代码",MCP 说的是"不同服务之间怎么用统一格式交换工具描述和调用结果",Agent Skills 说的是"把一组工具和提示词打包成一个开箱即用的能力单元"。
我试过用一个类比帮你记住:Function Call 是你会说"帮我查天气"这句话的能力;Tool 是你手机里那个天气 App;MCP 是 USB 接口标准,让任何厂商的 App 都能插进同一个系统;Agent Skills 则是一个"出行助手"套装,里面预装了天气 App、地图 App、打车 App,还附带了"下雨就打车、晴天就骑车"的判断逻辑。你不需要懂每个 App 怎么用,拿到这个套装就能直接干活。
对正在搭 Agent 的开发者来说,搞不清边界的代价很实在:你会把该用 MCP 的地方硬写成 Tool,把该封装成 Skill 的逻辑散落在 prompt 里,最后维护成本爆炸。这篇就按"定义边界 → 协作关系 → 可复制配置 → 跑通验证 → 排错"的顺序走一遍,每个概念都配一个能上手的最小 Demo。
先给一张对照表,后面所有内容都围绕它展开:
| 维度 | Function Call | Tool | MCP | Agent Skills |
|---|---|---|---|---|
| 本质 | 模型原生能力 | 功能模块封装 | 跨系统调用协议 | 能力组合抽象 |
| 层级 | 最底层 | 基础层 | 协议层 | 顶层 |
| 角色 | "能做什么" | "做什么" | "怎么统一调" | "一起做什么" |
| 复杂度 | 单次调用 | 单次调用 | 跨平台 | 多步骤协作 |
| 自主性 | 无 | 无 | 无 | 部分 |
| 典型产物 | JSON 参数 | 函数/接口 | server 描述 | 技能包 |
这张表建议你收藏,面试或者跟同事对齐认知时直接甩出来,比解释十分钟管用。接下来逐层拆开,每层都给可运行的验证动作。
2. TaoToken 统一通道:一个 Key 打通 Tool 调用与 MCP 接入
概念理清之后,落地时最烦的其实不是写代码,而是 Key 和 Base URL 满天飞。你调 OpenAI 格式的 Tool 用一个 Key,接 Claude 系模型换一个 Key,接 MCP server 又要配一套环境变量,调试时根本分不清是模型问题还是通道问题。
我的做法是统一走一个兼容层,把模型调用收敛到同一个 Base URL 和同一套 Key 上。这样 Tool 调用、MCP 接入、Function Call 验证都共用一条通道,出问题时排查范围直接砍一半。这里我用 TaoToken 作为统一通道来演示,它的接口兼容 OpenAI 格式,改 Base URL 就能接。
先说清楚它解决什么问题:你不需要为每个模型厂商维护独立的 SDK 和鉴权逻辑,Tool 的 schema、MCP server 的配置、Function Call 的请求体都走同一套格式。对 Agent 项目来说,这意味着你的工具层代码可以完全不动,只换底层通道。
具体操作分三步。第一步,去控制台创建一个 API Key,地址是 https://taotoken.net/api-keys ,创建后复制保存,后面所有配置都用它。第二步,确认你要用的模型 ID,不同模型在 Tool 调用上的表现差异挺大,建议先用一个支持 Function Call 的模型验证。第三步,把 Base URL 统一设成 https://taotoken.net/api ,注意这个地址不带任何查询参数,直接作为 OpenAI SDK 的 base_url 使用。
如果你用的是 Claude Code 这类工具,配置方式略有不同,需要设置 ANTHROPIC_BASE_URL 和对应的 Key,具体可以参考接入文档 https://taotoken.net/doc 。文档里有各语言的完整示例,比你自己试错快得多。
这里有个容易踩的坑:很多人把 Base URL 写成带/v1的完整路径,结果 SDK 又自动拼了一次,变成/v1/v1/chat/completions,直接 404。记住 base_url 只写到域名和/api,路径交给 SDK 拼。
统一通道之后,你的 Agent 项目结构会清爽很多:模型层只认一个 client,工具层只认 schema,MCP 层只认 server 配置。三者解耦,任何一层出问题都能单独替换。这也是为什么我建议在写第一行 Agent 代码之前,先把通道定下来——后面省的时间是复利的。
3. 可复制配置:Function Call、Tool、MCP 三件套最小片段
这一节直接给能复制粘贴的配置,覆盖 Function Call 请求体、Tool 定义、MCP server 配置三种形态。你按需取用,路径和字段名都跟实际一致。
先看 Function Call 的最小请求体。这是最底层的能力验证,模型返回的tool_calls字段就是它"决定调用哪个工具"的证据:
{ "model": "gpt-4o-mini", "messages": [ {"role": "user", "content": "北京今天天气怎么样?"} ], "tools": [ { "type": "function", "function": { "name": "get_weather", "description": "查询指定城市的实时天气", "parameters": { "type": "object", "properties": { "city": {"type": "string", "description": "城市名称"} }, "required": ["city"] } } } ], "tool_choice": "auto" }注意tools数组里每个元素就是一个 Tool 的定义,而模型输出的调用意图就是 Function Call。这两者的关系在这里体现得最清楚:Tool 是你给的菜单,Function Call 是模型点的菜。
再看 MCP server 的配置片段。MCP 的核心是把工具描述标准化,让不同来源的工具用同一套格式暴露出来。下面是一个典型的 MCP server 配置,放在你的客户端配置文件里:
{ "mcpServers": { "weather-server": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-weather"], "env": { "API_KEY": "your-key-here" } } } }这个配置告诉客户端:启动一个叫 weather-server 的 MCP 服务,它通过标准输入输出暴露工具。客户端连上后会自动拉取工具列表,你不需要手动写 schema——这就是 MCP 相比裸 Tool 的价值,工具描述由 server 自己声明。
最后是 Agent Skills 的配置形态。Skills 没有统一标准,但常见做法是一个目录加一个描述文件,把提示词、工具引用、执行逻辑打包:
[skill] name = "travel-assistant" description = "根据天气和交通情况推荐出行方式" version = "1.0.0" [skill.tools] required = ["get_weather", "get_traffic"] [skill.prompt] system = "你是一个出行助手,先查天气再查交通,最后给出建议。"三件套放一起看,层次就出来了:Function Call 是请求体里的一个字段,Tool 是tools数组里的定义,MCP 是独立的 server 配置,Skills 是更高层的打包文件。它们不是替代关系,是嵌套关系。
配置时有个细节要注意:MCP server 的command和args必须能在你的环境里直接执行,npx找不到包是最常见的启动失败原因。建议先在终端手动跑一遍npx -y @modelcontextprotocol/server-weather,确认能起来再写进配置。
4. 跑通验证:从 Tool 调用到 MCP 接入的成功结果长什么样
配置写完不算完,得看到真实返回才算跑通。这一节给你两个验证动作,一个验 Tool 调用,一个验 MCP 接入,都基于上一节的统一通道。
先验 Tool 调用。用 Python 写一个最小脚本,走 OpenAI SDK,Base URL 指向统一通道:
from openai import OpenAI client = OpenAI( api_key="你的Key", base_url="https://taotoken.net/api" ) resp = client.chat.completions.create( model="gpt-4o-mini", messages=[{"role": "user", "content": "北京今天天气怎么样?"}], tools=[{ "type": "function", "function": { "name": "get_weather", "description": "查询指定城市的实时天气", "parameters": { "type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"] } } }] ) print(resp.choices[0].message.tool_calls)跑通后你会看到类似这样的输出:
[ChatCompletionMessageToolCall( id='call_abc123', function=Function( arguments='{"city": "北京"}', name='get_weather' ), type='function' )]看到tool_calls里有name和arguments,说明 Function Call 成功,模型正确选择了 Tool 并生成了参数。这一步是整个 Agent 的地基,地基不稳后面全白搭。
再验 MCP 接入。MCP 的验证稍微复杂一点,因为要确认客户端能拉到工具列表。如果你用的是支持 MCP 的客户端,连上 server 后应该能看到工具被自动注册。验证方法是发一条会触发工具的消息,观察客户端日志里有没有tools/list的请求和响应。
成功的结果长这样:日志里先出现initialize握手,然后是tools/list返回工具清单,最后是tools/call执行具体调用。三步都出现,说明 MCP 链路通了。如果只看到initialize没有后续,多半是 server 启动后崩溃了,回去检查command能不能手动执行。
Agent Skills 的验证最直观:把 skill 目录加载进去,发一条自然语言指令,看它有没有按预设的 system prompt 走多步流程。比如问"明天去上海怎么走",理想结果是它先调天气工具,再调交通工具,最后综合给建议。如果只调了一个工具就停了,说明 skill 里的流程编排没生效。
验证阶段建议按 Function Call → Tool → MCP → Skills 的顺序逐层来,别跳步。底层没通就往上搭,出问题时你根本不知道是哪层的锅。每层都留一个能复现的最小用例,后面排错时直接拿来对比。
5. 常见报错排查:401、local proxy failed、reading choices、OAuth 逐个击破
这一节按真实报错来,每个都给你现象、原因、修法。这些是我和身边人踩过的坑,命中率很高。
401 Unauthorized。现象是请求直接被拒,返回体里带invalid_api_key或authentication_error。原因通常是 Key 没设对,或者设了但没生效。检查顺序:先确认环境变量名和代码里读的是同一个,很多人设了OPENAI_API_KEY但代码读API_KEY;再确认 Key 没有多余空格或换行,复制时特别容易带上;最后确认 Base URL 和 Key 是配套的,别拿 A 通道的 Key 去请求 B 通道。
local proxy failed。现象是连接超时或connection refused。这个报错名字容易误导,其实多半是本地网络配置或环境变量里的代理设置残留导致的。检查HTTP_PROXY、HTTPS_PROXY这类环境变量有没有被设成失效地址,清掉再试。另外确认 Base URL 拼写正确,少个字母也会连不上。
reading choices 报错。完整报错通常是Error reading choices或choices field missing。这说明请求发出去了、也返回了,但返回体结构不符合预期。常见原因是模型 ID 写错,通道返回了一个错误对象而不是正常的 completion 结构。检查model字段是不是通道支持的模型,别用了一个不存在的名字。另一个原因是流式和非流式搞混了,stream=True时返回的是 chunk 序列,直接读choices会出错。
OAuth 相关报错。如果你接的是 Claude Code 这类工具,可能遇到 OAuth 鉴权失败。现象是提示需要登录或 token 无效。这类工具通常需要设置ANTHROPIC_BASE_URL和ANTHROPIC_API_KEY两个变量,缺一个都会失败。配置方式参考接入文档,别自己猜变量名。设置完记得重启终端,环境变量不会热更新。
排查通用心法:先分层定位,再逐层排除。401 是鉴权层,proxy failed 是网络层,reading choices 是响应解析层,OAuth 是工具配置层。定位到层之后,用上一节的最小用例复现,改一个变量测一次,别一次改一堆。
还有个隐蔽的坑:MCP server 启动失败时,客户端有时不报错,只是工具列表为空。这时候去看客户端日志,找 server 的 stderr 输出,真正的错误信息都在那里。养成看日志的习惯,比盲目改配置快十倍。
6. 概念理清之后:把统一通道用起来的下一步
走到这里,四个概念的边界应该清楚了:Function Call 是能力底座,Tool 是执行单元,MCP 是连接标准,Agent Skills 是复用封装。它们不是四个竞品,是一条从底到顶的技术栈。你搭 Agent 时遇到的多数困惑,本质是把不同层的东西放一起比较了。
下一步建议按这个顺序推进:先用统一通道把 Function Call 跑通,确认模型能正确输出tool_calls;再把你的业务函数封装成 Tool,验证参数传递;然后如果有多系统协作需求,上 MCP 把工具标准化;最后把高频组合封装成 Skills,降低使用门槛。
统一通道的价值在项目变大后特别明显。当你有十几个工具、三四个 MCP server、若干 Skills 时,如果每个都维护独立的鉴权和地址,光是配置同步就能耗掉半天。收敛到一个 Base URL 和一套 Key,改一处全生效。
如果你还在选模型阶段,可以先用模型对话页面快速对比不同模型在 Tool 调用上的表现,地址是 https://taotoken.net/chat ,不用写代码就能试。确定模型后再落到代码里,省得反复改配置。
长期做编码和 Agent 开发的,建议直接上 Coding Plan,把通道、额度、模型切换都托管掉,你专注写工具逻辑就行,地址是 https://taotoken.net/coding-plan 。工具层的代码才是你项目的护城河,底层通道交给专业的事。
最后留一个实用习惯:每引入一个新概念,先问它处在哪一层,再问它和相邻层怎么交互。Function Call 和 Tool 是"能力与载体",Tool 和 MCP 是"单元与协议",MCP 和 Skills 是"连接与组合"。把这几个关系记牢,下次再冒出什么新名词,你也能快速定位它该待的位置,不被概念忽悠。