Function Calling 让模型能把自然语言转成结构化调用,但它没有把模型变成可信后端。{"name":"delete_project","arguments":...} 只是一份候选意图:参数可能不完整,用户可能无权操作,外部文本可能包含提示注入,网络重试还可能把副作用执行两次。真正的执行权必须留在应用。
本文面向准备开放数据库、支付、工单、文件或 MCP 能力的开发者。你需要熟悉身份认证、RBAC/ABAC、事务与重试。我们用四道闸门把模型建议变成可审计命令:契约、权限、幂等执行与安全证据。
图 1(1600 × 900):WEB/SUN 原创 SVG。模型调用位于闸门之外;越靠近真实副作用,越不能依赖自然语言保证。
闸门一:参数只表达最小意图
官方函数调用指南将工具定义为模型可考虑的能力,并把调用流程明确分成“模型提出调用—应用执行—应用回传结果”。因此工具 Schema 是模型与执行器的协议,不是执行器本身。
一个好工具只接收完成意图所需的字段。比如 cancel_order 可以接收 orderId 和有限枚举的 reason;不要接收 userId、isAdmin、tenantId 或最终退款金额,因为这些可信事实应由服务端根据认证上下文和订单状态计算。
const cancelOrderTool = {
type: 'function',
name: 'cancel_order',
description: 'Request cancellation for one order owned by the current account.',
strict: true,
parameters: {
type: 'object',
properties: {
orderId: { type: 'string', description: 'Order identifier beginning with ord_' },
reason: { type: 'string', enum: ['duplicate', 'changed_mind', 'other'] },
},
required: ['orderId', 'reason'],
additionalProperties: false,
},
} satisfies FunctionTool;
严格模式要求对象禁用额外字段,并把所有 properties 列为 required;可选值用包含 null 的类型表达,具体限制见官方Strict mode。Schema 通过后还要做领域校验:ID 是否存在、字符串长度是否合理、状态是否允许取消。解析 arguments 必须捕获错误,未知工具名必须默认拒绝,绝不能用 eval 或任意动态导入执行模型给出的名称。
工具描述也属于安全边界。写清适用条件、非目标和失败语义,避免“manage_order”这种权限跨度过大的万能工具。读取、预览、提交最好拆开:preview_cancellation 可以返回影响,commit_cancellation 才产生副作用,并要求确认令牌。
闸门二:工具可见不等于用户有权
tools 列表和 tool_choice 控制模型可以选择什么,不构成授权。即便只给某用户暴露一个工具,执行时仍要重新检查:认证主体是谁,资源属于哪个租户,动作是否在当前角色和环境允许范围,资源状态是否满足前置条件。
授权信息从服务端会话进入执行器,不能从模型参数或检索内容进入。可以把判定写成纯函数:
authorize({
subject: auth.userId,
tenant: auth.tenantId,
action: 'order.cancel',
resource: freshOrder,
environment: runtime.environment,
});
每次请求只暴露完成当前阶段所需的最小工具集。OpenAI 的工具指南说明可以通过配置控制模型使用工具;应用可以在“只读查询”和“已验证身份后的变更阶段”传入不同集合。这样减少模型误选,却仍不能省略执行时授权。
高影响操作增加人类确认。确认页显示规范化后的对象、影响范围与不可逆后果,而不是展示模型原始句子。确认令牌要绑定用户、资源、动作、参数摘要和短有效期,防止用户确认 A 后参数被换成 B。
闸门三:副作用需要幂等状态机
网络会超时,浏览器会重连,模型可能重复提出同一工具,队列也可能至少投递一次。对写操作说“不要重复调用”没有用;幂等必须由执行层保证。
幂等键应绑定业务意图,而不是只用随机请求 ID。一个可行组合是 tenant + operation + resource + confirmedParametersHash + workflowStep。执行记录维护 reserved → running → succeeded | failed,并保存可安全返回的结果摘要:
- 原子写入幂等键;若已存在,读取既有状态。
succeeded直接返回先前结果,不再执行副作用。running返回处理中,或由协调器等待;不要并发重复执行。- 只有确认不会产生重复副作用的失败才允许自动重试。
- 不确定外部系统是否已提交时,先用外部幂等键或查询接口对账。
call_id 用来把工具结果关联回某次模型调用,但它不必然等于业务幂等键。一次工作流恢复后可能出现新的 call ID,却仍代表同一“取消订单”意图;反过来,同一工具名和参数在不同租户也绝不能共用结果。
重试预算要分工具设置。纯读取可以指数退避;发信、扣款、删除或发布必须依赖目标系统的幂等能力和状态查询。超过预算后返回稳定错误码和人工恢复路径,不要让模型无限换措辞再试。
闸门四:把不可信数据和能力隔开
工具让提示注入从“回答跑偏”升级成“可能执行动作”。官方代理安全指南将 prompt injection 和私有数据泄漏列为核心风险,并指出即使结合缓解措施,代理仍可能出错。安全设计因此不能只靠一句“忽略恶意指令”。
首先,网页、邮件、文档和用户文本始终标为不可信数据,不拼入 developer message。其次,节点间只传明确字段和枚举,不把检索到的整段文本直接变成下一节点命令。第三,工具输入、输出都做最小化:查询只返回完成任务所需字段,错误不暴露堆栈、密钥和内部拓扑。
审批要覆盖读和写的风险差异。读取私有通讯录、文件或客户数据本身就可能泄露,不能因为“没有修改”而无条件开放。官方指南建议工具审批保持开启,并用 guardrail、结构化输出、清晰策略、trace grader 与 eval 组合降低风险;文档同时强调这些手段不能完全消除攻击。
审计记录至少包含:追踪 ID、用户与租户、工具与版本、规范化参数摘要、授权决定、审批主体、幂等键、开始与结束状态、裁剪后的输出和错误分类。敏感值应脱敏或哈希,密钥绝不落日志。OpenAI 的生产最佳实践同样要求 API key 不进入代码或公开仓库,而应由环境变量或秘密管理服务提供。
结果信封与错误语义
工具输出给模型时使用稳定信封,避免把内部异常原样塞回上下文:
{
"ok": false,
"code": "APPROVAL_REQUIRED",
"message": "This operation needs user confirmation.",
"retryable": false,
"data": null
}
模型可以据此向用户解释下一步,但不能自行把 retryable 改成 true。错误类别至少区分参数无效、未认证、无权限、需确认、资源冲突、可重试依赖故障和未知故障。对用户展示友好文案,对运行系统保存受保护的详细原因。
工具返回成功也不要让模型成为唯一回执。写操作的 UI 应从业务 API 查询最终状态;模型只负责解释。这样即使最终自然语言生成失败,用户仍能看到订单到底有没有取消。
测试矩阵
每个工具至少测试:合法调用;未知字段和错误类型;跨租户资源;过期确认;重复 call ID;新 call ID 但同一业务意图;执行中重试;外部提交后响应丢失;工具输出含提示注入;超长输出;用户拒绝审批;达到轮次和时间预算。
断言不只看最终文案,还要看工具是否被选择、参数是否规范化、授权是否执行、同一幂等键只产生一次副作用、日志是否没有敏感正文。对抗测试要进入持续回归,而不是上线前临时演示。
失败模式与取舍
最危险的捷径包括:Schema 通过就直接执行;让模型传用户身份;按函数名动态反射;把 tool_choice: required 当成“必须成功”;仅用 call ID 去重业务操作;把完整数据库记录返回模型;审批只保护写操作;失败后整轮无限重试。
四道闸门会增加延迟与代码量,确认也会中断顺滑体验。风险越低,可以越自动:公开只读搜索可以自动执行;内部私有读取需要最小范围和审计;财务、删除、外部发布则需要强授权、幂等和显式确认。体验优化应发生在清晰展示影响与快速恢复上,而不是移除边界。
结论
模型擅长把用户意图映射为候选工具与参数,却不掌握可信身份、实时业务状态和副作用语义。安全的工具系统让调用依次通过严格契约、服务端授权、业务幂等和最小化审计,并为确认、超时和不确定结果保留恢复路径。
一句可以写进代码评审清单的话是:模型提出建议,执行器验证意图,授权系统决定资格,业务系统确认结果。 四个角色不合并,工具调用才是能力,而不是漏洞放大器。
Sources
- Function calling — OpenAI,访问于 2026-07-16。
- Using tools — OpenAI,访问于 2026-07-16。
- Safety in building agents — OpenAI,访问于 2026-07-16。
- Production best practices — OpenAI,访问于 2026-07-16。