DX Agent · 模型技术

Tool Calling 不是插件魔法:它是接口设计

Tool Calling 经常被讲成“让模型调用插件”。这个说法太轻了。真正的 Tool Calling 是把自然语言系统接到真实软件系统上:模型负责判断何时需要外部能力,应用负责定义工具、执行工具、校验结果、处理失败和记录审计。

OpenAI 的 Function calling 文档把它定义为让模型访问外部系统和数据的方式。放到工程里看,它更像接口设计:你给模型的不是“万能手臂”,而是一组受限、可验证、可观察的函数。

一个工具应该像一个好 API

工具 schema 不是给人看的装饰,而是模型决策的边界。一个好工具通常满足四个条件:

  • 名字表达动作,例如 search_docs、create_calendar_event、deploy_static_site。
  • 参数足够窄,避免把一整段自然语言塞进万能字段。
  • 返回值稳定,最好是结构化对象,而不是不可预测的长文本。
  • 副作用明确,写操作、发消息、付款、部署都必须比读操作更受控。

这和传统 API 设计的直觉一致:函数越含糊,调用者越容易误用。差别只在于调用者是模型,它会根据工具描述推理用途,所以描述必须同时服务人和模型。

工具越多,越需要路由

许多团队的第一个 Tool Calling 原型会把所有工具一次性塞给模型。工具很少时可以工作,工具变多后会出现两个问题:上下文被工具描述挤占,模型也更容易在相似工具之间犹豫或误选。

官方资料已经开始把大量工具管理拆成不同层次: tool search用于延迟加载大规模或低频工具,Programmatic Tool Calling则让模型生成 JavaScript 来执行循环、条件、并行调用和中间结果压缩。社区里关于 MCP、工具注册表和代理编排的长帖,也都在讨论同一个问题:工具层需要成为系统架构的一部分,而不是 prompt 后面的一串 JSON。

当工具数量从 5 个变成 50 个,问题就从“模型会不会调用”变成“系统怎样让它只看到此刻该看的工具”。

错误恢复比首次成功更重要

Tool Calling 的演示通常展示理想路径:用户问天气,模型调用天气函数,函数返回结果,模型回答。但真实应用里更常见的是:

  • 参数缺失:用户没有提供城市、日期或账号。
  • 权限不足:当前 token 不能读取某个资源。
  • 工具失败:外部 API 超时、限流、返回 500。
  • 结果冲突:检索到多个同名对象,需要用户确认。
  • 副作用敏感:模型想执行写操作,但系统需要人工批准。

所以工具返回值里应该包含可机器读取的错误码和恢复建议,而不是只抛异常。模型可以把 permission_denied、rate_limited、ambiguous_target 转成下一步对话或降级方案。

并行调用不是无脑加速

并行工具调用能提升速度,但只适合独立读操作,例如同时查文档、查库存、查多个项目状态。写操作、顺序依赖和共享资源更新不应该盲目并行。否则一次看似聪明的优化,可能变成重复下单、重复发信或部署状态竞争。

面向个人开发者,可以先采用简单规则:读操作默认可并行,写操作默认串行;任何会影响外部世界的动作,都要求工具层检查幂等键、权限和确认状态。

可观测性决定你能不能修

当用户说“AI 刚才乱操作了”,你需要能回答:

  • 模型看到了哪些工具。
  • 它为什么选择这个工具。
  • 传入参数是什么。
  • 工具返回了什么。
  • 最终回复如何引用工具结果。

OpenAI 的 Agents 相关文档把 tracing、guardrails、human review 放进代理开发流程,原因就在这里。Tool Calling 不是一次函数调用,而是一条可审计链路。没有链路记录,你只能靠猜。

一个极简设计模板

下面是一个有效 JSON Schema 风格的概念示例,用于表达工具参数边界;真实接入时还需要按所用 API 的完整工具定义格式补齐名称、描述和返回处理。

{
  "name": "search_project_docs",
  "description": "Search public project documentation by keyword.",
  "parameters": {
    "type": "object",
    "properties": {
      "query": {
        "type": "string",
        "minLength": 1
      },
      "project": {
        "type": "string",
        "enum": ["skillgene", "niu-lai-video-translator", "openstock-enhanced"]
      },
      "limit": {
        "type": "integer",
        "minimum": 1,
        "maximum": 5
      }
    },
    "required": ["query", "project"],
    "additionalProperties": false
  }
}

这个模板故意很窄:只能查公开项目文档,不能读取私有仓库,不能写入外部系统。等系统真的需要写操作,再设计单独工具,并加上确认、幂等和审计。

资料来源

本文参考了 OpenAI Function calling、Programmatic Tool Calling、Agents 与 Agents SDK Guardrails 文档。社区趋势参考了 X 和开发者社区对 MCP、工具路由、代理编排的公开讨论;本文只做综合评论,不引用或改写任何长帖正文。

返回博客首页 查看应用站