AI Agent · Function Calling

2026 Function Calling 是什麼?OpenAI、Gemini、Claude 如何用 JSON 呼叫 API 與外部工具

2026.08.18 · 約 12 分鐘閱讀

Function Calling 的分水嶺不是「哪家模型更聰明」,而是誰輸出 JSON、誰執行副作用。下文拆協議、三家 JSON 形態與執行邊界,並給出可帶走的選型矩陣與 7 步清單。

開發者工作台上的 JSON 編輯器與接線工具,象徵 Function Calling 把模型接到外部 API

Function Calling(也叫 tool calling / 工具呼叫)在 2026 年已经从「演示技巧」变成 Agent 产品的預設協議:模型不再用散文假装呼叫接口,而是在约定 schema 下吐出 JSON,由你的程式碼去真正请求天气、查库、改檔案或跑测试。真正差异不在模型谁更会聊天,而在schema 是否可校驗、执行是否可稽核、副作用是否可隔離

3
厂商 JSON 方言
1
共同循环:请求→执行→回填
MCP
工具發現与传输层

为什么纯文本 prompt 不够(Why)

早期做法是让模型输出「请呼叫 get_weather(city=北京)」,再用正規表示式去抠。这在 demo 里能过,上线后会遇到三类硬伤:

  1. 解析不稳定——模型加礼貌用语、换参数顺序、漏引号,下游 JSON.parse 直接炸。
  2. 无法約束类型——该传枚举却传自由文本;该必填却省略;並行呼叫时分不清哪次对应哪次。
  3. 副作用与对话混写——模型「声称已经删除了檔案」,其实你从未执行;或反过来,你执行了但模型不知道结果。

Function Calling 把「决策」留给模型、「执行」留给執行環境:模型只选择工具与参数,HTTP、資料庫、shell 永远不在模型进程里发生。这和 CI「一 job 一 workspace」同一思想——执行边界先于聪明程度。工具一旦能改磁盘,就要配 Agent 檔案系统沙箱;一旦要跨会话记住用户偏好,就要把状态放到 独立 Memory 层,而不是塞进下一次 tool arguments。

Function Calling 三层分类(What)

不要把「接了 OpenAI tools」当成架构。至少拆三层:

层级职责典型载体谁拥有
L1 Schema工具名、JSON Schema、描述、必填字段OpenAI tools[].function、Gemini functionDeclarations、Claude input_schema产品 / 平台团队
L2 Runtime校驗参数、注入金鑰、超时、重试、稽核自研 Agent loop、LangGraph、Claude Code你的后端或本机 Agent
L3 Transport如何發現与连接工具进程直连 HTTP、MCP stdio/SSE、内部 RPC基础设施

非对称结论:厂商 API 只标准化了 L1 的「JSON 信封」;L2 的权限与 L3 的进程隔離,三家都不替你做完。MCP 解决的是 L3 發現与会话,不是「自动安全」。

完整循环如下。注意箭头方向:模型从不持有你的 API Key,金鑰只存在 Runtime。

┌──────────────┐     JSON tool request      ┌──────────────────┐
│  LLM API     │  ────────────────────────► │  Your runtime    │
│  (OpenAI /   │     name + arguments       │  (Agent loop)    │
│   Gemini /   │                            │                  │
│   Claude)    │  ◄──────────────────────── │  execute tool    │
└──────────────┘     tool result JSON       │  • HTTP APIs     │
                                            │  • DB / search   │
                                            │  • shell / MCP   │
                                            └────────┬─────────┘
                                                     │
                                                     ▼
                                            ┌──────────────────┐
                                            │ Policy + secrets │
                                            │ allowlist, audit │
                                            │ Cloud Mac / VPC  │
                                            └──────────────────┘

核心对比:OpenAI vs Gemini vs Claude

工具入口执行能力上下文适合人群
OpenAI toolsChat Completions / Responses API由你执行;arguments 常为 JSON 字符串並行 tool_calls[];可选 strict schema已有 OpenAI SDK、閘道统一成 OpenAI 形态
Gemini functionDeclarationsGemini API / Vertex由你执行;可 toolConfig.mode 强制/禁止呼叫Schema 类型名常用大写 OBJECT/STRINGGCP 栈、需要 mode 开关的产品
Claude tool_useMessages API / Claude Code由你执行;input 已是对象而非字符串content 块:tool_use / tool_resultAnthropic 栈、IDE Agent、MCP 生态
MCP 工具客户端连 MCP ServerServer 进程内执行;模型仍只出 JSON工具列表執行環境發現本地/遠端工具目錄要热插拔

真正分水岭不是「谁支持 Function Calling」(2026 年三家都支持),而是参数是字符串还是对象、並行呼叫怎么对齐、以及失败结果如何写回。閘道层(OpenRouter / 自建)通常把三家歸一成内部 ToolCall{name, id, args},再分发到同一 L2 Runtime。

三家 JSON 怎么写(How)

下面用同一个 get_weather 工具对照。生产环境请把 description 写清边界(「只查公开气象,不查个人位置」),避免模型把不该暴露的字段塞进参数。

OpenAI:tools + tool_calls

请求侧把工具挂在 tools。模型若决定呼叫,助手消息带 tool_callsarguments字符串化的 JSON,你必须先 parse 再校驗。

{
  "model": "gpt-4.1",
  "messages": [{"role": "user", "content": "What's the weather in Beijing?"}],
  "tools": [{
    "type": "function",
    "function": {
      "name": "get_weather",
      "description": "Current weather for a city",
      "parameters": {
        "type": "object",
        "properties": {
          "city": {"type": "string", "description": "City name"},
          "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
        },
        "required": ["city"]
      }
    }
  }]
}

模型返回形态(简化):

{
  "role": "assistant",
  "tool_calls": [{
    "id": "call_abc123",
    "type": "function",
    "function": {
      "name": "get_weather",
      "arguments": "{\"city\":\"Beijing\",\"unit\":\"celsius\"}"
    }
  }]
}

执行后,你再发一条 role: tool(或 Responses API 等价字段),tool_call_id 对齐,content 放结果字符串。然后模型用自然语言或再一次 tool_call 继续。

Gemini:functionDeclarations + toolConfig

Gemini 把宣告放在 tools[].functionDeclarations。类型字段习惯用大写。用 toolConfig.functionCallingConfig.mode 可设 AUTOANY(必须调工具)或 NONE(禁止调工具)——这是产品开关,不是安全沙箱。

{
  "contents": [{"role": "user", "parts": [{"text": "What's the weather in Beijing?"}]}],
  "tools": [{
    "functionDeclarations": [{
      "name": "get_weather",
      "description": "Current weather for a city",
      "parameters": {
        "type": "OBJECT",
        "properties": {
          "city": {"type": "STRING"},
          "unit": {"type": "STRING", "enum": ["celsius", "fahrenheit"]}
        },
        "required": ["city"]
      }
    }]
  }],
  "toolConfig": {"functionCallingConfig": {"mode": "AUTO"}}
}

模型侧常见 functionCall part(name + args 对象)。你执行后回 functionResponse part。不要假设字段名与 OpenAI 完全一致,SDK 版本之间也有 Chat vs Gemini 原生差异。

Claude:tools + tool_use / tool_result

Claude Messages API 的工具用 input_schema(JSON Schema)。助手回复是 content 块数组:可能先有一段 text,再跟 tool_useinput 已经是对象,少一次 parse,但仍要做 schema 校驗——模型仍可能漏字段。

{
  "model": "claude-sonnet-4-6",
  "max_tokens": 1024,
  "tools": [{
    "name": "get_weather",
    "description": "Current weather for a city",
    "input_schema": {
      "type": "object",
      "properties": {
        "city": {"type": "string"},
        "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
      },
      "required": ["city"]
    }
  }],
  "messages": [{"role": "user", "content": "What's the weather in Beijing?"}]
}
{
  "role": "assistant",
  "content": [{
    "type": "tool_use",
    "id": "toolu_01XYZ",
    "name": "get_weather",
    "input": {"city": "Beijing", "unit": "celsius"}
  }]
}

把结果写回时,用 role: usertool_resulttool_use_id 必须一致:

{
  "role": "user",
  "content": [{
    "type": "tool_result",
    "tool_use_id": "toolu_01XYZ",
    "content": "{\"temp_c\": 28, \"condition\": \"clear\"}"
  }]
}

Claude Code / Cursor 等 IDE Agent 在此之上又加了 MCP:模型看到的仍是「一组带 JSON Schema 的工具」,只是进程通过 MCP 会话热插拔。協議变了,循环没变

场景怎么选(决策矩阵)

如果你是…就选原因
已有 OpenAI 兼容閘道统一成 OpenAI tools 方言生态最大;下游 adapter 一次写成
主栈在 GCP / VertexGemini functionDeclarations + mode少一层翻译;mode 适合「这一轮必须调检索」
主力是 Claude Code / AnthropicClaude tools + MCPcontent 块与 IDE 工具目錄一致
要同时接三家模型内部规范化 ToolCall + 每家 adapter不要让业务程式碼写三套 if-else
工具会改檔案 / 跑命令遠端 Mac 工作区 + 路径白名单JSON 再漂亮也挡不住错误 rm
只要只读 SaaS API无伺服器函式 + 金鑰托管无需整机;仍要做参数 allowlist

組合 A — 个人最快(半天)

  • 单模型:OpenAI 或 Claude,注册 1–3 个只读工具(搜索、天气、文档检索)。
  • 参数校驗:用 JSON Schema 库拒绝额外字段;金鑰放环境变量,永不进 prompt。
  • 日誌:记录 tool, args_hash, latency, ok,不要把完整金鑰或 PII 打进日誌。

組合 B — 小团队生产(推薦)

  • 閘道歸一:对内 ToolCall;对外 adapter 到 OpenAI / Gemini / Claude。
  • L2 Policy:按工具分超时、並行、日限额;危险工具二次确认或仅在隔離节点运行。
  • 执行面:只读 API 用函式计算;写仓库 / 跑测试放到 Cloud Mac 会话,对齐 遠端 Mac 自动化 的銷毀纪律。
  • 记忆与工具参数分离:用户偏好走 Memory,不塞进每次 arguments

組合 C — 企业合规

  • 工具目錄走审批;schema 变更打 PR。
  • MCP / 自定义 server 跑在无出网或受控 VPC;稽核 JSONL 出工作区。
  • 禁止把 bash 做成万能工具而不带路径策略。

常见誤區

  1. 以为模型会替你鉴权——Key 在 Runtime;模型只看到 schema 与历史结果。
  2. 把 OpenAI 的字符串 arguments 直接当对象用——先 parse,失败当模型错误重试或降级。
  3. description 写成「万能助手」——描述越泛,模型越爱乱调工具;写清何时不该呼叫。
  4. 忽略並行 tool_calls——两个呼叫共享可变状态会竞态;只读可並行,写入要串行或加锁。
  5. 把失败当无结果——应回传结构化 error,让模型改参数或换工具,而不是沉默。
  6. MCP = 安全——MCP 是传输与發現;root 设成家目錄照样裸奔。

落地步骤(7 步 Action Plan)

  1. 列出工具清单——名称、副作用级别(只读 / 写入 / 不可逆)、超时、数据驻留。
  2. 写 JSON Schema——必填、enum、禁止 additionalProperties;description 写边界。
  3. 实现最小 loop——一次用户消息 → 可能的 tool_calls → 执行 → 回填 → 最终回答;先单工具。
  4. 加校驗与金鑰隔離——parse 失败、schema 失败、未知工具名一律拒绝并稽核。
  5. 接第二家模型 adapter——证明内部 ToolCall 可映射 Claude content 块与 Gemini parts。
  6. 给写入类工具加沙箱——路径白名单或遠端工作区;对照檔案系统指南做 deny 测试。
  7. 观测 7 天——统计误呼叫率、平均 round-trip、並行冲突;把高频误呼叫改成更窄的 schema。

FAQ

Function Calling 和普通 JSON mode 有什么区别?

JSON mode / structured output 約束的是最终回复形状(例如抽出订单字段)。Function Calling 約束的是中间的工具请求,并且預設会进入多轮:执行后再生成。两者可組合,但解决的问题不同。

模型会不会直接访问我的資料庫?

不会。除非你的 Runtime 把「任意 SQL」做成工具且未做权限。預設循环里模型只能提出符合 schema 的参数。

三家能不能共用一份 schema?

核心 JSON Schema 可以共用,再写成各家信封(OpenAI parameters、Gemini 大写 type、Claude input_schema)。枚举与必填要回归测试,因为各家对 strict 的实现不完全一样。

Claude Code 里的工具是 Function Calling 吗?

是同一类循环:模型产出结构化呼叫,宿主执行(含 MCP)。差别在工具目錄由 IDE/MCP 动态提供,而不是你每次在 HTTP 请求里手写 tools 数组。

工具结果要不要进长期记忆?

原始 API 响通常太大且含瞬时数据。应摘要后写入 Memory,而不是把整段 tool_result 当永久状态。详见 說明中心 与 Memory 选型文。

總結

2026 年谈 Function Calling,请把它当成带 schema 的 RPC:OpenAI、Gemini、Claude 只是三种 JSON 方言,共同语法是「模型提议、執行環境执行、结果回填」。选型看你的模型閘道与工具副作用;安全看 L2 校驗与执行面隔離,而不是看哪家的营销名。

上线前自问:如果模型此刻发出 write_file,实际落盘的是哪台机器、哪个目錄? 若答不上来,先别接写入类工具。只读 API 可以今天就接;改程式碼、跑测试,请放到可銷毀的 Cloud Mac 节点,并先看清 方案定價

延伸閱讀

把工具執行放到隔離的 Cloud Mac 節點

天氣查詢可以在無伺服器函式裡跑;改倉庫、跑測試、調內網 API 則需要可銷毀的執行環境。遠端 Mac 節點按會話隔離工作區,適合 Claude Code / Cursor / 自研 tool loop。

立即訂購 · 查看定價

Function Calling

把工具執行放到隔離的 Cloud Mac 節點

M4 · Cloud Mac · isolated tool runtime

立即訂購