Function Calling 是什么?AI Agent 接 API 的关键能力与接入实战
Function Calling 是 AI Agent 接入外部工具和 API 的关键能力。本文用开发者能落地的方式讲清原理、接入步骤、常见错误,以及如何用 APIBox 快速验证。
如果你在做 AI Agent、工作流自动化或企业内部助手,Function Calling 基本就是“能不能真正接 API 干活”的分水岭。一句话理解:它让模型不只是“会说”,而是能按结构化参数去调用天气、搜索、数据库、工单、支付、CRM 等外部工具。对开发者来说,重点不是概念,而是 什么时候该用、参数怎么设计、怎么避免调用翻车。本文会用 APIBox 的 OpenAI 兼容接法,把这件事讲到能落地。
一、Function Calling 解决的到底是什么问题
很多人第一次做 Agent,都会先用 Prompt 硬写:
- 让模型“根据用户问题决定是否查天气”
- 让模型“尽量按 JSON 输出”
- 让模型“如果需要查库存就返回商品 ID”
这套方法能跑,但一进生产环境就容易出问题:
- 输出格式不稳定
- 参数字段名经常漂
- 同一个问题不同轮次行为不一致
- 一旦接真实 API,就会出现字段缺失、类型错误、误调用
Function Calling 的作用,就是把“调用工具”这件事,从自然语言提示词,改成更稳定的结构化协作流程。
它最适合的 4 类场景
| 场景 | 典型动作 | 是否建议用 Function Calling |
|---|---|---|
| 查外部实时信息 | 天气、汇率、物流、库存 | 强烈建议 |
| 执行业务动作 | 创建工单、发消息、下订单 | 强烈建议 |
| 调内部系统 | CRM、数据库、权限系统 | 强烈建议 |
| 纯内容生成 | 写文案、总结文章、改写文本 | 不一定需要 |
结论很简单:只要模型需要“拿数据”或“做动作”,就优先考虑 Function Calling。
二、它的工作原理到底是什么
Function Calling 不是模型真的去执行函数,而是:
- 你把可用工具的描述和参数 schema 发给模型
- 模型判断当前问题要不要调用工具
- 如果要调用,它返回结构化的工具名和参数
- 你的程序收到后,自己去执行真实 API
- 再把工具结果回传给模型,让模型生成最终回答
也就是说:
- 模型负责决策和参数生成
- 你的应用负责真正执行
一个最常见的调用流程
用户:北京今天下雨吗?
↓
模型:需要调用 get_weather(city="北京")
↓
你的后端:请求天气 API
↓
工具返回:{"city":"北京","condition":"多云","temp":19}
↓
模型:今天北京多云,19℃,降雨概率较低三、开发者最容易踩的 5 个坑
1. 工具定义写得太宽泛
坏例子:
get_infoquery_systemdo_action
这种名字对模型来说太模糊,它很难知道什么时候该调、该传什么。
更好的写法:
get_weather_by_citysearch_order_by_idcreate_support_ticket
函数名越具体,模型越容易稳定。
2. 参数 schema 不够严格
如果你只是写一个大概描述,而没有明确:
- 字段名
- 字段类型
- 必填项
- 枚举值
- 参数含义
模型就会自由发挥,最后最痛苦的是后端。
3. 让一个工具做太多事
比如一个 manage_order 同时支持:
- 查询订单
- 取消订单
- 修改地址
- 申请退款
这会让模型决策空间过大。更稳的办法通常是拆成多个职责清晰的工具。
4. 工具返回值不规范
如果你的工具返回一大段自然语言,模型二次处理时反而容易丢信息。
更好的方式:
- 结构化 JSON
- 字段含义清晰
- 错误码统一
5. 没有失败兜底
真实环境里,工具调用经常失败:
- 上游 429
- 参数非法
- 权限不足
- 接口超时
如果你没设计失败分支,用户体验会很差。
四、什么时候应该用,什么时候不该用
建议用的情况
- 你需要查询实时数据
- 你需要让模型调内部业务系统
- 你要做多步骤 Agent
- 你需要稳定的结构化参数输出
- 你要让工作流节点可观测、可审计
不建议一上来就用的情况
- 只是简单写文案
- 只是摘要、翻译、润色
- 还在做最早期 DEMO,目标只是先验证一句话能不能生成
一句话判断:
如果结果要进入代码逻辑或业务动作,就尽量不用“纯 Prompt 猜格式”,而用 Function Calling。
五、一个能直接跑的最小示例
下面用 OpenAI 兼容 SDK 演示。你可以直接把 base_url 指向 APIBox,快速测试支持工具调用的模型。
from openai import OpenAI
import json
client = OpenAI(
api_key="YOUR_APIBOX_KEY",
base_url="https://api.apibox.cc/v1"
)
tools = [
{
"type": "function",
"function": {
"name": "get_weather_by_city",
"description": "根据城市名称获取实时天气",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "中文城市名,例如北京、上海、深圳"
}
},
"required": ["city"]
}
}
}
]
response = client.chat.completions.create(
model="gpt-5",
messages=[
{"role": "user", "content": "帮我查一下北京今天天气"}
],
tools=tools,
tool_choice="auto"
)
msg = response.choices[0].message
print(msg)如果模型触发了工具调用,下一步怎么做
你需要取出工具名和参数,自己执行真实函数:
tool_call = msg.tool_calls[0]
function_name = tool_call.function.name
arguments = json.loads(tool_call.function.arguments)
if function_name == "get_weather_by_city":
result = {
"city": arguments["city"],
"condition": "多云",
"temp": 19
}然后把工具结果再发回模型,让它生成最终回答:
second_response = client.chat.completions.create(
model="gpt-5",
messages=[
{"role": "user", "content": "帮我查一下北京今天天气"},
msg,
{
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(result, ensure_ascii=False)
}
]
)
print(second_response.choices[0].message.content)六、参数设计怎么做才稳
这是最关键的实战部分。
推荐的参数设计规则
| 规则 | 错误写法 | 更好的写法 |
|---|---|---|
| 函数名具体 | do_task | create_support_ticket |
| 字段名语义清晰 | q | user_question |
| 类型明确 | 模糊描述 | string / integer / boolean |
| 必填项收紧 | 全部可选 | 明确 required |
| 枚举尽量固定 | 任意字符串 | order_status: pending/shipped/cancelled |
一个比较稳的工单工具示例
{
"type": "function",
"function": {
"name": "create_support_ticket",
"description": "为用户创建售后工单",
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "订单号"
},
"issue_type": {
"type": "string",
"enum": ["refund", "delivery", "invoice", "other"],
"description": "问题类型"
},
"user_message": {
"type": "string",
"description": "用户原始问题"
}
},
"required": ["order_id", "issue_type", "user_message"]
}
}
}这个定义有几个好处:
- 模型不容易乱传字段
- 后端更容易校验
- 日志更清晰
- 出错更容易排查
七、如何把它接到 AI Agent 或工作流里
如果你在做 Agent,常见的接法一般分三层:
方案 1:单模型 + 多工具
适合:
- 客服助手
- 查询助手
- 企业知识 + 内部 API 混合场景
特点:接入简单,但工具多了之后治理成本会上升。
方案 2:分类模型 + 工具执行模型
流程示意:
用户问题
↓
轻量模型做意图分类
↓
决定是否调用工具
↓
主模型负责参数生成与回答适合:
- 请求量大
- 对成本敏感
- 任务分层明显
方案 3:工作流平台接入
如果你在用:
- Dify
- n8n
- Flowise
- 自研工作流引擎
通常都可以通过 OpenAI 兼容接口快速接入 APIBox,然后把支持 Function Calling 的模型挂进去做验证。
八、成本和性能上怎么权衡
Function Calling 比纯文本问答更贵一点,主要贵在:
- 多轮请求
- 工具调用中间状态
- 参数生成 + 结果总结
成本主要受 4 个因素影响
| 因素 | 影响 |
|---|---|
| 工具描述长度 | tools schema 越长,输入 token 越高 |
| 调用轮数 | 一次问答变两次甚至三次请求 |
| 模型选择 | 高级模型单价更高 |
| 工具结果长度 | 返回内容越长,二次总结越贵 |
实际建议
- 轻任务:先用低成本模型试工具决策
- 重任务:把关键步骤交给更强模型
- 长工具描述:要压缩,不要写成文档
- 工具结果:只返回必要字段,不要整页 JSON 原样塞回去
如果你本来就在做多模型接入,APIBox 这种统一入口的价值会更明显:
- 方便切模型验证效果
- 不用换 SDK
- 不用为每家供应商单独接一套
九、最推荐的落地检查清单
一篇文章讲原理不够,真正上线前至少过这份表:
上线前检查
- 每个工具的名称是否具体可理解
- 参数字段是否有类型和必填约束
- 是否设计了失败分支和超时处理
- 是否记录了 tool_call 日志
- 是否限制了模型可用工具范围
- 是否避免把整个数据库查询结果原样返回给模型
- 是否区分了测试模型和生产模型
不建议的做法
- 一个工具干所有事
- schema 写得像自然语言说明文
- 返回值全靠模型自己猜
- 出错就无限重试
- 只在单次 DEMO 场景测过,没有测异常场景
十、总结
Function Calling 的真正价值,不是“多一个炫技功能”,而是让 AI Agent 从“会聊天”变成“能接系统、能做动作、能稳定协作”。
如果你现在正准备做:
- AI Agent
- 工作流自动化
- 企业内部助手
- 需要查实时数据或执行 API 的 LLM 应用
那你最该优先做好 3 件事:
- 工具定义要具体
- 参数 schema 要严格
- 调用失败要有兜底
如果只是想先低成本验证,直接用 OpenAI 兼容 SDK + APIBox 的 base_url 切换,通常是最快的起步方式。先把工具链路跑通,再谈复杂 Agent 架构,会更稳。
立即体验,注册后加客服并发送账号 ID,可限时领取 ¥10 体验额度
免费注册 →