🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度
1. 从 OpenRouter 的 MiniMax M3 model card 说起
OpenRouter 上 MiniMax M3 的 model card 显示可调用,这件事本身不稀奇,稀奇的是很多人看完 model card 就以为「接上了」。model card 只告诉你这个模型在 OpenRouter 的目录里存在、支持哪些能力、上下文多长、价格区间大概在哪,它不负责告诉你本地 Agent 里怎么把请求真正发出去、tools 字段怎么传、返回的 tool_calls 长什么样。我这次要做的,是把 MiniMax M3 放进一个本地 Agent 的默认供应商位置,用 TaoToken 当统一 API 基线,发一次带 tools 的请求,然后把 request 和 tool_calls 返回逐字段对照出来。
为什么绕这一圈?因为模型路由这件事,最怕的就是「目录里有、本地跑不通」。OpenRouter 的 model card 是路由信息,TaoToken 是兼容通道,本地 Agent 是消费方,三者对同一个模型 ID、同一套 tools schema 的理解必须一致。我见过太多情况:model card 上写着支持 function calling,本地一发 tools 请求就 400,或者返回里根本没有 tool_calls,只有一个干巴巴的 content。问题往往不在模型,而在路由层把 tools 字段吞了,或者模型 ID 映射错了。
这篇不评测 TaoToken,也不评测 MiniMax M3 本身的能力上限。我要产出的是一张可复现的对照表:同一个带 tools 的请求,request 里我写了什么,返回里 tool_calls 给了我什么。Key 在官网创建,Base URL 填https://taotoken.net/api,模型 ID 以模型广场为准。跑完之后,你拿同一把 Key、同一个 Prompt,应该能复现出结构一致的返回。
2. 本地 Agent 把 TaoToken 设为默认供应商的两步
2.1 拿 Key:只在官网做一次
第一步是拿 Key。这一步没有捷径,也不该有捷径。打开 TaoToken 官网,进控制台创建 API Key,占位符记作YOUR_API_KEY。这里要强调一点:Key 只在官网创建,不要从任何第三方页面复制,也不要把 Key 写进会被提交到 git 的配置文件里。我习惯用环境变量,本地 Agent 读环境变量,配置文件里只留变量名。
创建完 Key,顺手在控制台看一眼模型广场,确认 MiniMax M3 对应的模型 ID 写法。不同通道对同一个模型的 ID 命名可能不同,有的带版本后缀,有的带供应商前缀。这一步不做,后面 404 的概率很高。模型 ID 以模型广场为准,不要凭记忆写。
2.2 设默认供应商:Base URL 与模型 ID
第二步是把本地 Agent 的默认供应商指向 TaoToken。核心就两个字段:Base URL 填https://taotoken.net/api,模型 ID 填你在广场看到的那个。注意 Base URL 末尾不带/v1,这是很多人第一次配会踩的坑——带了/v1之后,请求路径会变成/v1/v1/chat/completions之类,直接 404。
如果你用的是 Claude Code,配置走ANTHROPIC_BASE_URL、ANTHROPIC_AUTH_TOKEN、ANTHROPIC_MODEL三件套,或者写进~/.claude/settings.json的env段。如果你用的是 Codex,配置走~/.codex/config.toml,不要把ANTHROPIC_*套到 Codex 上,两套配置体系不通用。如果你用 CC Switch 做供应商切换,就在自定义供应商里填 Base URL、Key、模型 ID 三项,切过去之后验证一次。
这一步做完,TaoToken 就成了本地 Agent 的默认供应商。接下来所有请求,包括带 tools 的 function call,都从这条通道出去。
2.3 为什么默认供应商要固定
有人会问,为什么不每次请求都手动指定供应商?因为 Agent 场景下,工具调用是链式的:模型先返回 tool_calls,本地执行工具,再把结果贴回对话,模型继续推理。这条链上任何一次请求换了供应商,模型 ID 映射、tools schema 解析、返回格式都可能变,链就断了。把 TaoToken 固定成默认供应商,是为了让整条链的请求格式一致,对照表才有意义。
3. 发一次带 tools 的 MiniMax M3 请求
3.1 request 长什么样
我用一个最小可复现的 tools schema:一个查天气的函数,参数是城市名。请求体大致如下,模型 ID 用广场里的写法,这里用占位符表示。
{ "model": "YOUR_MODEL_ID", "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" }这个 request 里,tools是数组,每个元素是type: function加function对象,function里有name、description、parameters。parameters是标准 JSON Schema。tool_choice设auto,让模型自己决定要不要调工具。这套结构是 OpenAI 兼容格式,TaoToken 作为兼容通道应该原样透传。
3.2 tool_calls 返回长什么样
模型返回里,关键看choices[0].message.tool_calls。如果模型决定调工具,这个字段是个数组,每个元素有id、type、function,function里有name和arguments。arguments是字符串形式的 JSON,需要本地JSON.parse一次。大致结构:
{ "choices": [ { "message": { "role": "assistant", "content": null, "tool_calls": [ { "id": "call_xxx", "type": "function", "function": { "name": "get_weather", "arguments": "{\"city\":\"杭州\"}" } } ] }, "finish_reason": "tool_calls" } ] }注意finish_reason是tool_calls,不是stop。content可能是null,因为模型把输出全放进了 tool_calls。这两点是判断 function call 是否真正触发的关键。
3.3 request 与 tool_calls 对照表
把上面两段拆成字段级对照,这张表是这篇的核心产出。
| request 字段 | 我写的值 | tool_calls 返回字段 | 返回的值 | 是否一致 |
|---|---|---|---|---|
| model | YOUR_MODEL_ID | — | — | 需与广场一致 |
| tools[0].function.name | get_weather | tool_calls[0].function.name | get_weather | 一致 |
| tools[0].function.parameters.properties.city | string | tool_calls[0].function.arguments | {"city":"杭州"} | 类型一致 |
| tool_choice | auto | finish_reason | tool_calls | 触发成功 |
| messages[0].content | 查杭州天气 | tool_calls[0].function.arguments | 杭州 | 语义一致 |
这张表说明三件事:第一,tools schema 里的函数名被原样带到了返回里;第二,参数类型 string 被正确解析,模型填了「杭州」;第三,tool_choice: auto下模型主动触发了工具调用,finish_reason正确标记为tool_calls。如果哪一行对不上,问题就定位到那一层:函数名对不上是 schema 没透传,参数类型对不上是 JSON Schema 解析问题,finish_reason不是tool_calls是模型没触发或路由层吞了 tools。
3.4 本地执行工具再贴回
tool_calls 拿到之后,本地执行get_weather("杭州"),把结果作为role: tool的消息贴回对话,tool_call_id对上返回里的id。这一步是本地做的,AI 工具不直连你的生产库或生产机执行任何业务操作。它只生成或解释命令、SQL、函数调用参数,由你本地执行后再把结果贴回。这条边界在 Agent 场景里尤其重要,因为 function call 的诱惑就是让模型直接调你的内部接口,一旦接上生产环境,风险不可控。
4. 模型路由里容易踩的三个坑
4.1 模型 ID 映射错
最常见的坑是模型 ID。OpenRouter 的 model card 上写的 ID,和 TaoToken 模型广场里的 ID,可能不是同一个字符串。model card 是 OpenRouter 的目录命名,广场是通道侧的命名。你在本地 Agent 里填的必须是广场里的那个。填错的表现是 404 或model not found。解决办法很简单:配之前先打开广场看一眼,复制粘贴,不要手打。
4.2 tools 字段被吞
第二个坑是 tools 字段在路由层被吞。表现是请求发出去了,返回 200,但tool_calls是空的,finish_reason是stop,模型用自然语言回了一句「我帮你查一下杭州天气」。这说明 tools 没被透传到模型侧,模型根本不知道有工具可用。排查方法是把同一个 request 直接发到模型原生通道对比,如果原生通道有 tool_calls 而兼容通道没有,问题就在路由层。TaoToken 作为兼容通道,tools 透传是基本要求,遇到吞字段的情况先确认 Base URL 和模型 ID 是否正确。
4.3 Base URL 带了 /v1
第三个坑是 Base URL 末尾带了/v1。https://taotoken.net/api是正确写法,末尾不带/v1。带了之后,请求路径会多一层,直接 404。这个坑在 Claude Code 和 Codex 里都常见,因为有些通道的 Base URL 确实带/v1,习惯性带上就错了。记住:TaoToken 的 Base URL 是https://taotoken.net/api,不加/v1,也不加任何 UTM 参数。
5. 用同一把 Key 复现这张对照表
5.1 复现步骤
复现这张对照表,你需要:一把在 TaoToken 官网 创建的 Key,Base URL 填https://taotoken.net/api,模型 ID 从模型广场复制,然后发上面那个带 tools 的请求。跑完之后,对照第 3.3 节的表,逐行核对。如果每一行都对得上,说明你的路由链路是通的。
这里要声明一句:本文不含排行分数。我没有跑公榜,也没有引用任何 Arena ELO、SWE-bench 百分比、LiveCodeBench 分数。这张对照表是一次本地运行的字段级核对,不代表 MiniMax M3 在公榜上的名次,也不代表 TaoToken 的性能上限。它只证明一件事:在本地 Agent 里把 TaoToken 设为默认供应商后,MiniMax M3 的 function call 能正确触发,tools schema 能正确透传,tool_calls 返回结构符合预期。
5.2 验证调用是否入账
跑完请求,回控制台看用量。这次 function call 的 token 消耗应该出现在账单里。如果没出现,说明请求没走 TaoToken 通道,检查 Base URL 和 Key。对账这件事在模型路由里很重要,因为 Agent 场景下请求量大、链式调用多,没有对账就不知道钱花在哪。
5.3 长期开发看 Coding Plan
如果你只是试一次 function call,按上面的步骤走就够了。如果你要把 MiniMax M3 接进长期跑的 Agent,建议看一下 Coding Plan,它更适合高频调用的场景。模型对话入口在 这里,可以确认模型 ID 与广场是否一致。Key 在 控制台 创建,Claude Code 接入细节对照 接入文档。
模型路由这件事,说到底就是把「目录里有」变成「本地跑得通」。OpenRouter 的 model card 给了你路由信息,TaoToken 给了你兼容通道,本地 Agent 给了你消费场景,三者对齐的那一刻,function call 才真正落地。这张对照表就是对齐的证据。
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度