AI Agent(五):Tool Use 工具调用——用 TaoToken 统一 Key 打通 Function Calling 与 MCP
1. 从“只会说”到“能动手”AI Agent 工具调用到底卡在哪AI Agent 的 Tool Use工具调用能力说白了就是让大模型从“只会聊天”变成“能真正干活”。Function Calling 负责让 LLM 输出结构化的调用意图MCPModel Context Protocol负责把外部工具标准化地注册进来两者配合才能跑通一条完整的工具调用链路。这套东西适合谁适合已经在写 Agent 项目、被“模型说得好听但啥也干不了”折磨过的开发者也适合刚接触 Function Calling、想搞明白 tool_calls 到底怎么回填结果的新手。我一开始做 Agent 的时候最大的困惑不是模型不会调用工具而是调用链路太碎LLM 输出一个 JSON我得手动解析、手动执行、手动把结果塞回 messages中间任何一环格式对不上整个循环就断了。更麻烦的是每接一个新工具就要改一遍代码工具多了以后维护成本直线上升。后来我把接入点统一到 TaoToken 的 API 通道上用一套 Key 同时跑 Function Calling 和 MCP链路才真正稳定下来。这篇文章不讲空概念直接给你能复制的东西一份工具 schema、一段 MCP 配置、一次端到端调用验证。你跟着走一遍就能在自己的 Agent 项目里把 Tool Use 跑通。核心检索词就三个AI Agent、Tool Use、Function Calling外加 MCP 这个绕不开的协议。先说清楚一个最容易搞混的点LLM 本身不执行工具。它只负责“决定调用哪个工具、传什么参数”真正执行的是你的 Agent 代码。这个分工想明白了后面所有报错你都能定位到是“模型决策层”还是“执行层”的问题。2. TaoToken 前置统一 Key 打通 Function Calling 与 MCP 的接入点在动手写代码之前先把接入层理清楚。Tool Use 链路里有两个地方要发请求一是 LLM 的 chat/completions带 tools 参数二是 MCP Server 的工具注册与调用。如果这两条链路各用一套鉴权和地址调试起来会非常痛苦。我的做法是统一走 TaoToken 的 API 通道Base URL 固定为https://taotoken.net/apiKey 用同一个模型 ID 也在一处管理。先拿 Key。打开 API Keys 页面https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite创建一个新 Key复制出来存到环境变量里。注意别把 Key 硬编码进代码后面配置片段里我都用TAOTOKEN_API_KEY这个变量名。export TAOTOKEN_API_KEYsk-你的key export TAOTOKEN_BASE_URLhttps://taotoken.net/api模型 ID 这块Function Calling 对模型能力有要求不是所有模型都能稳定输出 tool_calls。我实测下来选支持工具调用的模型在请求里显式带上tools字段模型才会返回结构化的调用意图。如果你不确定当前模型支不支持可以先去模型对话页面https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite手动发一条带工具定义的请求看返回里有没有tool_calls字段这是最快的验证方式。MCP 这一侧TaoToken 的接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite里有完整的协议说明和示例配置。我建议你先按文档把 MCP Server 的地址和鉴权方式确认一遍再回到 Agent 代码里对接。很多人卡在 MCP 连不上其实不是协议问题是 Base URL 或 Key 没对齐。这里有个关键点Function Calling 和 MCP 虽然协议不同但都可以复用同一个 API 通道和同一套鉴权。你不需要为 MCP 单独申请一套凭证也不需要维护两个 Base URL。统一之后Agent 代码里只需要一个 client 实例工具注册和模型调用共用链路清晰很多。如果你打算长期做编码类 Agent或者要跑多工具编排的复杂任务可以考虑 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite它在长链路调用和并发工具执行上更稳一些。不过对于本文这个最小闭环普通 API Key 就够了。3. 可复制配置工具 schema、MCP 配置与 Agent 接入片段这一节是全文最核心的部分所有片段都可以直接复制。我按“工具定义 → MCP 注册 → Agent 接入”的顺序给你照着改路径和参数就行。先看工具 schema。Function Calling 要求工具用 JSON Schema 描述参数描述写得越清楚模型调用越准。下面这个add_device_model工具是我实际项目里用的你可以替换成自己的业务工具{ type: function, function: { name: add_device_model, description: 添加设备机型到数据库。当用户查询未解锁的机型时可以使用此工具将机型添加到数据库中。机型代码应该去除后缀如 IN、CN 等例如 CPH2223IN 应该使用 CPH2223。, parameters: { type: object, properties: { model: { type: string, description: 机型代码例如 CPH2223去除后缀如 IN、CN 等 }, marketName: { type: string, description: 中文营销名例如 OPPO Find N6 } }, required: [model] } } }注意description里我特意写了“去除后缀”的规则因为模型很容易把CPH2223IN原样传进来。工具描述就是给模型的说明书你写得越具体它犯错越少。接下来是 MCP 配置片段。MCP Server 的注册一般放在一个配置文件里路径按你的项目结构来。我用的是mcp/servers.json{ mcpServers: { device-tools: { command: python, args: [-m, mcp_server.device], env: { TAOTOKEN_API_KEY: ${TAOTOKEN_API_KEY}, TAOTOKEN_BASE_URL: https://taotoken.net/api } } } }这里command和args是启动 MCP Server 的方式env里把 Key 和 Base URL 透传进去。如果你的 MCP Server 是远程服务把command换成url字段即可。配置里的${TAOTOKEN_API_KEY}会从环境变量读取避免明文写 Key。然后是 Agent 接入片段。我用 Python 写一个最小闭环核心是三步注册工具、发起带 tools 的请求、处理 tool_calls 并回填结果。import os import json import requests BASE_URL os.environ[TAOTOKEN_BASE_URL] API_KEY os.environ[TAOTOKEN_API_KEY] MODEL_ID 你的模型ID def call_llm(messages, tools): resp requests.post( f{BASE_URL}/v1/chat/completions, headers{ Authorization: fBearer {API_KEY}, Content-Type: application/json, }, json{ model: MODEL_ID, messages: messages, tools: tools, tool_choice: auto, }, timeout60, ) resp.raise_for_status() return resp.json() def execute_tool(name, arguments): args json.loads(arguments) if name add_device_model: # 这里替换成你的真实业务逻辑 return json.dumps({success: True, message: f已添加 {args[model]}}) return json.dumps({success: False, message: unknown tool})这段代码里tool_choice: auto让模型自己决定要不要调用工具。execute_tool是执行层模型返回的arguments是字符串要先json.loads再处理。执行结果再序列化成字符串回填这是 Function Calling 的硬性要求。Agent Loop 的核心逻辑是这样def run_agent(user_input, tools): messages [{role: user, content: user_input}] for _ in range(10): data call_llm(messages, tools) choice data[choices][0][message] messages.append(choice) tool_calls choice.get(tool_calls) if not tool_calls: return choice.get(content, ) for tc in tool_calls: result execute_tool( tc[function][name], tc[function][arguments], ) messages.append({ role: tool, tool_call_id: tc[id], content: result, }) return 达到最大迭代次数注意messages.append(choice)这一步必须把模型返回的 assistant 消息含 tool_calls原样加进历史否则下一轮模型不知道自己在等工具结果。role: tool的消息要带上tool_call_id和请求里的id对应这是回填的关键。4. 验证请求一次端到端调用与成功结果配置写完了现在跑一次端到端验证。这一步的目的是确认整条链路通了模型输出 tool_calls → Agent 执行工具 → 结果回填 → 模型生成最终回复。先构造请求。把第 3 节的工具 schema 放进tools数组用户输入用一句会触发工具调用的话tools [{ type: function, function: { name: add_device_model, description: 添加设备机型到数据库。机型代码应去除后缀例如 CPH2223IN 使用 CPH2223。, parameters: { type: object, properties: { model: {type: string, description: 机型代码}, marketName: {type: string, description: 中文营销名} }, required: [model] } } }] print(run_agent(帮我把机型 CPH2223 添加到数据库, tools))跑起来之后你会看到模型第一轮返回的不是文本而是tool_calls。结构大概是这样{ choices: [{ message: { role: assistant, content: null, tool_calls: [{ id: call_abc123, type: function, function: { name: add_device_model, arguments: {\model\: \CPH2223\} } }] } }] }看到content是null、tool_calls有内容说明模型正确识别了工具调用意图。这时候 Agent 执行execute_tool把结果回填再发第二轮请求。第二轮模型拿到工具结果后会生成最终文本回复类似“已成功将机型 CPH2223 添加到数据库”。如果你用的是 MCP 方式验证步骤多一层先确认 MCP Server 启动成功再确认 Agent 能列出工具。可以用下面这段代码检查工具注册import requests resp requests.post( f{BASE_URL}/v1/mcp/tools/list, headers{Authorization: fBearer {API_KEY}}, json{server: device-tools}, timeout30, ) print(resp.json())返回里应该能看到add_device_model这个工具的定义。如果列表是空的说明 MCP Server 没注册成功回到第 3 节的servers.json检查command和args路径。实测下来整条链路最容易出问题的地方是arguments的解析。模型返回的是 JSON 字符串不是对象直接当 dict 用会报错。一定要先json.loads。另外tool_call_id必须一一对应多个工具调用时不能串。成功跑通后你会看到类似这样的完整输出[第一轮] 模型返回 tool_calls: add_device_model({model: CPH2223}) [执行] 工具返回: {success: true, message: 已添加 CPH2223} [第二轮] 模型最终回复: 已成功将机型 CPH2223 添加到数据库。这就是 Tool Use 的最小闭环。MCP 只是把工具注册从“代码里硬编码”变成“配置里声明”执行链路是一样的。5. 本篇常见错排查401、local proxy failed、reading choices 与 OAuth这一节按真实报错来都是我踩过的坑。你对照自己的日志找对应项。401 Unauthorized最常见Key 没传对或者过期了。检查Authorization头是不是Bearer开头中间有空格。如果你用的是环境变量确认TAOTOKEN_API_KEY真的被 export 了Python 里os.environ读不到会直接报 KeyError 或者传空。还有一种情况是 Key 复制时带了换行或空格肉眼看不出来重新复制一遍。local proxy failed / connection refused这个报错通常出现在 MCP Server 启动阶段。servers.json里的command路径不对或者 Python 环境里没装 MCP 依赖。先手动在终端跑一遍python -m mcp_server.device看能不能启动。如果报模块找不到装依赖如果报端口占用换端口。注意别把本地代理配置和这个混在一起MCP 走的是标准输入输出或 HTTP不需要额外网络层。reading choices 报错 / KeyError: choices模型返回体里没有choices字段说明请求本身失败了但你的代码直接去取data[choices]。先打印完整resp.text看错误信息。常见原因是模型 ID 写错或者请求体里tools格式不对导致服务端拒绝。还有一种情况是模型不支持 Function Calling返回了普通文本但没有choices结构换一个支持工具调用的模型 ID 即可。OAuth / 鉴权失败如果你接的是需要 OAuth 的 MCP Serverservers.json里要配auth字段不能只靠 API Key。检查 token 有没有过期scope 对不对。TaoToken 的接入文档里有 OAuth 流程的完整说明按文档走一遍。如果报invalid_grant多半是回调地址和注册时不一致。tool_calls 为空但模型有回复模型没决定调用工具直接给了文本。原因通常是工具描述不够清楚或者用户输入没触发调用意图。把description写具体加上“当用户……时使用此工具”的引导。也可以在 system message 里明确告诉模型“你有工具可用合适时请调用”。arguments 解析失败json.loads报错说明模型返回的参数字符串格式不对。先打印原始字符串看有时候模型会多包一层引号或者带 markdown 代码块标记。可以在解析前做一次清洗去掉json 和标记。排查顺序建议先看 HTTP 状态码再看返回体结构最后看业务逻辑。401 和连接类错误在接入层choices 和 tool_calls 在协议层arguments 在执行层。分层定位别一上来就改代码。6. 语义一致 CTA把 Tool Use 链路固化到你的项目里跑通一次不代表稳定。我的经验是把工具 schema、MCP 配置、Agent Loop 这三样东西版本化管理每次改工具都走一遍端到端验证。工具描述和参数 schema 的改动最容易引入回归改完一定要重新跑第 4 节的验证请求。如果你在接入过程中遇到鉴权或协议问题直接去 API Keys 页面https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite重新生成一个 Key 试试再对照接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite检查 Base URL 和请求格式。想先验证模型对工具调用的支持程度用模型对话https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite手动发一条带 tools 的请求最快。长期做编码类 Agent 或多工具编排Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite在长链路和并发场景下更省心。最后留一个实用技巧在 Agent Loop 里加日志把每一轮的tool_calls和工具执行结果都打出来。出问题时不用猜直接看日志就知道是模型没调用、参数传错还是执行层报错。这个习惯能帮你省掉大量调试时间。

相关新闻

为什么我的微信Bot总是断连?AI Agent 接入微信 Bot 排坑实战手册:装好只是开始,稳跑才是本事

为什么我的微信Bot总是断连?AI Agent 接入微信 Bot 排坑实战手册:装好只是开始,稳跑才是本事

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/2 20:09:50 阅读更多 →
【vscode】编辑器只显示单文件、双击覆盖问题解决 + claude code 插件友好页面设置,顺带把 Base URL 改到 TaoToken

【vscode】编辑器只显示单文件、双击覆盖问题解决 + claude code 插件友好页面设置,顺带把 Base URL 改到 TaoToken

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/2 20:09:50 阅读更多 →
Codex驱动AEDT完成无线充电仿真——从双线圈建模到三维电磁场动画

Codex驱动AEDT完成无线充电仿真——从双线圈建模到三维电磁场动画

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/2 20:09:50 阅读更多 →

最新新闻

Unity新输入系统实现鼠标单击、双击、长按判定与事件分发框架

Unity新输入系统实现鼠标单击、双击、长按判定与事件分发框架

最近在做一个需要同时支持鼠标左键单击、双击、长按三种操作的小项目,切换到 Unity 的 New Input System 之后,第一版代码写得非常简陋:一个 MonoBehaviour 里塞满了 if 判断、时间戳和一堆“状态变量”。加功能只敢加在同一个文件里&#xf…

2026/10/2 22:08:16 阅读更多 →
TLQ 7/8消息中间件运维常用命令与故障排查实战指南

TLQ 7/8消息中间件运维常用命令与故障排查实战指南

拿到TLQ 7/8这套消息中间件的时候,很多运维同事的第一反应是:这玩意儿不就是国产消息队列嘛,思路应该和RabbitMQ、Kafka差不太多。可真到了配置环境、启服务、查队列、定位故障的时候才发现,命令一多就容易乱,今天记住了明天又得翻手册。尤其是从TLQ 7升级到TLQ 8之后,部分命令…

2026/10/2 22:08:16 阅读更多 →
OpenClaw on reComputer:隐私优先的边缘情绪识别Agent部署指南

OpenClaw on reComputer:隐私优先的边缘情绪识别Agent部署指南

1. 项目概述:为什么在 reComputer 上跑 OpenClaw 是个“隐私优先”的硬核选择OpenClaw on reComputer —— 这个标题乍看像一串技术缩写堆砌,但拆开来看,它其实指向一个正在快速成型的边缘智能新范式:把高敏感度的情绪识别&#x…

2026/10/2 22:08:16 阅读更多 →
SpringBoot+Vue3+MyBatis流浪动物救助平台源码解析

SpringBoot+Vue3+MyBatis流浪动物救助平台源码解析

1. 从小区流浪猫说起:这套系统到底解决的问题是什么我最初关注流浪动物救助,是因为小区楼下那只橘猫。它有固定的喂食点,有志愿者拍照发朋友圈,但信息散在十几个群里,今天谁喂了、明天猫在哪、有没有生病,全…

2026/10/2 22:08:16 阅读更多 →
2026年论文党必备:TaoToken 统一 Key 接入降AI率工具实测与配置清单

2026年论文党必备:TaoToken 统一 Key 接入降AI率工具实测与配置清单

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/2 22:08:16 阅读更多 →
专业的AI论文写作软件排行榜(2026 最新版)

专业的AI论文写作软件排行榜(2026 最新版)

基于功能完整性、学术适配性、用户反馈及操作便捷性,本文对当前主流AI论文写作工具进行了全面测评,按综合推荐指数从高到低进行排序,并详细标注各工具的核心优势与适用场景。🏆 第一梯队:全流程学术解决方案&#xff0…

2026/10/2 22:07:16 阅读更多 →

日新闻

从零搭建AI工程化:模型之外的完整闭环

从零搭建AI工程化:模型之外的完整闭环

先搞清楚一件事:从零开始做 AI 工程化,难的从来不是调模型、写提示词,而是把一套原型 Demo 变成长得像是“正经系统”的东西。你手里可能已经有了能跑通的代码,也可能刚读完一些概念,但真到了要把它变成可维护、可观测…

2026/10/2 0:00:20 阅读更多 →
大模型训练显存估计与混合精度训练实战指南

大模型训练显存估计与混合精度训练实战指南

1. 大模型训练显存估计与混合精度训练详解显存不够用,几乎是每个做大模型训练的人都会撞上的第一堵墙。你可能也经历过:模型代码写完了,数据管道跑通了,满心欢喜地按下训练启动脚本,结果几秒钟后终端弹出一行红字——C…

2026/10/2 0:00:20 阅读更多 →
小样本学习数据集选型指南:27个真正可用的高质量数据集

小样本学习数据集选型指南:27个真正可用的高质量数据集

1. 小样本学习的“弹药库”:为什么你总在找数据集,却总找不到真正能用的? 小样本、数据集——这两个词最近半年在我处理的200多个AI项目咨询里,出现频率排进前三。不是模型调不好,不是代码写不对,而是卡在…

2026/10/2 0:00:20 阅读更多 →

周新闻

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/10/1 19:40:48 阅读更多 →
SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/10/1 19:41:40 阅读更多 →
FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏 【免费下载链接】FireRed-OpenStoryline FireRed-OpenStoryline is an AI video editing agent that transforms manual editing into intention-driven directing through natural language …

2026/10/1 20:05:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/2 10:36:31 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/2 5:26:06 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/2 6:09:11 阅读更多 →