OpenAI Responses API 函数调用与安全接入
模型只提出调用,应用负责执行。本文逐字段说明 Responses 的函数调用结构,并标出仍需真实 Key 验证的能力。
函数调用实际做了什么
模型不会替你执行函数。它只返回结构化调用;应用需要验证参数、运行允许的代码,再把结果传回模型。模型生成的参数必须按不可信输入处理。
| 步骤 | Responses API 数据 | 应用职责 |
|---|---|---|
| 1. 定义 | 在 tools[] 中提供 JSON Schema | 只暴露允许调用的函数 |
| 2. 请求 | output[] 可能包含 function_call | 解析 name、arguments 和 call_id |
| 3. 执行 | 模型不会执行外部操作 | 鉴权、校验、执行并记录 |
| 4. 继续 | 用相同 call_id 返回 function_call_output | 请求最终回答 |
先验证接口、Key 和模型
请求 GET /v1/models,再使用当前 Key 返回的准确模型 ID。2026 年 8 月 3 日,未携带 Key 的生产 POST 探测到达 /v1/responses 并返回 401 API_KEY_REQUIRED。这只能证明接口和认证中间件可达,不能证明某个模型支持函数调用。
curl -sS https://monkeytheme.com/v1/models \ -H "Authorization: Bearer ***"
本次复核没有使用客户 Key 执行下方工具请求。涉及写入、支付、消息或账号操作前,请使用计划上线的模型和 schema 在非生产流程中测试。
发送最小 Responses API 工具定义
OpenAI 当前函数调用文档要求把 Responses 函数字段直接放在 tools 项内。下面的 schema 要求一个字符串参数,并拒绝额外字段。
curl -sS https://monkeytheme.com/v1/responses \
-H "Authorization: Bearer ***" \
-H "Content-Type: application/json" \
-d '{
"model": "MODEL_ID_FROM_LIST",
"input": "What is the weather in Paris?",
"tools": [{
"type": "function",
"name": "get_weather",
"description": "Return current weather for a city.",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string"}
},
"required": ["city"],
"additionalProperties": false
},
"strict": true
}]
}'严格模式要求每个属性都列入 required,且每个对象都设置 additionalProperties: false。可选值应使用包含 null 的类型表示。
执行调用并返回结果
一次 Responses 返回可能没有函数调用,也可能有一个或多个。应遍历全部 output 项,不能假设第一项就是文本。
import json
from openai import OpenAI
client = OpenAI(
api_key="YOUR_KEY",
base_url="https://monkeytheme.com/v1",
)
response = client.responses.create(
model="MODEL_ID_FROM_LIST",
input="What is the weather in Paris?",
tools=[weather_tool],
)
next_input = list(response.output)
for item in response.output:
if item.type != "function_call":
continue
args = json.loads(item.arguments)
result = dispatch_approved_function(item.name, args)
next_input.append({
"type": "function_call_output",
"call_id": item.call_id,
"output": json.dumps(result),
})
final = client.responses.create(
model="MODEL_ID_FROM_LIST",
input=next_input,
tools=[weather_tool],
)
print(final.output_text)dispatch_approved_function 是应用代码,并非 SDK 自带函数。它必须拒绝未知函数名,并在执行任何外部操作前检查权限。
Responses 与 Chat Completions 的结构不同
| 字段 | Responses | Chat Completions |
|---|---|---|
| 函数定义 | 函数各字段直接位于 tools[] 项内 | 函数各字段位于 tools[].function |
| 返回调用 | output[] 中类型为 function_call 的项 | choices[0].message.tool_calls[] |
| 关联字段 | call_id | 返回工具消息时使用 tool_call_id |
| 函数结果 | function_call_output 输入项 | role: tool 消息 |
给执行器加上安全边界
- 使用函数名白名单,禁止把模型给出的名称映射到任意代码。
- 解析 JSON 后再次执行服务端校验,并拒绝未知字段。
- 对每个资源 ID 检查当前用户权限。
- 破坏性操作或对外可见操作必须要求确认。
- 写操作使用幂等键,并按 call ID 保留审计记录。
- 返回内容应限制大小并移除敏感数据,不能把密钥送回模型上下文。
资料与相关教程
常见问题
模型会直接执行函数吗?
不会。模型只返回结构化调用。应用决定是否执行,并把结果传回模型。
收到 401 能证明函数调用可用吗?
不能。401 只能证明请求到达认证层。应使用真实 Key 和准确模型 ID 测试函数调用。
strict 模式能代替权限检查吗?
不能。strict 只约束参数结构。应用仍需认证用户、检查资源权限并验证业务规则。
一次响应会返回多个函数调用吗?
可能。OpenAI 建议应用按零个、一个或多个调用处理,并遍历返回的调用项。
Responses 能直接使用 Chat Completions 的工具结构吗?
不能。函数定义、返回调用和工具结果消息的结构都不同,必须明确转换。