ARTICLE DETAIL

资讯详情

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

一文讲清楚Agent、MCP、Function Call:用TaoToken统一Key跑通实操代码示例

一文讲清楚Agent、MCP、Function Call:用TaoToken统一Key跑通实操代码示例 1. 先把三个概念摆到同一张桌子上Agent、MCP、Function Call 这三个词经常被混着用但它们在系统里站的位置完全不同。你可以把一次完整的 AI 任务想象成装修房子Function Call 是电钻模型自己决定什么时候按下开关MCP 是标准化的插座面板让不同品牌的电器都能插上去用Agent 是那个拿着图纸、会自己判断先刷墙还是先铺砖的工头。三者不是替代关系而是从「单点能力」到「标准接口」再到「自主调度」的递进。Function Call 的本质是模型的原生能力扩展。你在请求里声明一组函数签名模型在推理时如果判断需要外部数据就会返回一个结构化的调用意图由你的代码去执行真正的函数再把结果塞回对话。它跟具体模型绑定换一个模型可能就要改声明格式。MCPModel Context Protocol解决的是「接口不统一」的问题。它把外部服务抽象成 MCP Server用一套标准协议描述工具、资源和提示模板。任何支持 MCP 的客户端都能发现并调用这些服务不用为每个模型单独写适配层。它不绑定模型是应用层和工具层之间的通用插座。Agent 则是站在最上层的调度者。它维护任务状态、做多步规划、决定什么时候调 Function Call、什么时候走 MCP、什么时候直接回答。Agent 本身不提供工具能力它依赖下面两层把活干完。这篇要做的是用 TaoToken 的统一 Key 和 API 通道把这三层在本地串起来跑一次闭环。你会拿到可复制的settings.json、config.toml骨架一个 MCP 服务注册片段以及一段能实际触发的 Function Call 示例代码。目标不是讲透理论而是让你在本地看到「模型决定调工具 → 工具返回 → 模型总结」这条链路真的跑通。2. 为什么用 TaoToken 做统一入口本地实验最容易卡住的地方不是代码是 Key 管理。Function Call 要调模型MCP 客户端要调模型Agent 循环里每一步还要调模型如果每个环节用不同的供应商和 Key排查问题时你根本分不清是模型返回格式变了还是网络抖了。TaoToken 在这里的角色是一个统一的 API 通道。你申请一个 Key就能在模型对话、编码工具、Agent 框架里用同一套鉴权和计费。对做实验来说最大的好处是变量少了模型侧的行为一致出问题只可能是你的配置或代码。接入前先做两件事。第一到控制台创建一个 API Key记下它以sk-开头的完整字符串后面所有配置都用它。第二确认你要用的模型名TaoToken 的模型列表在文档里有选一个支持 Function Call 的比如带工具调用能力的通用模型。注意Key 只显示一次创建后立刻复制到本地密码管理器或环境变量里不要写进会提交到 Git 的配置文件。环境变量方式最省事后面所有配置都引用它export TAOTOKEN_API_KEYsk-你的key export TAOTOKEN_BASE_URLhttps://taotoken.net/api如果你用的是 Windows PowerShell换成$env:TAOTOKEN_API_KEYsk-...。这一步做完后面的settings.json和config.toml就不用硬编码密钥了。3. 可复制的配置骨架3.1 settings.json给支持 MCP 的客户端用很多本地 AI 工具用settings.json管理模型和 MCP 服务。下面这份骨架把模型通道指向 TaoToken同时注册一个本地 MCP 服务。字段名按你实际用的工具微调结构是通用的。{ model: { provider: openai-compatible, baseUrl: https://taotoken.net/api, apiKey: ${TAOTOKEN_API_KEY}, model: 你的模型名, temperature: 0.2 }, mcpServers: { local-tools: { command: python, args: [-m, mcp_server_demo], env: { TAOTOKEN_API_KEY: ${TAOTOKEN_API_KEY} } } } }这里${TAOTOKEN_API_KEY}是占位引用工具启动时会从环境变量读取。temperature设低一点Function Call 场景下模型更倾向稳定输出结构化参数减少瞎编字段的概率。3.2 config.toml给编码类工具用编码工具通常用 TOML。下面这份把模型通道和 MCP 服务都写进去注意base_url不要带末尾斜杠。[model] provider openai-compatible base_url https://taotoken.net/api api_key ${TAOTOKEN_API_KEY} name 你的模型名 max_tokens 4096 [mcp_servers.local-tools] command python args [-m, mcp_server_demo] [mcp_servers.local-tools.env] TAOTOKEN_API_KEY ${TAOTOKEN_API_KEY}两份配置的核心逻辑一样模型走 TaoToken 统一通道MCP 服务作为子进程启动通过标准输入输出通信。你不需要在 MCP 服务里再写一遍模型鉴权它只负责提供工具。3.3 MCP 服务注册片段MCP Server 的最小实现是暴露一个工具列表和一个调用入口。下面用 Python 写一个只做加法的服务方便验证链路不涉及任何外部依赖。import json import sys TOOLS [ { name: add_numbers, description: 计算两个数字之和, inputSchema: { type: object, properties: { a: {type: number, description: 第一个加数}, b: {type: number, description: 第二个加数} }, required: [a, b] } } ] def handle(request): method request.get(method) if method tools/list: return {tools: TOOLS} if method tools/call: params request.get(params, {}) args params.get(arguments, {}) result args.get(a, 0) args.get(b, 0) return {content: [{type: text, text: str(result)}]} return {error: unknown method} for line in sys.stdin: line line.strip() if not line: continue req json.loads(line) resp handle(req) resp[id] req.get(id) sys.stdout.write(json.dumps(resp) \n) sys.stdout.flush()把它保存为mcp_server_demo.py放在配置里args能找到的路径。这个服务只响应tools/list和tools/call两个方法足够验证 MCP 注册是否生效。4. 跑通一次 Function Call 闭环4.1 准备请求Function Call 的关键是请求体里带tools字段。下面这段用requests直接打 TaoToken 的 API模型名换成你实际用的。import json import os import requests API_KEY os.environ[TAOTOKEN_API_KEY] BASE_URL https://taotoken.net/api tools [ { type: function, function: { name: get_weather, description: 获取指定城市的当前天气, parameters: { type: object, properties: { city: {type: string, description: 城市名称} }, required: [city] } } } ] payload { model: 你的模型名, messages: [ {role: user, content: 北京今天天气怎么样} ], tools: tools, tool_choice: auto } resp requests.post( f{BASE_URL}/v1/chat/completions, headers{ Authorization: fBearer {API_KEY}, Content-Type: application/json }, jsonpayload, timeout60 ) print(resp.status_code) print(json.dumps(resp.json(), ensure_asciiFalse, indent2))4.2 预期返回与二次请求如果模型判断需要调工具返回的choices[0].message里会带tool_calls数组里面有函数名和参数。你拿到后执行本地函数再把结果作为role: tool的消息追加回去发起第二次请求。data resp.json() msg data[choices][0][message] if msg.get(tool_calls): call msg[tool_calls][0] args json.loads(call[function][arguments]) # 本地执行 weather_result {city: args[city], temp: 22C, condition: 晴} follow_up { model: 你的模型名, messages: [ {role: user, content: 北京今天天气怎么样}, msg, { role: tool, tool_call_id: call[id], content: json.dumps(weather_result, ensure_asciiFalse) } ] } resp2 requests.post( f{BASE_URL}/v1/chat/completions, headers{ Authorization: fBearer {API_KEY}, Content-Type: application/json }, jsonfollow_up, timeout60 ) print(resp2.json()[choices][0][message][content])第二次返回应该是模型用自然语言总结的天气比如「北京今天晴气温 22 摄氏度」。看到这句话说明 Function Call 闭环成立。4.3 把 MCP 接进 Agent 循环Agent 的调度逻辑可以很简单先让模型规划如果规划里提到需要外部工具就分别走 Function Call 或 MCP。下面是一个最小 Agent 骨架把前面两个能力串起来。class MiniAgent: def __init__(self, api_key, base_url, model): self.api_key api_key self.base_url base_url self.model model self.history [] def plan(self, user_input): self.history.append({role: user, content: user_input}) resp requests.post( f{self.base_url}/v1/chat/completions, headers{Authorization: fBearer {self.api_key}}, json{ model: self.model, messages: self.history [ {role: system, content: 判断是否需要调用工具只回答 need_tool 或 direct} ] }, timeout60 ) return resp.json()[choices][0][message][content] def run(self, user_input): decision self.plan(user_input) if need_tool in decision: # 这里接 Function Call 或 MCP 调用 return 已触发工具调用分支 return 直接回答分支这个骨架不完整但足够让你看到 Agent 的决策点在哪它不直接执行工具而是先判断再分派。真正的工具执行逻辑复用第 4.1 和 4.2 的代码。5. 本篇常见错排查报 401 或鉴权失败先确认Authorization头是Bearer sk-...格式中间有空格。再检查环境变量是否在当前 shell 生效echo $TAOTOKEN_API_KEY看有没有输出。如果 Key 是从文件读的注意有没有多余换行。模型不返回 tool_calls两个原因最常见。一是模型本身不支持 Function Call换一个支持工具调用的模型名。二是tool_choice设成了none改成auto。另外提示词太模糊也可能让模型选择直接回答把用户问题写具体一点。MCP 服务启动后没反应MCP 走标准输入输出服务端必须逐行读取并 flush。检查你的服务有没有在每行处理后sys.stdout.flush()否则客户端会一直等。另外确认command和args拼起来能在终端直接跑通路径问题占这类故障的大半。第二次请求报 tool_call_id 不匹配追加role: tool消息时tool_call_id必须和模型返回的call[id]完全一致不能自己编。同时msg对象要原样放回 messages不能只放 content。返回内容被截断Function Call 的返回可能较长检查max_tokens是否设得太小。编码类工具里如果max_tokens默认 1024多轮工具调用容易撞上限调到 4096 更稳。6. 把 Key 和通道固定下来跑通一次之后建议把配置固化模型通道统一走 TaoTokenKey 只放环境变量MCP 服务用版本管理Function Call 的声明抽成独立模块。这样下次换模型或加工具改动面很小。如果你主要在做工具接入和排障先去 API Keys 页面确认 Key 状态再对照接入文档检查base_url和路径拼接。路径是https://taotoken.net/api加/v1/chat/completions不要重复写/v1。想先验证模型对工具调用的支持情况可以直接在模型对话里发一句带函数声明的请求看返回结构里有没有tool_calls。这一步能省掉很多在代码里反复调试的时间。长期做编码和 Agent 循环的话Coding Plan 更适合高频调用场景额度和通道都更稳定。把这三层跑顺之后你会发现 Agent 的复杂度主要不在模型而在工具注册和状态管理而这正是 MCP 想帮你标准化掉的部分。
返回列表