Tool Calls 费 token,我为啥还在项目里坚持用?
前段时间在做小程序低代码页面生成平台,后端接大模型生成 PageSchema。一开始走的是最朴素的路子:把需求丢给模型,让它直接吐一整段 JSON。
听起来简单,实际用起来很折磨。
模型经常多写字段、组件 type 乱编、JSON 半截截断,前端一解析就炸。改 prompt 能好一阵,换几个页面描述又翻车。那段时间我基本是在跟「自由发挥」较劲。
后来改成 Tool Calls,体验完全变了。不是夸张,是第一次跑通完整链路时,我真的松了口气。
一、Tool Calls 到底是什么(新手版)
一句话:不让模型直接给最终结果,而是让它在限定工具里选、按格式填参数,由你的程序去执行。
以前:
用户描述 → 模型自由输出 JSON → 你祈祷它能 parse
现在:
用户描述 → 模型说「我要调 recognize_page_intent」→ 你执行 → 把结果塞回去
→ 模型说「我要调 list_components」→ 你执行 → 再塞回去
→ … → 最后 submit_page_schema
模型不再「凭空写代码」,而是在你定义的接口里做选择题和填空题。
我们项目里大致就是这么干的:意图识别、查组件、拿 spec、校验 Schema、提交结果,拆成六步。某一步不对,至少知道错在哪,不用对着一大坨 JSON 猜。
新手最容易踩的坑
1. 工具定义写太宽
一开始我把 list_components 设计得啥都能查,模型反而乱调。后来按 page_type、category、keyword 收窄,效果好很多。
2. 以为一步就能生成完
Tool Calls 天然是多轮的。要接受「慢几步」,换「稳很多」。
3. 不在服务端执行,只让模型假装调了
工具必须在你的代码里真跑,结果真返回。否则就是换皮 prompt,没有约束意义。
4. 工具返回塞太多垃圾
组件 spec 全量丢回去,token 飞涨,模型还容易被无关字段干扰。按需查、按需返,别图省事一次给全库。
二、从能跑到用顺:我现在的做法
1. 工具粒度:一步一件事
每个工具只做一件清楚的事。我们后来固定成:
- 识别意图
- 列组件
- 查 spec
- 拿布局模式
- 校验
- 提交
模型不用一次想完整页面,负担小,出错面也小。
2. 强约束写在工具 schema 里
比如 validate_page_schema 的说明里写死:校验不过不能 submit。比在 prompt 里喊「请务必校验」管用得多。模型对结构化接口的遵守,通常比对散文式要求好。
3. 服务端做后处理,别全信模型
我们 AI 出 PageSchema 后,还有布局优化、字段合并等后处理。Tool Calls 解决「结构对不对」,后处理解决「好不好看」。两件事别混为一谈。
4. 失败要能降级
Tool 链路偶发超时或模型抽风,我们保留了传统 Prompt 模式兜底。生产环境别只有一条路。
5. 日志要记 Tool 调用
生成耗时、调了几次、哪步失败——这些不记,后面优化只能凭感觉。我们写进 generation_history,排查问题时省很多时间。
三、Tool Calls、MCP、Skills 到底啥区别
这三个名字都常出现,我第一次也混。用我现在的理解:
Tool Calls:模型「怎么动手」的协议
- 是什么:OpenAI 等 API 自带的能力,模型输出
{ name, arguments },你的程序执行并回传。 - 谁提供工具:你自己写 Java/Python/Node 函数,在请求里把 schema 带给模型。
- 典型场景:查数据库、调内部 API、校验 JSON、读业务规则——和你自己系统深度绑定的逻辑。
我们后端 PageGenerationToolService 那套,就是标准 Tool Calls。
MCP:工具「怎么接入」的协议
- 是什么:Model Context Protocol,一套标准,让外部服务以统一方式给 AI 暴露工具、资源。
- 谁提供工具:MCP Server(Playwright、文档读取、Figma 等),客户端(如 Cursor)连上去用。
- 典型场景:跨应用、可复用、可插拔的能力。你不必为每个 SaaS 写一遍胶水代码。
可以这么记:Tool Calls 是模型和运行时之间的调用格式;MCP 是「工具供应商」和「AI 应用」之间的插拔标准。
在 Cursor 里你配 MCP,本质是让 IDE 里的 agent 能调外部 server 的工具;底层往往还是 function calling 那套,只是工具从哪来的、怎么发现,MCP 帮你规范了。
Skills:AI「怎么做事」的说明书
- 是什么:Cursor 里的 SKILL.md,告诉 agent 某类任务该怎么一步步做。
- 不是:可执行代码,也不是 API 接口。
- 典型场景:写 hook、写 skill、改 settings——流程、规范、检查清单。
Skills 像老员工留下的操作手册;Tool Calls 像系统提供的按钮;MCP 像统一规格的 USB 接口,各种设备插上就能用。
| Tool Calls | MCP | Skills | |
|---|---|---|---|
| 本质 | 模型调用函数 | 工具接入协议 | 任务指导文档 |
| 谁执行 | 你的业务代码 | MCP Server | Agent 读文档后自行操作 |
| 绑定程度 | 和你的项目强绑定 | 跨项目复用 | 和编辑器/工作流绑定 |
| 典型内容 | 查组件库、校验 Schema | 读网页、调 Figma | 创建 PR、写 commit 规范 |
三者不互斥。 可以:Skill 规定「做页面生成先调意图识别」→ Agent 通过 Tool Calls 调你的后端 → 后端再通过 MCP 读外部文档。各干各的层。
四、Tool Calls 费 token,为啥还要用
这是我最常被问的点,也是我以前犹豫的地方。
到底费在哪
- 工具定义:每个工具的 name、description、parameters schema 都要进上下文,工具越多越占。
- 多轮往返:调 6 次工具 ≈ 多轮对话,每轮都带着历史。
- 工具返回值:组件 spec、校验结果,都是实打实的 token。
我们平台一次生成,Tool 调用次数和总耗时都会涨。如果只比「单次请求谁更省」,裸 Prompt 往往更便宜。
那为啥还要用
因为省下来的 token,经常不够补锅。
裸生成 JSON 时,我遇到过:
- 解析失败 → 重试 → 又一轮完整上下文
- 组件 type 不存在 → 前端降级 → 页面缺块
- 结构缺字段 → 手写修复 → 人工时间更贵
Tool Calls 多花的 token,买的是:
1. 结构化输出,少 parse 翻车
参数有 schema,类型错了至少能定位。
2. 按需取数,不全量生成
不用让模型背 50 个组件定义,需要时再 list_components / get_component_spec。看起来轮次多了,单轮上下文往往更干净。
3. 关键步骤可强制
校验不过不能 submit——这种硬约束,纯 prompt 很难稳定做到。
4. 失败可观测
知道死在「查组件」还是「校验」,比「JSON 又烂了」好查一个数量级。
5. 业务逻辑留在代码里
匹配规则、权限、校验在 Java 里跑,不靠模型「记得」。该改就改,不用赌下次 prompt 生效。
我的结论:Tool Calls 不是为省 token 设计的,是为省返工、省排查、省上线后半夜救火设计的。 真算总账,往往更划算。
五、给想上手的人几条实话
-
别一上来定义 20 个工具
3~5 个跑通链路,再拆细。 -
description 写给模型看,不是写给人看
「什么时候必须调」「参数怎么填」「调完下一步干啥」——写清楚比写漂亮重要。 -
返回值能瘦就瘦
只返模型决策需要的字段。 -
和 MCP、Skills 分工
业务核心用 Tool Calls;通用外部能力用 MCP;重复流程用 Skills 固化。别指望一个概念包打天下。 -
接受多轮
生成从 3 秒变 8 秒,用户一般能接受;生成出来不能用,用户不会接受。
写在最后
Tool Calls 不是银弹。复杂页面该不稳还是不稳,prompt 和后处理照样要做。但它把「模型该干什么、程序该干什么」的边界划清楚了,这点对做平台的人很重要。
我是从「直接生成 JSON 写到怀疑人生」,到「拆工具链路到终于能 demo」,才真正体会到这玩意儿香在哪。费 token 是事实,但为了少返工、少猜 JSON 哪里又坏了,我觉得值。
如果你也在做 AI + 业务系统,不妨从一个小工具试起——比如先做一个「查数据库/查配置」的 tool,让模型只能调它拿数据,别自己编。跑通一次,大概就懂我在说啥了。
(基于个人在小程序低代码页面生成项目中的实践整理,Tool 拆分和命名因项目而异,思路可复用。)
更多推荐




所有评论(0)