1. 从 Function Calling 到 Agent Skills:我踩过的三次工具调用坑
如果你在 2026 年还在用一套硬编码的 Function Calling 定义去接所有模型,大概率会遇到三个问题:换模型要重写工具定义、工具一多上下文直接爆炸、Agent 能连上工具但完全不知道怎么用。这三个问题分别对应了 AI 工具调用的三次进化:Function Calling 解决“能动手”,MCP 解决“手能通用”,Agent Skills 解决“知道怎么用好手”。
这篇内容面向正在做 AI 应用开发、Agent 编排或者智能硬件接入的开发者,尤其是那些已经用过 Function Calling、正在犹豫要不要上 MCP、又听说 Skills 但没搞清三者关系的人。我会用 TaoToken 的统一 Key 和 API 通道作为底座,把三个阶段的可复制配置、迁移路径和验证动作全部串一遍。你不需要同时掌握三代技术,只需要跟着每一节的配置骨架走,就能在自己的项目里跑通从 Function Calling 到 MCP 再到 Skills 的完整链路。
核心进化主线先记住:Function Calling(硬连接调用)→ MCP(标准化通用接口)→ Agent Skills(智能化业务实操)。下面按这条线拆。
2. TaoToken 前置:统一 Key 与 API 通道准备
在动手写任何配置之前,先把 TaoToken 的接入底座搭好。这一步的意义在于:不管你后面用 Function Calling、MCP 还是 Skills,底层都走同一个 API 通道和同一把 Key,迁移时只需要改上层配置,不用动网络层。
TaoToken 官网地址是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 端点统一为 https://taotoken.net/api 。你需要先去控制台创建一个 API Key,然后把它写进环境变量,后面所有配置都引用这个变量,避免硬编码泄露。
# 写入 shell 配置文件,Linux/macOS 用 ~/.bashrc 或 ~/.zshrc export TAOTOKEN_API_KEY="sk-你的实际key" export TAOTOKEN_BASE_URL="https://taotoken.net/api"Windows 用户可以在 PowerShell 里临时设置,或者写进系统环境变量:
$env:TAOTOKEN_API_KEY="sk-你的实际key" $env:TAOTOKEN_BASE_URL="https://taotoken.net/api"创建 Key 的入口在控制台的 API Keys 页面,建议按项目分 Key,方便后面排查是哪个应用在消耗额度。接入文档里有各语言 SDK 的示例,遇到 401 或 404 先对照文档检查 base_url 有没有多写或少写路径。
注意:TaoToken 的 API 端点是 https://taotoken.net/api ,不要在后面手动加 /v1 或其他后缀,具体路径以接入文档为准。Key 只放在环境变量或密钥管理服务里,不要提交到 Git。
这一步做完,你手里应该有一个可用的 Key 和一个统一的 base_url。接下来三个阶段的所有配置都会引用这两个值。
3. 阶段一:Function Calling 的可复制配置
Function Calling 是最基础的一层,模型不直接执行任务,而是输出结构化的调用请求,由你的程序去执行。它的配置核心是工具定义的 JSON Schema。下面是一个最小可用的 Python 示例,用 TaoToken 的 OpenAI 兼容接口。
import os import json from openai import OpenAI client = OpenAI( api_key=os.environ["TAOTOKEN_API_KEY"], base_url=os.environ["TAOTOKEN_BASE_URL"] ) tools = [ { "type": "function", "function": { "name": "get_weather", "description": "查询指定城市的天气预报", "parameters": { "type": "object", "properties": { "city": { "type": "string", "description": "城市名称,如 Hangzhou" } }, "required": ["city"] } } } ] response = client.chat.completions.create( model="gpt-4o-mini", messages=[{"role": "user", "content": "杭州明天天气怎么样"}], tools=tools, tool_choice="auto" ) print(response.choices[0].message.tool_calls)跑通之后你会看到模型返回一个 tool_calls 数组,里面包含函数名和参数。你的程序拿到这个 JSON 后去调真实 API,再把结果塞回 messages 里让模型组织自然语言回复。
Function Calling 的局限在工具数量超过 10 个之后会非常明显:每个工具的 Schema 都要塞进上下文,工具描述占用的 Token 会挤压对话空间;而且换一个模型或换一个应用,工具定义要重写一遍。这就是 MCP 要解决的问题。
4. 阶段二:MCP 的 settings.json 与 config.toml 骨架
MCP 把工具定义从你的代码里抽出来,变成一个独立的 Server 进程,通过标准协议对外暴露能力。你只需要在配置文件里声明要连哪个 Server,Host 会自动完成握手、工具发现和调用转发。
不同工具的配置文件格式不一样。Claude Desktop 和 Cline 用 JSON,Codex 类的工具用 TOML。下面给出两套骨架。
Claude Desktop 的 settings.json 位置在用户目录下的 claude 配置文件夹里,核心结构是 mcpServers:
{ "mcpServers": { "github": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"], "env": { "GITHUB_TOKEN": "your-github-token" } }, "filesystem": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/yourname/projects"] } } }Cline 的配置在 VS Code 的设置里,结构类似,但字段名可能略有差异,以 Cline 文档为准。关键是 command、args、env 三个字段:command 是启动 Server 的可执行文件,args 是参数,env 是环境变量。
Codex 类的 config.toml 骨架如下:
[mcp_servers.github] command = "npx" args = ["-y", "@modelcontextprotocol/server-github"] [mcp_servers.github.env] GITHUB_TOKEN = "your-github-token" [mcp_servers.filesystem] command = "npx" args = ["-y", "@modelcontextprotocol/server-filesystem", "/Users/yourname/projects"]如果你用的是 CC Switch 来管理多个 Claude Code 配置,可以在它的配置界面里直接粘贴上面的 JSON 片段,切换项目时不用手动改文件。CC Switch 的本质是帮你管理多套 settings.json,底层还是同一套 MCP 配置格式。
MCP 的传输方式有两种:stdio 用于本地 Server,sse/http 用于远程 Server。本地开发优先用 stdio,延迟低、不用管网络。远程 Server 适合团队共享,但要注意鉴权和超时。
配置写完后,重启对应的 Host 应用,它会在启动时连接所有声明的 Server。你可以在 Host 的日志里看到握手过程和工具列表。
5. 阶段三:Agent Skills 的目录结构与渐进式披露
Agent Skills 不是工具,也不是 Prompt,它是一个知识包,告诉 Agent 什么时候该用某个技能、具体怎么一步步做、有哪些坑。它的核心创新是渐进式披露:元数据常驻,技能主体按需加载,附加资源用到才读。
一个标准的 Skill 目录结构长这样:
skills/ └── code-review/ ├── SKILL.md # 主技能文件,包含元数据和指令 ├── check_security.py # 安全扫描脚本,需要时才执行 ├── style-guide.md # 代码风格参考,遇到风格问题才加载 └── templates/ └── review-comment.mdSKILL.md 的头部是元数据,用 YAML front matter 写:
--- name: "code-review" description: "当用户提交代码要求 Review、检查代码质量、或合并 PR 前审查时使用" triggers: - "review 代码" - "代码审查" - "检查代码质量" - "PR review" ---元数据只占约 100 Token,就算你装了 50 个 Skill,初始消耗也只有 5000 Token 左右。对比 MCP 连一个 Playwright Server 就占 16000+ Token,差距是数量级的。
技能主体写在元数据下面,要用 SOP 式的结构,不要写散文:
## Step 1 — 理解上下文 1. 确认变更的目的(修 Bug / 新功能 / 重构) 2. 查看关联的 Issue 或需求描述 3. 了解影响范围(涉及哪些模块) ## Step 2 — 逐层审查 1. 安全性:是否有 SQL 注入、XSS、硬编码密钥 2. 正确性:边界条件、空值处理、并发安全 3. 性能:是否有 N+1 查询、内存泄漏、死循环风险 4. 可维护性:命名清晰度、函数长度、重复代码 ## 完成标准 - [ ] 所有文件都已逐一审查 - [ ] 安全类问题标记为「必须修复」 - [ ] 每条审查意见标注了严重等级(P0/P1/P2) - [ ] 给出总体评价(通过 / 需修改 / 打回重写)Skill 内部可以编排 MCP 工具,比如在 Step 3 里写“使用 GitHub MCP Server 在 PR 上逐行添加 Review Comment”,这样 Skill 负责决策和编排,MCP 负责执行具体操作。
6. 逐阶段验证请求与成功结果
配置写完不算完,每一层都要有明确的验证动作。
Function Calling 的验证:跑上面的 Python 示例,看返回的 tool_calls 里 name 和 arguments 是否正确。如果模型直接返回自然语言而不是 tool_calls,检查 tools 参数有没有传对,tool_choice 是不是 auto。
MCP 的验证:重启 Host 后,在对话里问一个需要用到 MCP 工具的问题,比如“帮我列出 projects 目录下的文件”。如果 Host 日志里显示 Server 已连接但工具没被调用,检查工具描述是否清晰、触发词是否匹配。如果连接失败,先手动在终端跑一遍 command 和 args,看 Server 能不能独立启动。
Agent Skills 的验证:在对话里说一个匹配触发词的话,比如“帮我 review 这段代码”,观察 Agent 是否加载了对应的 Skill。如果没加载,检查 description 和 triggers 是否覆盖了用户的说法。加载后看 Agent 是否按 Step 1、Step 2 的顺序执行,完成标准是否被逐条检查。
三层都验证通过后,你可以做一个组合测试:让 Agent 用 Skill 编排 MCP 工具完成一个完整任务,比如“查一下本周的 Bug 列表,写封周报邮件”。观察它是否先加载 weekly-report-writer 这个 Skill,再调用 Jira MCP Server 查数据,最后调用邮件 MCP Server 发送。
7. 本篇常见错排查
报错一:401 Unauthorized。检查 TAOTOKEN_API_KEY 是否设置正确,有没有多余空格。如果用的是 SDK,确认 base_url 是 https://taotoken.net/api ,不要手动加 /v1。
报错二:MCP Server 启动失败。最常见的原因是 npx 找不到包或者 Node 版本太低。先在终端手动执行 command 和 args,看报什么错。如果是权限问题,检查 env 里的 Token 是否有效。
报错三:Skill 不加载。检查 SKILL.md 的 front matter 格式是否正确,name 和 description 是否都有。triggers 要覆盖用户可能说的多种说法,不要只写一个。
报错四:工具调用死循环。Skill 里没有写完成标准,Agent 不知道什么时候算做完。补上“完成标准”章节,用 checklist 形式列出退出条件。
报错五:上下文爆炸。如果用了 MCP 且工具数量很多,考虑把部分工具迁移到 Skill 里按需加载。MCP 适合高频、固定的工具,Skill 适合低频、复杂的领域任务。
报错六:CC Switch 切换后配置不生效。CC Switch 管理的是多套 settings.json,切换后需要重启对应的 Host 应用。检查当前激活的配置是不是你改的那一套。
8. 迁移路径与 CTA
从 Function Calling 迁移到 MCP,核心动作是把硬编码的工具定义抽成独立的 Server 进程,然后在 settings.json 或 config.toml 里声明。迁移过程中可以两者并存:高频简单工具继续用 Function Calling,跨应用共享的工具走 MCP。
从 MCP 迁移到 Skills,核心动作是把“怎么用工具”的领域知识从 Prompt 里抽出来,写成结构化的 SKILL.md。MCP 负责连接,Skill 负责编排,两者不是替代关系。
如果你在接入过程中遇到 API Key 或通道问题,先去控制台的 API Keys 页面检查 Key 状态,再对照接入文档核对 base_url 和路径。需要验证模型对话是否正常,可以直接用模型对话页面发一条测试消息。长期做编码和 Agent 编排的话,Coding Plan 提供了更稳定的额度和通道配置,适合把上面这套三层架构跑在生产环境里。