尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

LLM工具调用四件套:Function Calling、MCP、Skill、CLI到底怎么选?TaoToken统一Key实测对比

LLM工具调用四件套:Function Calling、MCP、Skill、CLI到底怎么选?TaoToken统一Key实测对比 1. 四种工具调用形态的真实边界从一次 Agent 翻车说起先说一个我踩过的坑。去年做一个代码仓库问答 Agent需求很简单用户问「这个函数在哪些文件被调用」Agent 去 grep 一下返回结果就行。我图省事把整个仓库的文件列表和部分内容通过 MCP 工具一次性喂给模型结果上下文直接爆掉模型开始胡言乱语finish_reason返回length而不是tool_calls整个链路卡死。后来换成 CLI 脚本在外部执行 grep只把匹配到的文件路径和行号返回给模型问题瞬间消失。这件事让我意识到Function Calling、MCP、Skill、CLI 这四样东西很多人包括当时的我是混着用的觉得「反正都是让模型调工具」。但它们的职责边界完全不同选错了形态轻则上下文浪费重则整个 Agent 不可用。这篇文章面向正在搭 Agent 或工具链的开发者用同一套 TaoToken 统一 Key 和 API 通道把四类调用形态全部跑通一遍。你会拿到可复制的配置片段、逐项验证动作以及一张「什么场景选什么形态」的判断表。核心检索词先摆出来LLM 工具调用选型、Function Calling 与 MCP 区别、Agent Skill 渐进式加载、CLI 绕过上下文窗口这四个问题本文都会给出可操作的答案。先给一个一句话结论方便你建立全局观Function Calling 是模型内嵌的函数决策机制解决「模型怎么输出结构化调用请求」MCP 是协议化的服务接入层解决「工具怎么标准化复用」Skill 是封装好的能力包解决「Agent 拿到工具后该按什么流程做」CLI 是本地命令执行解决「大数据量处理怎么不撑爆上下文」。四者不是替代关系而是不同层面的东西。下面逐个拆开每个都配可跑通的代码。2. TaoToken 统一 Key 前置准备一个通道跑通四类调用在动手之前先把 API 通道统一。四类调用形态如果各自用不同的 Key 和 Base URL排障时会非常痛苦——你分不清是工具调用逻辑错了还是鉴权通道的问题。我用 TaoToken 的统一 Key 来跑好处是一个 Key 覆盖 Function Calling、MCP 客户端、Skill 加载和 CLI 脚本里的模型请求出问题时变量只有一个。2.1 获取 Key 与配置环境变量访问控制台创建 API Key地址是 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。创建后拿到形如sk-xxxx的 Key不要硬编码进代码用环境变量管理export TAOTOKEN_API_KEYsk-你的key export TAOTOKEN_BASE_URLhttps://taotoken.net/api注意 Base URL 是https://taotoken.net/api不带任何 UTM 参数这是给程序调用的地址。带 UTM 的那个是官网首页别搞混。2.2 验证通道连通性先做一次最小请求确认 Key 和 Base URL 可用。用 curl 测curl https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -H Content-Type: application/json \ -d { model: gpt-4o-mini, messages: [{role: user, content: 回复 OK 两个字母}], max_tokens: 10 }返回里能看到choices[0].message.content是OK说明通道正常。这一步别跳过后面四类调用都依赖这个通道先确认地基没问题。2.3 模型 ID 的选择四类调用对模型能力要求不同。Function Calling 需要模型支持tools参数MCP 底层依赖 Function Calling所以模型必须支持工具调用Skill 本质是提示词加资源加载对模型要求最低CLI 只是把模型当决策器普通对话模型即可。我实测下来gpt-4o-mini和claude-3-5-sonnet在工具调用上表现稳定finish_reason能正确返回tool_calls。推理类模型比如某些带思考链的在工具调用上会有兼容问题后面第 5 节会专门讲这个报错。如果你要长期跑编码类 Agent可以考虑 Coding Plan地址是 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 额度更划算。但本文的验证用按量 Key 就够了。3. 四类调用形态的可复制配置JSON、TOML 与 settings 片段这一节是全文的核心四类形态各给一份可直接复制的配置。路径和字段名我尽量保持和官方文档一致你复制后改 Key 就能跑。3.1 Function CallingJSON Schema 定义与两轮对话闭环Function Calling 的运行时是「两轮对话 中间执行」。第一轮你把工具定义JSON Schema传给模型模型判断需要调用就返回tool_calls你的代码执行工具把结果塞回对话第二轮模型基于结果给出最终答案。工具定义示例注意description字段是模型判断是否调用的核心依据要写清楚{ type: function, function: { name: get_weather, description: 查询指定城市的当前天气当用户询问天气、温度、是否下雨时调用, parameters: { type: object, properties: { city: { type: string, description: 城市名称如北京、上海 }, unit: { type: string, enum: [celsius, fahrenheit], description: 温度单位默认摄氏度 } }, required: [city] } } }完整调用代码import os, json from openai import OpenAI client OpenAI( api_keyos.environ[TAOTOKEN_API_KEY], base_urlos.environ[TAOTOKEN_BASE_URL] /v1 ) tools [{ type: function, function: { name: get_weather, description: 查询指定城市的当前天气, parameters: { type: object, properties: {city: {type: string}}, required: [city] } } }] messages [{role: user, content: 北京今天天气怎么样}] resp client.chat.completions.create( modelgpt-4o-mini, messagesmessages, toolstools, tool_choiceauto ) choice resp.choices[0] if choice.finish_reason tool_calls: tool_call choice.message.tool_calls[0] args json.loads(tool_call.function.arguments) # 这里真正执行工具示例用假数据 result {city: args[city], temp: 22, condition: 晴} messages.append(choice.message) messages.append({ role: tool, tool_call_id: tool_call.id, content: json.dumps(result, ensure_asciiFalse) }) final client.chat.completions.create( modelgpt-4o-mini, messagesmessages, toolstools ) print(final.choices[0].message.content)关键点模型全程只负责决策输出结构化 JSON 调用请求真正执行工具的是你的宿主程序代码。这个职责分工是整个机制的核心设计。模型支持一次返回多个tool_calls实现并行调用你可以遍历choice.message.tool_calls批量执行。3.2 MCPClient-Server 架构与 JSON-RPC 配置MCP 解决的是工具接入碎片化问题。以前每接一个新工具都要单独写对接代码换个客户端又得重写。MCP 是 Client-Server 架构Server 是工具实现方Client 是 AI 应用侧一个 Client 可以连接多个 Server。MCP 底层通信使用 JSON-RPC 2.0传输层支持 Stdio本地和 Streamable HTTP远程。核心能力分三类Tools 是有副作用的操作需要授权Resources 是只读数据无副作用Prompts 是可复用的提示词模板。以 Claude Desktop 的配置为例配置文件路径在 macOS 是~/Library/Application Support/Claude/claude_desktop_config.jsonWindows 是%APPDATA%\Claude\claude_desktop_config.json{ mcpServers: { filesystem: { command: npx, args: [ -y, modelcontextprotocol/server-filesystem, /Users/yourname/projects ] }, fetch: { command: npx, args: [-y, modelcontextprotocol/server-fetch] } } }如果你用的是 Cline 这类支持 MCP 的编辑器插件配置写在 Cline 的 MCP 设置里格式类似。注意 MCP 不是 Function Calling 的替代品而是建立在 Function Calling 之上的——Client 把 MCP Server 暴露的工具转成 Function Calling 的 Schema 传给模型模型决策后 Client 再通过 JSON-RPC 调用 Server。3.3 Skill文件夹结构与渐进式加载Agent Skill 是一个能力包本质是一个包含指令、脚本和资源的文件夹。核心是把完成特定任务的复杂流程、专业知识和最佳实践封装成 AI 可以随时查阅和执行的操作手册。每个 Skill 是一个文件夹里面有skill.md指令文件可以带上脚本、模板、参考文档等资源。目录结构示例skills/ code-review/ skill.md scripts/ lint.sh templates/ review-template.mdskill.md内容示例--- name: code-review description: 对代码进行审查检查命名规范、潜在 bug 和性能问题 --- # 代码审查流程 1. 读取目标文件内容 2. 检查命名是否符合团队规范 3. 检查是否有未处理的异常 4. 检查循环中是否有重复计算 5. 按 templates/review-template.md 格式输出 需要运行 lint 时执行 scripts/lint.sh。Skill 具有渐进式加载设计三层加载机制只读元数据name 和 description→ 按需加载指令skill.md 正文→ 用到时才读取资源scripts 和 templates。这样不会一次性把所有 Skill 内容塞进上下文。Skill 和 Prompt 的区别Skill 能被 Agent 自动发现和按需加载不需要每次手动输入。Skill 和 MCP 工具的区别MCP 给 Agent 提供外部工具和数据的访问能力而 Skill 教 Agent 拿到这些工具和数据后该怎么使用。Tool 是「能做什么」Skill 是「该按什么流程做」。3.4 CLI本地命令执行与数据流向控制CLI 形态的核心价值是改变数据流向。MCP 的数据会流入模型上下文窗口成为模型思考的一部分大数据会直接撑爆窗口CLI 脚本在模型外部执行数据被处理后只把精简的结果返回给模型。一个典型的 CLI 工具封装让模型决策后调用本地脚本import subprocess, json def run_grep(pattern: str, path: str) - str: 在指定路径下搜索 pattern只返回匹配的文件和行号 result subprocess.run( [grep, -rn, --include*.py, pattern, path], capture_outputTrue, textTrue, timeout30 ) lines result.stdout.strip().split(\n)[:20] # 只取前20条 return \n.join(lines) if lines else 无匹配结果 # 把这个函数注册成 Function Calling 的工具 cli_tool { type: function, function: { name: run_grep, description: 在代码库中搜索指定字符串返回匹配的文件路径和行号, parameters: { type: object, properties: { pattern: {type: string}, path: {type: string} }, required: [pattern, path] } } }注意这里的关键设计run_grep在模型外部执行grep 的完整输出不会进入上下文只有截断后的前 20 条返回给模型。这就是「不要让模型去看数据而是让模型去指挥工具处理数据」。4. 逐项验证请求与成功结果四类形态的实测动作配置写完逐个验证。每类形态给一个明确的成功标志你照着做能确认是否跑通。4.1 Function Calling 验证跑 3.1 的代码成功标志是第一轮响应finish_reason为tool_callsmessage.tool_calls[0].function.name是get_weatherarguments是合法 JSON第二轮响应finish_reason为stopcontent里包含天气信息。如果第一轮finish_reason是stop而不是tool_calls说明模型认为不需要调用工具检查你的description是否写清楚了触发条件。4.2 MCP 验证配置好 Claude Desktop 后重启客户端在对话框输入「列出 /Users/yourname/projects 下的文件」。成功标志是 Claude 弹出工具授权提示你点允许后返回文件列表。如果没弹出提示检查claude_desktop_config.json的 JSON 格式是否合法以及npx命令是否在 PATH 里。4.3 Skill 验证把skills/code-review/文件夹放到 Agent 能扫描到的目录然后输入「帮我审查一下 utils.py」。成功标志是 Agent 自动加载了 code-review 这个 Skill按skill.md里的流程执行并输出符合模板格式的审查结果。如果 Agent 没自动加载检查skill.md的 frontmatter 里description是否写清楚了适用场景。4.4 CLI 验证跑 3.4 的代码输入「在 /path/to/code 里搜索 TODO」。成功标志是模型返回tool_calls你的代码执行 grep返回匹配结果模型基于结果总结。关键验证点是grep 的完整输出没有进入上下文只有截断后的结果被模型看到。四类形态都跑通后你会得到一张清晰的对照表形态职责数据流向适用场景Function Calling模型输出结构化调用请求请求进模型结果回模型简单工具调用参数明确MCP标准化工具接入与复用数据流入模型上下文多客户端复用同一工具Skill封装流程与最佳实践按需加载指令和资源复杂流程、团队规范CLI本地命令执行数据留在外部只回摘要大数据量处理、文件操作5. 本篇常见错排查401、local proxy failed 与 OAuth 报错这一节对照真实报错逐个给排查路径。这些错我都实际遇到过按顺序检查基本能定位。5.1 401 Unauthorized最常见。检查三件事Key 是否复制完整有没有多余空格Base URL 是否写成https://taotoken.net/api而不是带 UTM 的首页地址请求头是否是Authorization: Bearer sk-xxx格式。如果用的是 OpenAI SDK确认base_url参数拼上了/v1。5.2 local proxy failed这个报错通常出现在 MCP 客户端连接远程 Server 时。检查 MCP Server 的传输层配置Stdio 类型需要command和args字段Streamable HTTP 类型需要url字段。如果 Server 是本地启动的确认npx或node命令在 PATH 里且 Server 进程没有崩溃。可以手动在终端跑一遍 Server 启动命令看是否有报错输出。5.3 reading choices 报错这个报错说明响应体里没有choices字段通常是 API 返回了错误信息但你的代码直接去读choices了。加一层判断resp client.chat.completions.create(...) if not resp.choices: print(响应异常:, resp) return常见原因是模型 ID 写错或者请求参数里tools格式不合法。检查tools数组里每个元素是否有type和function两个字段。5.4 OAuth 报错MCP 远程 Server 如果启用了 OAuth 鉴权Client 需要配置对应的认证信息。检查 Server 文档要求的认证方式在 Client 配置里加上headers或auth字段。如果是本地 Stdio Server一般不需要 OAuth。5.5 推理模型不支持工具调用有些推理模型的思考链是一次性连续生成的不能中途打断工具调用天然需要在生成过程中暂停等待外部执行这和连续生成的范式冲突。MCP 底层依赖 Function Calling推理模型连 Function Calling 都支持不好MCP 自然也使用不了。后续模型迭代中采用了折中方案让工具调用发生在思考阶段结束后保证思考过程仍然完整连续。如果你遇到推理模型工具调用失败换用非推理模型即可。5.6 上下文窗口溢出这是 MCP 形态最容易踩的坑。MCP 获取到的数据会被完整输入 LLM 的上下文窗口数据量大时会撑爆窗口导致模型无法处理而报错或中断回答。解决方案有三层MCP Server 优化返回数据只返回必要字段或摘要对于大数据提供「先检索、再按需获取」的工具组合在 MCP Client 和 Server 之间加代理层自动拦截大响应存到外部存储只返回摘要和 ID 给模型。工程最佳实践还包括把 MCP 工具调用的结果缓存起来当模型再次需要相同数据时直接从缓存读取避免重复调用和上下文污染。6. 选型决策与统一 Key 接入入口四类形态跑完选型逻辑其实很清晰。我总结成几个判断问题你按顺序问自己第一个问题这个操作的数据量大吗如果大优先 CLI让数据留在外部只回摘要。如果小继续往下问。第二个问题这个工具需要在多个客户端复用吗如果需要选 MCP一次实现到处复用。如果只在单个应用里用继续往下问。第三个问题这个任务有固定的流程和规范吗如果有封装成 Skill让 Agent 自动发现和按需加载。如果只是简单的参数化调用用 Function Calling 就够了。第四个问题需要模型做复杂决策吗如果只是执行固定命令CLI 脚本直接跑就行不需要模型介入。实际项目里这四类形态往往是组合使用的。一个成熟的 Agent 可能是用 Function Calling 做基础工具调用用 MCP 接入外部服务用 Skill 封装业务流程用 CLI 处理大数据量操作。把模型当成大脑把工具当成手脚大脑不需要记住身体的每一个细胞只需要能指挥手脚去拿东西。如果你要开始搭建建议从 Function Calling 入手跑通两轮对话闭环再逐步引入 MCP 和 Skill。统一 Key 和 API 通道能帮你减少变量把精力集中在工具调用逻辑本身。模型对话调试入口在 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API Key 管理在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。长期跑编码 Agent 的话Coding Plan 在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。最后留一个我实测有效的技巧在 Function Calling 的description里明确写出「什么时候不该调用」比只写「什么时候调用」效果更好。模型建立「能直接回答就不调用工具」的边界感能显著减少无效工具调用。这个细节在 SFT 和 RLHF 阶段模型就学过你在 Schema 里再强化一次命中率会更高。
返回列表