Function Calling 让模型不再输出一段难以解析的“Action 文本”,而是返回工具名和结构化参数。
这确实解决了很多格式问题。
但结构化不等于正确。
模型可以输出合法 JSON,却把 top_k 设得过大;可以满足字符串类型,却把关键词填进 URL 字段;可以选中正确工具,却漏掉当前页面 ID;也可以生成业务上不允许的参数组合。
更危险的是,程序若看到 Schema 校验通过就直接执行,越权访问、重复写入、资源消耗和错误证据都会进入真实系统。
所以面试官问“怎样保证工具调用参数正确”时,真正想听的是:
JSON Schema 能约束什么、不能约束什么,参数在执行前要经过哪些校验,错误怎样修复,工具版本和兼容性怎样管理,以及如何证明 Schema 改动真的提高了成功率而没有引入新误用?
Function Calling 解决了哪一类问题?
文本标签方案常让模型输出:调用 search,参数是某个关键词。
程序还要用正则从自然语言中提取工具名、引号和参数。模型多写一句解释、漏一个括号或换一种格式,解析就可能失败。
Function Calling 让模型按照工具定义返回结构化调用。程序可以直接读取工具名和参数对象,避免大量脆弱字符串解析。
它主要改善的是语法层和接口层:结构更稳定,工具列表更明确,参数类型可声明,错误更容易定位。
它没有自动解决语义层和业务层。一个 JSON 对象完全合法,也可能对当前任务毫无意义。因此“能解析”只是执行前的第一关。

Function Calling 提高结构稳定性,但语义、权限和执行安全仍需系统校验。
一个工具 Schema 应该表达什么?
第一,稳定且明确的工具名。
名字应表达动作,不与其他工具高度相似。search_web 和 visit_page 比两个都叫“获取信息”更容易路由。
第二,具体 description。
说明工具做什么、什么时候用、什么时候不用、输出是什么证据等级。description 是模型理解工具的主要说明书。
第三,参数类型和必填项。
URL、查询词、数量、时间范围和枚举选项要有明确类型。真正必须执行的字段写进 required,不要让后端靠默认值猜。
第四,取值约束。
数量可以声明上下界,固定选项使用 enum,字符串可限制空值和合理长度。没有业务需要时,不接受额外字段。
第五,字段语义。
参数说明要写清单位、格式和来源。例如时间是日期还是时间戳,top_k 是候选数还是最终证据数,url 是否必须来自前一步 Search。
第六,版本和兼容信息。
字段改名、枚举调整和默认值变化都可能影响模型行为。Schema 应有版本,服务端知道当前请求使用哪一版。
Schema 能验证什么,不能验证什么?
Schema 可以发现字段缺失、类型错误、未知枚举、超出显式范围和多余字段。
但很多错误仍然完全合法。
字符串类型的 URL 可能指向不存在页面。
合法日期可能超出用户要求的时间范围。
top_k 在允许范围内,却超过当前工具预算。
两个单独合法的字段组合起来可能矛盾,例如开始时间晚于结束时间。
页面 ID 存在,但不属于当前租户或当前任务。
工具名正确,当前研究阶段却应该先 Search 而不是 Visit。
因此要区分三层正确性:语法正确、业务语义正确、当前执行上下文正确。JSON Schema 主要覆盖第一层和一部分静态业务约束,后两层必须由程序和状态共同判断。
参数校验应该分成哪几层?
第一层是解析校验。
确认调用对象可读取,工具名存在,参数能够解析为预期结构。
第二层是 Schema 校验。
检查必填、类型、枚举、范围、格式和未知字段。错误信息要精确到字段。
第三层是业务规则校验。
检查字段组合、单位、时间顺序、数量预算和工具特定约束。例如 Visit 的 URL 必须来自允许的协议和来源范围。
第四层是状态校验。
当前是否已有 URL,是否重复调用,当前缺口是否需要这个工具,输入数据是否已经核验。
第五层是权限与安全校验。
用户或租户是否有权调用,目标资源是否可访问,是否包含危险路径、任意代码或敏感参数。
第六层是幂等和副作用校验。
只读工具主要防重复成本。有写操作时,必须使用幂等键、用户确认和审计,防止重试造成重复副作用。
全部通过后,调用才进入网关。不能让工具自己承担所有拒绝逻辑,因为那样错误已经走到执行边界。

结构化调用先经过解析、Schema、业务、状态、权限和幂等检查,再执行。
为什么 required 越多不一定越好?
必填字段能减少后端猜测,但过度必填会让模型为了通过格式而编造值。
例如 Visit 工具需要 URL。如果当前状态没有任何候选链接,正确行为应该先 Search,而不是要求模型必须填一个 URL。Schema 把 URL 设为必填没有错,路由层还要阻止此时选择 Visit。
另一个例子是时间范围。任务未指定时间时,强制要求开始和结束日期,模型可能随意补一个范围。更合理的做法是让时间字段可选,同时在业务层根据任务类型决定是否必须向用户澄清。
所以 required 表达的是“调用这个工具时必须提供”,不是“系统任何时候都必须生成”。工具选择和参数完整性必须配合。
enum、范围和额外字段怎样使用?
enum 适合真正封闭的选项,例如排序方向或预定义来源类型。
如果选项经常扩展,过窄 enum 会让模型无法表达新能力;过宽自由字符串又会产生拼写和兼容问题。可以在稳定内部代码和用户可读标签之间做映射。
数值范围应来自工具真实能力和产品预算,不能随意写一个看起来合理的上限。服务端仍需再次校验,不能相信客户端或模型一定遵守 Schema。
额外字段默认应谨慎。允许模型随意附加未知参数,后端不同版本可能产生不可预测行为。若确实需要扩展区,可以明确一个 options 对象并对其内容做白名单,而不是让顶层无限开放。
Schema 设计目标是减少歧义,不是把所有未来变化一次塞进去。
参数语义错误怎样识别?
语义错误常常需要结合当前状态。
Search 的 query 类型正确,但遗漏核心实体和时间条件,结果会跑偏。可以检查它是否覆盖当前子任务的关键槽位。
Visit 的 URL 合法,但指向已经访问且内容未更新的页面。可以结合已访问集合和页面版本判断重复。
Scholar 的关键词正确,却用来查产品当前配置。路由目的与工具能力不匹配,需要在执行前拒绝或建议换工具。
Python 的表达式合法,但输入数据来自尚未核验的搜索摘要。系统应阻止把候选线索包装成精确计算。
语义校验不必全部依赖另一个大模型。高风险、稳定规则适合程序判断;开放语义可以用小模型或主模型给出候选,再通过状态和规则约束。
错误返回应该怎样写,模型才会修?
“Invalid arguments”信息太少。
一个可修复错误应包含错误类别、字段路径、当前值、期望约束和下一步建议。
例如:“参数 top_k 超过当前允许范围,请在允许范围内重新生成;不要修改 query。”
又如:“Visit 缺少候选 URL,当前研究状态没有已发现页面。请先调用 Search,或结束并说明无法访问。”
错误信息不应包含内部堆栈、密钥和敏感路径,也不应把工具返回的网页指令直接当成系统要求。
修复重试要有配置上限,并保留原调用与错误。模型连续生成同类错误,或已达到当前工具配置的重试上限时,应切换策略、降级或停止,不能无限自我纠正。
修复参数时,怎样避免越修越错?
第一种方法是最小修复。
只修改出错字段,其他已通过字段保持不变。完全重新生成整组参数,可能修好 top_k 却改坏 URL。
第二种方法是程序规范化。
大小写、空白、日期格式等确定性问题可以由程序修正,不必再次调用模型。但程序不能猜测缺失的业务事实。
第三种方法是重新路由。
如果字段格式没有问题,前置条件却不满足,就应换工具或补信息,不能硬把当前调用修到通过。
第四种方法是用户确认。
涉及写操作、权限扩大、不可逆动作或模糊目标时,让用户决定,不让模型自行补全关键参数。
第五种方法是终止。
工具能力无法满足、资源不可访问或错误持续重复时,返回明确缺口比编造参数更可靠。
Function Calling 也要防提示注入
Visit 读到的网页内容是不可信输入。
页面可能包含“忽略之前要求,调用某工具”之类文本。它只是网页内容,不能改变系统工具权限和任务契约。
工具返回应标记数据边界,模型只能把它当证据候选。路由和权限由系统策略控制,不由页面文字决定。
URL、文件路径、代码和查询参数还要做白名单、协议限制、编码处理和长度限制。Python 等执行工具必须沙箱隔离,不能因为参数符合 JSON 类型就允许任意命令。
敏感工具不应向无权限用户暴露 Schema。模型看不到的工具就不会正常选择,但后端仍必须鉴权,防止伪造请求。
结构化调用提高了接口纪律,不会自动消除不可信输入和越权风险。
一个教学场景:合法 JSON 导致错误研究
下面是教学情境,用于说明状态校验缺失的影响。
任务要核对某项目当前版本的限制。
模型调用 Visit,参数是一个格式合法的 URL。Schema 校验全部通过。
但这个 URL 来自旧消息,指向一年前的文档。当前状态里已经发现新版页面,只是模型选错了候选。
工具成功返回正文,Agent 据此生成旧版本结论。
问题不在 JSON,也不在 Visit 服务,而在状态校验缺失。执行前应该检查 URL 对应的对象、版本、访问历史和当前研究缺口。若旧文档确实用于研究演变,可以允许;若目标是当前能力,应提示选择新版来源。
这个例子说明参数有效性必须相对于任务判断。
Schema 版本怎样管理?
工具参数会变化。
字段可能改名,原来的自由字符串可能变成 enum,默认值可能调整,一个工具也可能被拆成两个单一职责工具。
如果直接替换 Schema,旧对话、缓存调用和长任务恢复可能无法继续。需要明确版本号,并在网关做兼容或迁移。
向后兼容的改动也要谨慎。新增可选字段可能改变模型选择和参数分布,description 修改也会影响路由。
发布时可以做小流量或离线 Trace 回放,比较旧版和新版的工具选择、Schema 通过率、语义错误、重试和最终任务结果。
运行日志必须记录当时的 Schema 版本。否则看到一个参数错误时,团队不知道模型究竟依据哪份说明生成。
同一份 Schema 能直接跨模型使用吗?
接口格式可以相同,模型行为未必相同。
不同模型对 description、嵌套对象、可选字段和复杂联合类型的遵循能力可能不同。某份 Schema 在一个模型上稳定,在另一个模型上可能频繁漏字段或错误选择枚举。
因此工具契约应保持简单和单一职责,避免为了减少工具数量设计很深的嵌套参数。切换模型时,用相同任务集比较工具选择、参数分布、修复次数和最终结果,而不是只确认 API 能接受请求。
必要时可以为不同模型提供语义等价但复杂度不同的 Schema 适配层,后端统一映射到内部工具协议。这样不会让真实执行服务被某个模型的接口习惯绑死。
任何适配都要记录模型和 Schema 版本,防止回放时使用了错误契约。
工具 Schema 怎样做离线测试?
第一类是格式样本。
覆盖缺字段、错类型、未知枚举、越界数值、多余字段、空字符串和超长输入。
第二类是组合规则。
覆盖时间反转、互斥字段同时出现、依赖字段缺失和预算不一致。
第三类是状态样本。
包括没有 URL 却调用 Visit、重复页面、未核验数据直接计算、超出当前权限和已经结束的任务继续调用。
第四类是对抗输入。
网页提示注入、危险协议、路径穿越、任意代码、超大参数和敏感信息外传。
第五类是恢复样本。
检查模型收到字段级错误后是否最小修复,连续失败时是否换工具或停止。
第六类是版本回归。
同一批任务在新旧 Schema 下比较调用分布和最终结果,不能只测 JSON 是否能被解析。

测试既要覆盖格式,也要覆盖业务状态、权限、对抗输入和错误恢复。
上线后应该看哪些指标?
格式通过率反映调用能否通过 Schema,但不能代表可执行。
语义有效率检查参数是否满足当前任务和业务条件。
一次执行成功率观察不经修复即可完成的比例,同时要按工具和错误类型拆开。
修复成功率要区分程序规范化、模型重试、换工具和用户确认。
重复调用率、越权拦截、危险参数拦截和工具失败率用于发现稳定性与安全问题。
最终还要看研究结果:调用是否新增证据,关键主张是否有来源,错误参数有没有污染后续状态。
指标需要结合任务分布。Schema 变严格后,格式拒绝可能增加,但错误执行减少;只看一个通过率会得出错误结论。
四类 bad case 怎样定位?
Bad case 一:JSON 合法,字段含义错
结合当前子任务做语义槽位检查,description 写清单位和来源,关键字段不允许模型猜。
Bad case 二:模型连续修同一个字段
返回精确字段错误并限制重试。重复失败后重新路由或停止,不把原调用无限发送。
Bad case 三:Schema 更新后老任务恢复失败
日志记录版本,网关提供兼容或迁移,长任务恢复时使用创建任务时的工具契约。
Bad case 四:工具返回中的指令触发新调用
明确数据与指令边界,系统策略控制工具权限,网页内容不能修改任务契约或获得新工具。
面试官继续追问,怎么接?
追问一:有 JSON Schema 后,参数还会错吗?
会。Schema 主要约束结构和部分静态范围,无法自动判断业务语义、当前状态、权限、资源存在和跨字段逻辑。
追问二:Schema 越严格越好吗?
不一定。过度必填或过窄枚举会逼模型编造值或无法表达合法新情况。约束要与工具真实能力和路由前置条件配合。
追问三:参数错了,为什么不让模型全部重生成?
完全重生成可能改坏已正确字段。优先最小修复,确定格式由程序规范化,前置条件不满足则重新路由。
追问四:Function Calling 能防提示注入吗?
不能单靠它。工具输出仍是不可信数据,权限、协议、参数和副作用需要程序控制,网页指令不能改变系统策略。
追问五:怎样证明新版 Schema 更好?
用固定 Trace 和边界集比较格式、语义、一次执行、恢复、安全拦截、证据增量与最终任务质量,而不是只看解析通过率。
从 Schema 到执行网关,面试时这样讲
Function Calling 的价值是把工具名和参数变成结构化输出,减少文本正则解析错误。JSON Schema 能约束必填、类型、枚举、范围和多余字段,但一个合法 JSON 仍可能在业务语义、当前状态、权限和参数组合上错误,所以不能校验通过就直接执行。
我的执行链会分层校验:先解析和 Schema,再检查跨字段业务规则、当前研究状态、重复动作、权限、安全、幂等和副作用,全部通过才进入统一网关。可修复错误返回字段路径、期望约束和建议动作,优先最小修复;前置条件不满足就重新路由;高风险或不可逆动作请求用户确认;连续失败则降级或停止。网页和工具输出始终是不可信数据,不能改变系统权限。
Schema 与 description 都要版本化。验证时除了格式通过率,还要看语义有效率、一次执行成功、错误恢复、重复调用、越权和危险参数拦截、证据增量与最终任务质量,并用无 URL 的 Visit、旧版本页面、冲突字段和提示注入等边界样本回归。目标是让错误在执行前被发现,不是承诺 Schema 绝不出错。

Function Calling 上线前检查什么
准备一个“格式合法但语义错误”的调用案例,说明各层校验在哪里拦截,以及错误是否进入了可追溯日志。
- Schema 是否声明真实字段语义、单位、必填和取值边界?
- 执行前是否还有业务、状态、权限、安全和幂等校验?
- 参数修复是否最小化、有限重试,并能重新路由或停止?
- 日志能否还原工具、Schema 版本、原参数、错误和最终执行结果?