renxuai.com
02 · 工具调用

给 AI 接上手:工具调用的完整工程解析

LLM 本质上只做一件事:输入文字 → 输出文字。它不能创建文件、不能发消息、不能打开网页。 它是一个只能说话的嘴,没有手。工具 = 给这只嘴接上的手。

Function Calling:核心协议

技术实现的核心机制——模型本身没有执行任何操作,它只是输出一个"我想调用什么工具、传什么参数"的意图声明,真正干活的是外层 Agent Harness:

用户:"帮我查北京天气"
  ↓ 模型输出(结构化 JSON):
{
  "tool": "get_weather",
  "arguments": {"city": "北京"}
}
  ↓ Agent Harness 真正执行 → 结果返回
  ↓ 模型拿到结果,组织成自然语言

五层架构

层级能力典型工具
第5层 应用层 飞书消息、GitHub、Notion
第4层 外部服务 搜索引擎、图片生成、语音合成
第3层 编程运行时 Python 沙盒、JS 执行
第2层 操作系统 终端命令、文件读写、进程管理
第1层 硬件抽象 GPU、网络、文件系统

工具 vs 命令

一个关键区分:工具是 Agent 的能力接口(约 30 个),命令是在终端里执行的具体指令(无限个)。终端是最危险也是最强大的工具——通过它,Agent 理论上可以在电脑上执行任意操作。

💡 安全模型分三层:
① 用户权限(OS 层):Agent 进程跑在哪个用户下,继承哪个用户的权限
② 文件权限(OS 层):rwx 位控制读写执行
③ 工具权限(Agent Harness 层):就算 OS 允许,Agent Harness 也可以拦截——"没有工具权限"≠ OS 不让你用,是框架自己的安全策略

四大框架工具集对比

能力HERMESClaude CodeOpenClaw
文件操作4个专用工具Read/Write/Editread/write/edit/exec
终端terminalBash(核心)exec(支持bg/pty/elevated)
浏览器9个专用工具❌ 无1个统一 browser 工具
多模态内置(图/音/视)❌ 无image_generate/video_generate/music_generate
消息发送send_message❌ 无message(多渠道)
子Agentdelegate_task有限支持sessions_spawn
设计哲学~30个精细工具~12个 + Bash万能browser统一接管 + exec万能

11个工程深水区

工具调用远不止"调个函数"那么简单。以下是实际工程中必须处理的深层问题:

  1. Function Calling 协议:JSON Schema 定义工具 → 模型输出结构化 JSON → 结果回传。arguments 是 JSON 字符串而非对象,这是"JSON parse error"偶发的根因。
  2. 工具描述工程:description 写得好坏直接决定模型会不会选对工具。模糊描述 → 模型选错工具 → 任务失败。
  3. Token 成本:每次对话都要把工具定义塞进上下文。30个工具 × 每个200 token = 6000 token 额外开销。
  4. 并行 vs 串行:同时调多个独立工具节省时间,但有依赖关系的必须串行。
  5. 返回值设计:太大撑爆上下文,太小信息不够。截断策略、分页、结构化返回。
  6. 错误处理与重试:JSON parse error、超时、权限不足——需要分级重试策略。
  7. 安全边界与沙盒:terminal 是最危险的工具——rm -rf / 通过 OS 权限 + 框架权限两层拦截。
  8. 工具注册机制:静态注册(启动时加载)vs 动态注册(运行时增删)。
  9. MCP 协议:Model Context Protocol——让工具变成可插拔的标准化组件,跨框架复用。
  10. Human-in-the-Loop:高风险操作弹确认——阻塞式、异步式、白名单自动过。
  11. 可观测性:日志(每次调用记录)+ 追踪(串成调用链)+ 指标(统计成功率/耗时)。
💡 工具描述工程是门手艺。description 不只要写"这个工具干什么",还要写"什么时候不该用这个工具"。例如:search_files 的 description 写明"仅用于文件内容搜索,不要用于网页搜索",才能避免模型在需要搜索网页时错误调用文件搜索工具。