青蛙小白

Function Calling(函数调用)

Function Calling(函数调用) 是让 LLM 通过结构化接口请求外部能力的机制:开发者把可用工具及其参数 schema 提供给模型,模型在需要外部数据或动作时生成一个函数调用请求,应用代码执行真实函数,再把结果回传给模型继续生成回答。

它也常被称为 tool calling(工具调用)。在 OpenAI API 语境中,function calling 是 tool calling 的一种主要形态:函数工具由 JSON Schema 定义;此外还有 custom tools,允许模型向工具传入自由文本,并可用 grammar 约束格式。在 Anthropic Claude API 语境中,同一机制表现为 tool_use block 和 tool_result 消息,详见 Claude API Tools

在更大的 OpenAI API Tools(OpenAI API 工具)语境中,Function Calling 负责“应用自定义能力”:模型请求调用某个业务函数,应用侧执行真实代码。Web search、File search、Remote MCP、Shell、Computer use 等也属于工具层,但它们的能力来源和执行位置不同。

关键边界:模型不直接执行函数。模型只产生“调用哪个工具、传什么参数”的结构化意图;真正的数据库查询、退款、发邮件、读文件或调用内部 API,都由应用侧 Harness Engineering(驾驭工程)执行。这一点决定了函数调用同时是能力接口,也是权限和安全边界。

不同供应商术语不同,但工程边界一致:

平台语境模型返回应用回填执行者
OpenAI Responses APIfunction_callfunction_call_output应用或平台工具
Claude Messages APItool_usetool_resultclient tools 由应用执行,server tools 由 Anthropic 执行

因此,本词条讨论通用机制;平台专属工具清单分别见 OpenAI API Tools(OpenAI API 工具)Claude API Tools

基本流程

函数调用流程可以概括为五步:

  1. 开发者定义可调用工具,包括名称、说明、参数 schema 和是否启用 strict mode
  2. 应用把用户输入和工具定义发给模型
  3. 模型判断需要工具时,返回 function_call / tool_calls,其中包含函数名和 JSON 编码参数
  4. 应用解析参数、执行本地函数或外部 API,并把结果绑定到对应 call_id / tool_call_id / tool_use_id
  5. 应用把工具结果再发给模型,模型基于观察结果生成最终回答,或继续请求下一轮工具调用
sequenceDiagram
    participant U as User
    participant H as Harness / App
    participant M as Model
    participant T as Tool / API
    U->>H: 用户请求
    H->>M: input + tools schema
    M-->>H: function_call(name, arguments, call_id)
    H->>T: 执行真实函数
    T-->>H: 工具结果
    H->>M: function_call_output(call_id, output)
    M-->>H: 最终回答或继续调用工具
    H-->>U: 回复 / 动作结果

这个循环正是 Agent Loop(智能体循环)的核心结构之一:模型负责选择动作,harness 负责执行动作并把观察结果追加回上下文。

函数工具与 schema

函数工具通常由以下部分组成:

  • name:函数名,要短、明确、能表达动作
  • description:函数用途、什么时候该用、什么时候不该用
  • parameters:JSON Schema,描述参数类型、枚举、嵌套对象和必填字段
  • strict:要求模型输出严格符合 schema,而不是 best-effort

OpenAI 建议启用 strict: true。严格模式底层依赖 Structured Outputs(结构化输出),因此 schema 需要满足额外约束:对象参数应设置 additionalProperties: false,所有 properties 字段都要出现在 required 中;可选字段可以用包含 null 的类型表示。

Claude 也支持 strict tool use:在自定义工具定义中加入 strict: true,让 tool_use 参数严格匹配 schema。两家平台的共同边界是:strict 提升结构正确性,不替代权限检查、业务校验和人工审批。

这把函数调用和 Agent-Computer Interface(智能体计算机接口)直接连接起来:函数 schema、参数名和描述就是模型看到的工具 UI。schema 越清楚,模型越不容易误用工具;schema 越宽泛,后续就越依赖护栏兜底。

处理多个调用

模型一次响应可能包含零个、一个或多个函数调用。应用不应假设“最多一个工具调用”,而应遍历所有 tool_calls / response.output 中的 function_call 项,分别解析、路由、执行并回填结果。

OpenAI API 提供 parallel_tool_calls 控制并行函数调用。开启时,模型可以在同一 turn 中请求多个函数;关闭时,每轮最多零个或一个函数调用。是否允许并行不是纯性能问题,还涉及业务语义:

场景更适合
多个只读查询彼此独立允许并行
调用之间存在顺序依赖禁用并行或在 harness 中串行执行
涉及写入、支付、删除、生产发布禁用并行,并接入 Agent Guardrails(Agent 护栏)

函数调用输出也可以流式返回。普通文本流式聚合的是 content,函数调用流式聚合的是 JSON 参数片段;应用需要把 response.function_call_arguments.delta 等事件累积成完整参数后再执行工具。

Custom tools 与 grammar

OpenAI 的 Function Calling 文档区分两类工具:

  • Function tools:输入由 JSON Schema 定义,适合结构化 API 调用、数据库查询、业务动作
  • Custom tools:模型向工具传入自由文本,适合代码执行、DSL、命令片段或不值得包成 JSON 的输入

Custom tools 可用 context-free grammar 约束输入格式。OpenAI 当前支持 larkregex 两类 grammar 语法。grammar 能把“输出必须是某种语言/表达式/格式”的约束前移到采样过程,但复杂 grammar 会增加调试成本;文档建议保持 grammar 简单,必要时同时迭代 prompt、工具描述和 grammar 本身。

Tool search 与大工具集

函数定义会被注入模型上下文,占用 input token,也会影响 Prompt Caching(提示缓存)。工具很多或 schema 很大时,把全部函数一次性暴露给模型会带来三类问题:

  • 上下文窗口被工具定义消耗
  • 模型在相似工具之间选择更困难
  • 工具列表变化破坏稳定 prompt 前缀

OpenAI 文档建议初始可用函数数量保持较小,并在大工具生态中使用 tool_search 延迟加载低频工具。tool_search 让模型先搜索相关工具,再把需要的工具加入上下文。根据文档,只有 gpt-5.4 及后续模型支持这一能力。

这与 Context Engineering(上下文工程)中的 Select 策略一致:不要把所有可能相关的能力都塞进当前上下文,而是按当前任务需要加载。

设计原则

OpenAI 文档给出的函数定义建议,与 ACI 和软件工程原则高度一致:

  • 函数名、参数名和说明要清楚,说明输出代表什么
  • 用系统/开发者指令说明什么时候使用或不要使用某个函数
  • 通过 examples 和 edge cases 修正常见失败,但 reasoning model 不一定总是受益于更多示例
  • 用枚举、对象结构和 schema 让无效状态不可表达
  • 不要让模型填写应用代码已经知道的参数,例如已在 UI 中确定的 order_id
  • 总是连续调用的函数可以合并,减少模型决策步骤
  • 起始工具数量保持小,必要时用 tool search、命名空间或 fine-tuning 改善大工具集准确率

这些原则背后的判断很简单:函数调用不是“给模型更多按钮”就会更强。每个函数都会消耗上下文、增加选择分支,并扩大误用和攻击面。好的工具接口应该减少模型需要猜测的东西。

安全边界

Function Calling 会把模型输出连接到真实系统,因此它天然属于 Agent Guardrails(Agent 护栏)Agent Sandbox(Agent 沙箱)的关注范围。

最低限度的生产边界包括:

  • 服务器端只允许调用白名单函数,不按模型返回的任意字符串动态执行代码
  • 参数解析后仍要做业务校验、权限检查和类型检查
  • 高风险动作按只读/可回滚/不可逆/资金或隐私影响分级
  • 工具结果以明确格式返回,包含错误码或失败原因,而不是让模型猜
  • 对工具调用、参数、结果和人工审批记录 trace,便于审计和回放

模型生成的参数符合 schema,不等于业务上安全。strict: true 只能提升结构正确性;“该不该执行”仍然由应用侧权限、策略和人工审批决定。

与 MCP 的关系

Model Context Protocol(模型上下文协议)和 Function Calling 都在解决“模型如何调用外部能力”,但层次不同。

维度Function CallingMCP
关注点单次模型请求中如何描述和处理函数调用AI 客户端与外部工具服务器的标准协议
工具来源应用在请求里提供或通过 tool search 加载MCP 服务器动态暴露
接口形态JSON Schema / custom tool grammarJSON-RPC 协议中的 tools、resources、prompts
主要风险schema 设计、参数校验、动作权限工具发现、工具投毒、服务器权限和供应链

在实际系统里,MCP 工具常会被客户端转换成模型供应商支持的 function/tool calling 结构。也就是说,MCP 更像工具接入协议,Function Calling 更像模型调用层的工具表达格式。

相关概念

参考来源
  1. 1. https://developers.openai.com/api/docs/guides/tools
  2. 2. https://developers.openai.com/api/docs/guides/function-calling
  3. 3. https://developers.openai.com/api/docs/guides/structured-outputs
  4. 4. https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview
评论