从缸中大脑到能动手的 AgentTool Use 如何让 LLM 突破物理限制那个在显卡里疯狂跑的 LLM本质上还是个词语接龙的游戏。它是被困在服务器里的缸中大脑——看不见屏幕摸不到键盘只能预测下一个词的概率。但今天我们见证了一场技术革命Tool Use 让这个缸中大脑学会了调用 API、读取数据库、操作物理世界的工具。这不是魔法是协议。一、核心论点LLM Tools Agent用户以为豆包能自动搜索网页、Claude 能分析 Excel 表格是 LLM 自己完成的。其实不是。LLM 只会做一件事Next Token Prediction预测下一个词。它无法访问实时数据股价、天气执行计算读取文件调用 API但加上 Tools它就变成了 Agent。LLM缸中大脑 Tools外部能力 Agent能动手的智能体今天的核心问题是一个只能预测下一个词的概率模型怎么突破物理限制去调用 API、读数据库、操作工具答案藏在三个关键词里认知植入 → 意图识别 → Runtime 介入。二、认知植入工具降维为语言2.1 LLM 的根本限制LLM 不懂什么是天气 API也不懂数据查询但它听得懂语言。所以Tool Use 的第一步是把复杂的软件接口函数翻译成 LLM 能理解的说明书——这就是认知植入。2.2 JSON Schema函数的说明书看这段代码index.mjs第 13-30 行consttools[{type:function,function:{name:get_closing_price,// 函数名description:获取指定股票的收盘价,// 功能描述parameters:{// 参数 Schematype:object,properties:{name:{type:string,description:股票名称}},required:[name]}}}]这就是认知植入的核心把一个复杂的软件工具get_closing_price函数降维成一个存储的文本描述JSON Schema。字段作用为什么需要name函数标识符LLM 据此生成调用description功能描述LLM 据此决策是否调用parametersJSON SchemaLLM 据此生成合法参数required必填字段约束 LLM 必须提供2.3 Schema 的本质Schema 是对数据结构的正式定义和约束说明描述数据应如何组织、验证其合法性并确保不同系统间数据交换的一致性。类比数据库设计CREATETABLEusers(nameVARCHAR(100)NOTNULLUNIQUE);JSON Schema 做的是同样的事——用结构化语言约束数据格式。2.4 为什么描述必须具体清晰LLM 是概率模型描述写得越具体LLM 决策越准确。// ❌ 差的描述description:获取价格// ✅ 好的描述description:获取指定股票的收盘价输入股票名称返回最新收盘价前者会让 LLM 困惑什么价格商品价格股价房价后者则精确指向股票场景。一句话总结认知植入的本质是把软件能力翻译成语言说明书让 LLM 能理解工具的存在和用法。三、意图识别LLM 的决策机制3.1 用户提问时的推理过程用户问“青岛啤酒的收盘价是多少”LLM 的推理引擎开始工作1. 检查训练语料我能直接回答吗 → 不能股价是实时数据不在训练数据里 2. 检查认知植入有工具吗 → 有get_closing_price 工具 3. 匹配意图这个问题需要调用工具吗 → 需要用户问的是股价 4. 生成调用根据 Schema 生成参数 → tool_calls: [{ name: get_closing_price, arguments: {name:青岛啤酒} }]3.2 LLM 返回的结构看代码index.mjs第 77-78 行constresponseawaitsendMessage(messages);constmessageresponse.choices[0].message;LLM 返回的message对象有两种可能情况 A直接回答不需要工具{role:assistant,content:你好有什么可以帮你,tool_calls:null}情况 B调用工具需要外部数据{role:assistant,content:null,tool_calls:[{id:call_abc123,type:function,function:{name:get_closing_price,arguments:{name:青岛啤酒}}}]}关键洞察LLM 不执行工具只是决策该调用什么工具、传什么参数。它赌这段代码发出后会有人响应。3.3 为什么是tool_calls数组OpenAI 协议支持并行工具调用——LLM 可以一次性请求调用多个工具// 用户问青岛啤酒的股价和北京天气tool_calls:[{id:call_1,function:{name:get_closing_price,arguments:{name:青岛啤酒}}},{id:call_2,function:{name:get_weather,arguments:{city:北京}}}]代码中取[0]第 86 行是简化处理假设每次只调用一个工具。一句话总结意图识别是 LLM 的核心能力——它依赖强大的模式识别和逻辑推理判断是否需要工具、调用哪个工具、传什么参数。四、Runtime 介入传统软件的执行4.1 LLM 不能执行但开发者可以LLM 只生成调用请求tool_calls不执行函数。真正的执行由 RuntimeNode.js/Python/Java完成。看代码index.mjs第 88-91 行constargsJSON.parse(toolCall.function.arguments);// 解析参数constpriceget_closing_price(args.name);// 执行本地函数执行流程LLM 返回 tool_calls ↓ Runtime 解析 argumentsJSON 字符串 → 对象 ↓ Runtime 调用本地函数 get_closing_price(青岛啤酒) ↓ 返回结果 67.924.2 为什么用JSON.parseLLM 生成的arguments是字符串arguments:{name:青岛啤酒}// 字符串需要解析成对象才能传给函数constargsJSON.parse(arguments);args.name// 青岛啤酒4.3 工具结果不直接返回给用户关键设计工具结果不直接返回给用户而是返回给 LLM。看代码index.mjs第 93-99 行messages.push({role:tool,content:price,// 67.92tool_call_id:toolCall.id// call_abc123})为什么用户问的是自然语言问题期望自然语言回答工具返回的是原始数据“67.92”不是用户友好的回答LLM 需要把原始数据翻译成自然语言“青岛啤酒的收盘价是 67.92 元”4.4tool_call_id的作用tool_call_id是关联工具请求和结果的纽带// LLM 返回的请求tool_calls:[{id:call_abc123,...}]// Runtime 返回的结果{role:tool,tool_call_id:call_abc123,content:67.92}LLM 通过id知道“这个 67.92 是刚才那个工具调用的结果”。支持多工具并发如果有多个工具调用每个都有独立的id结果可以精确关联。五、二次调用LLM 基于真实数据生成回答5.1 完整对话历史看代码index.mjs第 104-107 行constfinalResawaitsendMessage(messages);console.log(finalRes.choices[0].message.content);此时messages数组包含[{role:user,content:青岛啤酒的收盘价是多少},{role:assistant,content:null,tool_calls:[{id:call_abc123,...}]},{role:tool,content:67.92,tool_call_id:call_abc123}]第二次调用 LLM 时它看到了完整上下文用户问了什么自己决策调用什么工具工具返回了什么结果5.2 LLM 的最终回答有了真实数据LLM 才能生成用户友好的回答青岛啤酒的收盘价是 67.92 元。不是直接返回 “67.92”而是用自然语言包装——这才是用户期望的交互体验。六、完整时序图用户 Agent LLM 本地函数 │ │ │ │ │──青岛啤酒股价──→│ │ │ │ │──messages───→│ │ │ │ │检查训练语料不能回答 │ │ │检查认知植入有工具 │ │ │意图识别需要调用 │ │←─tool_calls─│ │ │ │ │ │ │ │──JSON.parse──→ │ │ │──执行函数──────────────────→│ │ │←──67.92───────────────────│ │ │ │ │ │ │──messages结果──→│ │ │ │ │基于数据生成回答 │ │←─青岛啤酒收盘价是67.92元─│ │←──回答──────│ │ │七、代码架构总结// Layer 1: LLM 客户端缸中大脑constclientnewOpenAI({apiKey,baseURL});// Layer 2: 工具协议层认知植入consttools[{type:function,function:{name,description,parameters}}];// Layer 3: 函数实现层传统软件functionget_closing_price(name){...}// Layer 4: Agent 编排层意图识别 Runtime 介入asyncfunctionmain(){// 第一次调用LLM 决策constresponseawaitsendMessage(messages);// Runtime 执行constargsJSON.parse(toolCall.function.arguments);constresultget_closing_price(args.name);// 第二次调用LLM 总结constfinalResawaitsendMessage(messagestool_result);}八、知识结构总览Tool Use 核心机制 │ ├── 认知植入工具降维为语言 │ ├── JSON Schema函数的说明书 │ ├── descriptionLLM 决策依据 │ ├── parameters参数约束 │ └── required必填字段 │ ├── 意图识别LLM 决策机制 │ ├── 检查训练语料能否直接回答 │ ├── 检查认知植入有无工具 │ ├── 匹配意图是否需要工具 │ └── 生成调用tool_calls 数组 │ ├── Runtime 介入传统软件执行 │ ├── JSON.parse解析参数 │ ├── 执行函数调用本地代码 │ ├── tool_call_id关联请求和结果 │ └── 返回结果不直接给用户 │ └── 二次调用LLM 总结 ├── messages完整对话历史 ├── 基于真实数据生成回答 └── 自然语言包装用户友好结语Tool Use 不是魔法是协议。它解决了一个根本矛盾LLM 只会预测下一个词但用户需要它调用 API、读数据库、操作工具。解决方案藏在三个步骤里认知植入把软件能力翻译成语言说明书JSON Schema意图识别LLM 决策该调用什么工具、传什么参数Runtime 介入传统软件执行函数把结果喂回 LLMLLM 负责思考Runtime 负责动手。这才是 Agent 的本质——不是 LLM 变聪明了而是我们给缸中大脑装上了手脚。用户看到的智能是协议编织的幻觉。但这个幻觉恰好能解决问题。Tool Use 的真正价值不是让 LLM 突破物理限制而是让传统软件的能力通过语言协议被 LLM 调用。这是新旧范式的融合——概率模型与确定性代码的协作。下一次当你看到豆包自动搜索网页、Claude 分析 Excel 表格时请记住LLM 只是在预测下一个词真正干活的是你写的代码。