工具调用
Tool Calling也常被叫作:函数调用Function Calling调工具
「他到底是真的看了我的文件,还是在猜?」
工具调用 Tool Calling
模型输出一个「我要用这个工具、参数是这些」的请求,宿主执行它,再把结果交回给模型。
工具调用是 Agent 能做事的机制。模型本身不能读文件、跑命令、发请求——它只能输出文字。所谓工具调用,是它输出一段结构化的请求(用哪个工具、什么参数),由外面的程序真正执行,再把结果作为新内容交回给它。
这个结构决定了一个非常实用的判断:「真的用了工具」和「凭上下文猜」在输出上可能长得一模一样。 它可以说「我查看了你的文件,里面写着…」,而实际上并没有发出任何调用。区分方法只有一个:看有没有真实的调用记录和原始返回。
三个失败点值得记住,因为症状完全相同(都表现为「用不了」):工具没注册(配置层面)、模型没发现或认不出该用它(描述层面)、调用了但结果没正确回填(连接层面)。日志里出现工具名,只能证明第一层。
最后一句:工具调用的权限就是 AI 的权限。给它一个「可以执行任意命令」的工具,等于把终端交出去。默认只给读,写和删单独授权。
长什么样 真实可交互,不是截图
模型输出(不是自然语言,是结构化请求):
{ "tool": "read_file", "args": { "path": "src/app.tsx" } }
宿主执行后回填:
{ "result": "文件的真实内容…" }
模型看到结果,再决定下一步有原始返回内容
结论能对应到返回里的具体某句
没有任何返回内容
细节说得很顺但对不上文件
「说得很顺」不是证据。真读过文件的回答,往往会带上具体的行号、变量名或它没预料到的细节。
拆开看,里面有这几块
-
1
工具定义 Tool schema
工具叫什么、有哪些参数、什么时候该用它。最后一项决定模型认不认得。
-
2
调用请求 Call
模型输出的结构化请求:用哪个工具、参数是什么。
-
3
执行 Execution
宿主真正去做这件事。权限检查必须发生在这一步之前。
-
4
结果回填 Result
把返回内容交回给模型。回填断了,模型会继续凭推理往下走。
容易搞混?这样区分
工具调用是模型的能力,MCP 是工具接入的标准。没有 MCP 也能有工具调用;有 MCP,是为了不用给每个客户端重写一遍接入。
看 MCP什么时候用得上
要求贴原始返回,或问一个文件里的具体细节(第几行写了什么)。
让它列出当前实际可见的工具名。名字对不上就是发现层出了问题。
先只给读。等你确认它的调用行为可靠,再逐项放开。
你可以这样跟 AI 说
直接复制下面这段,把【】里的换成你的情况。它比一句「帮我加个 X」多说清楚了:改哪里、不许动啥、做完交什么。
关于工具使用,请遵守两条: 1. 需要文件内容、命令输出、接口返回时,**真的去调用工具获取**,不要凭上下文推测。如果你无法调用某个工具,直接说"我无法访问,请贴给我"。 2. 汇报时把**原始返回**贴出来(关键部分即可),不要只给你的总结。我需要能对照原文。 另外: - 每个结论请注明依据来自哪一次调用的哪一段返回 - 如果某次调用失败了,明确说明失败原因,不要转而用推理填补然后照常汇报
「注明依据来自哪一次调用」这一句,能把「真读了」和「顺着猜」区分开——猜的内容找不到出处。
它说「做好了」,你怎么自己验
这是本站的重头戏。AI 最会的不是写代码,是说「已完成」。这一条,它通常最多做到「运行时」这层:真的跑起来了,能在本机看到结果。
要亲眼看到这些,才算数
- 要求看原始返回,不接受转述。返回里应该有你没预料到的细节。
- 问一个只有真读过才知道的具体问题(某个变量名、某一行内容)。
- 让它列出当前实际可见的工具名,和你配置的对一遍。
- 如果某次调用失败,确认它明确说了失败,而不是无声地改用推理继续。
- 权限测试:让它尝试访问范围外的路径,应该被拒绝而不是成功。
它常这么糊弄你
- 「我已经查看了你的项目结构」——但没有任何调用记录。它可能只是根据常见项目结构在描述。
- 调用失败后转为推理,输出看起来同样完整。这是最难发现的一种,因为格式没变。
- 日志里有工具名就宣称接通了。那只证明工具注册了,不证明模型能调、调得对。
- 为了「先跑通」给了完整读写权限,之后忘了收回。
工具调用能验到「运行时」层:你亲眼看到一次真实的调用和它的原始返回。
考考你 选一个你觉得对的
AI 说「我看过你的配置文件了,里面的端口是 3000」。怎么确认它真的读了?
端口是 3000 是最常见的默认值——猜对的概率很高,所以「对了」不能证明它读过。B 因此不成立;C 只会得到肯定回答;D 同样可以不调用而再答一次。只有原始返回或意外细节能证明调用真的发生了。