所属: 模型增强层。本页边界: 怎样将语言模型输出约束为可解析、可验证的函数调用,以及执行授权与语法约束为何是不同层次的问题。
#核心公式
工具输出可解析只是第一个条件;语义、用户权限和当前环境状态也必须同时满足,才允许执行。2026 年的关键变化在于:语法约束的成功可能掩盖工具调用能力的退化,而执行授权必须由计算之外的独立层判定。
#符号说明
| 符号 | 含义 |
|---|---|
| 语言模型生成的结构化文本 | |
| JSON Schema、grammar 或其他语法规范 | |
| 解析后的候选动作,通常包含工具名和参数 | |
| 当前用户任务与上下文 | |
| 已认证的用户或调用主体 | |
| 执行前的环境状态 | |
| 动作是否满足语法与类型约束 | |
| 参数是否与用户任务语义一致 | |
| 用户是否有权执行动作 | |
| 当前状态是否满足执行前置条件 | |
| 系统允许暴露给模型的动作集合 | |
| 编译后的契约状态机 | |
| 第 步仍能完成为合法输出的 token 集合 | |
| 约束优先反转假设 | |
| Skill 的规范定义 |
四个谓词由程序、身份系统或明确授权共同判定,不能只依靠模型自评。
#技术要点
- 约束税(Constraint Tax) :当工具调用与 JSON Schema 约束同时启用时,语法约束的 token 掩码可能使工具调用 token 在解码中不可达,导致开源模型停止调用工具。这是工具调用与结构化输出联合部署时的未文档化失效模式。
- CASD(契约感知投机解码) :将 API 契约编译为轻量动态状态机,对确定性结构 token 走“结构注入快速路径”,对概率性语义参数在草稿模型上施加 Schema 引导的 logit 掩码,在 BFCL v3 上实现最高 2.53 倍解码加速。
- 计算不等于授权(Computation Is Not Authority) :模型成功推理、沙箱隔离、连接器白名单或会话权限,都不自动构成对特定现实后果的授权。需引入硬件根植的执行终局性(Execution-Finality)架构。
- ToolClad:声明式工具契约格式,将参数验证推至结构性运行时围栏,使元字符注入、命令替换、路径穿越和同形字攻击在结构上不可表达,而非事后检测。
- Spring AI CVE-2026-59318:按请求通告的工具列表作为边界,但在工具调用分发时未被完全执行,可能导致权限提升。
- Tool Suppression 的缓解方案:Transparent Two-Pass Execution,将工具执行与 Schema 约束响应生成解耦,恢复工具调用同时保留结构化输出保证。
- Skill 是比 Function Calling 更高层级的能力抽象:Function Calling 定义“接口”,Skill 封装“知识”。Skill 通过渐进式上下文加载按需提供领域能力。
- 工具调用的评估需要区分选择与执行两个层面。CompToolBench 的 Selection Gap 发现:正确选择工具的模型经常无法产生有效调用,平均差距 13.2 个百分点。
#原理与演进
#模型输出不等于程序调用
执行链为:文本 token → 语法约束 → 结构化参数 → 校验/授权 → 工具执行。
- Schema 约束字段、类型、必填项;语法约束解码可在每一步只允许仍能组成合法 JSON 的 token。
- 语法正确仅说明“可解析”;参数是否存在、是否在权限范围、操作是否符合用户意图需要额外校验。
- 工具返回值是外部观察,不应提升为系统指令。否则网页、文档或日志中的恶意文本会借工具结果控制模型。
#约束解码的效率与安全权衡
标准自回归生成结构化输出面临延迟瓶颈。现有加速方法面临两难:标准投机解码因草稿模型的结构幻觉而严重精度下降,而基于语法的约束解码保持正确性但牺牲了加速,原因是昂贵的 CPU 端词汇表评估。
CASD 将 API 契约编译为轻量动态状态机。当结构 token 是确定性的(如 JSON 的括号、引号、字段名),CASD 激活 Structure-as-Injection Fast Path,直接发出语法样板并绕过冗余的神经前向传播。对于概率性语义参数(如字段值),CASD 在草拟阶段施加 Schema-Guided Logit Masking,在目标模型验证前将草稿模型限制在结构合法的词汇表中。这一设计同时解决了标准投机解码的结构幻觉和语法约束解码的 CPU 瓶颈。
#约束税:工具调用与结构化输出的联合失效
当 Tool Calling 和 JSON Schema 约束同时启用时,多个开源模型停止调用工具,尽管保持了高 Schema 合规性。这一现象称为 Tool Suppression,根源是 JSON Schema 约束被编译为基于语法的 token 掩码,导致工具调用 token 在解码过程中不可达。
约束优先反转(CPI)假设认为,在多个同时约束下,Schema 满足可能主导动作选择行为。这一假设是行为层面的,与观察到的解码级机制一致。
缓解方案 Transparent Two-Pass Execution 将工具执行与 Schema 约束响应生成解耦:第一遍决定是否调用工具及调用哪个工具,第二遍在工具执行后生成 Schema 约束的结构化响应。这一策略无需模型重训练即可恢复工具调用,同时保留结构化输出保证。
这一发现的工程含义是:单独评估工具使用和结构化输出可能遗漏生产 Agent 系统中的重要可靠性问题。
#从“执行什么”到“允许什么被执行”
IETF 草案明确区分了工具选择与工具效果:连接器白名单不是每次操作的终局授权。提案的架构中,一个拟议的后果承载操作被表示为 Candidate Act,并保持在 Non-Effective State,直到 Protected Enforcement Domain 验证操作特定的谓词,并由独立的 Finality Sink 在操作变为外部有效之前立即验证作用域化的、非承载的终局授权。如果授权缺失、过期、重放、撤销或与尝试的操作不匹配,Candidate Act 保持非有效状态,操作失败关闭。
这一架构的核心不变式是:计算不是授权;工具选择不是工具效果;连接器白名单不是每次操作的终局性。
ToolClad 将参数验证推至结构性运行时围栏。大多数生产中的 Agent 失败不是“工具不允许”,而是“工具允许但参数错误”:read_file(path="../../etc/shadow") 是一个被允许的操作,但带有攻击者塑造的参数。ToolClad 通过声明式契约使元字符注入、命令替换、路径穿越和同域同形字攻击在结构上不可表达。在九种托管 LLM 上的 A/B 评估中,333/335 次处理组分发被拒绝,对恶意输入的拦截率为 100%。
#Skill 的定位:从接口定义到知识封装
Function Calling 与 Skill 的本质差异:前者定义的是“接口”,后者传递的是“知识”。
Function Calling 的流程是:用户请求 → LLM 推理 → 生成函数调用 JSON → 开发者代码执行 → 返回结果。LLM 只负责“决定调用什么,生成参数”。
Skill 的流程是:用户请求 → LLM 读取 Skill 说明 → LLM 决定调用哪些底层 Tool → 执行 → 返回结果。Skill 本身不是可执行代码,它是写给 LLM 看的自然语言指导,包含领域知识、操作流程、最佳实践和约束规则。
Skill 的核心工程机制是渐进式上下文加载:
- Level 1 (Metadata):仅加载 Skill 的元数据(名称、描述),用于语义搜索和路由决策。
- Level 2 (Retrieval):当任务匹配到某个 Skill 时,加载
SKILL.md全文。 - Level 3 (Resources):模型根据
SKILL.md中的引用,按需读取额外的参考文档或执行脚本。
这一设计的工程意义是:上下文窗口只被真正需要的信息占用。一个有 50 个 Skill 的系统,在初始状态下只消耗 50 行元数据的上下文。
Skill 和 MCP 不是竞争关系,而是不同层级:MCP 解决“能不能连”,Skill 解决“会不会做”。
#1. 语法、语义、授权必须三次判定
设模型生成式(1)所示的候选动作, 为工具名, 为参数。安全执行要求 (语法合法)、式(2)(参数与任务语义一致)、式(3)(用户有权执行)。Schema 通常只能可靠约束第一项。
式(1):
式(2):
式(3):
例:transfer(amount=1000, account=...) 可以是合法 JSON,但金额、账户和用户授权都可能不对。对于不可逆动作,解析成功绝不是执行许可。
#2. 约束解码的工程进展
#2.1 CASD:契约感知的投机解码
标准自回归生成结构化输出面临延迟瓶颈。CASD 将 API 契约编译为动态状态机,利用结构化输出的确定性特征绕过冗余计算。
契约状态机 编码了工具调用的合法 token 序列。在解码第 步,状态机计算允许的 token 集合 。对于确定性结构 token(如 JSON 语法标记),CASD 直接注入而不经过模型前向传播;对于语义参数 token,施加 Schema 引导的 logit 掩码后将草稿模型限制在合法词汇表中。
在 BFCL v3 基准上跨多个模型家族的评估显示,CASD 相比贪心解码实现最高 2.53 倍加速,同时保持高 AST 精确匹配准确率。
#2.2 约束税的机制
JSON Schema 约束被编译为基于语法的 token 掩码后,在解码的每一步,只有仍能组成合法 JSON 的 token 才被允许。如果工具调用的 token(如工具名)不在当前允许集合中,模型就无法发出工具调用。
CPI 假设认为,当 Schema 满足和工具调用两个目标同时存在时,解码器倾向于优先满足 Schema 约束。这一行为在单独评估工具使用和结构化输出时不会显现,只在联合部署时出现。
| 部署模式 | 工具调用率 | Schema 合规率 |
|---|---|---|
| 仅工具调用 | 正常 | — |
| 仅 Schema 约束 | — | 正常 |
| 联合部署 | 显著下降 | 保持高位 |
#2.3 约束解码框架的标准化评估
JSONSchemaBench 提供了 10,000 个真实 JSON Schema,覆盖广泛约束类型,配合官方 JSON Schema 测试套件,评估六个主流约束解码框架(Guidance、Outlines、Llamacpp、XGrammar、OpenAI、Gemini)在效率、覆盖率和质量三个维度上的表现。
主流约束解码库包括:Outlines(FSM-based,97% 成功率,0.4% 幻觉率)、XGrammar、llguidance、LMQL、AICI 等。
#3. 工具调用的执行授权
#3.1 计算与授权的分离
IETF 草案的核心论点是:模型可能被授权进行计算,但仍未被授权行动。成功的推理、沙箱隔离、连接器白名单或会话权限,都不自动构成对特定现实后果的授权。
架构要求将后果承载操作表示为 Candidate Act,保持在 Non-Effective State,直到:
- Protected Enforcement Domain 验证操作特定的谓词
- 独立的 Finality Sink 验证作用域化的终局授权
如果授权缺失、过期、重放、撤销或与尝试的操作不匹配,操作失败关闭。
#3.2 ToolClad:危险参数的不可表达化
ToolClad 将参数验证推至结构性运行时围栏。其 .clad.toml 清单定义类型化参数、验证规则、命令模板(数组式执行,无 shell 字符串插值)和执行后端。
验证器在任何工具分发之前运行,拒绝无法由契约表达的参数。这使得元字符注入、命令替换、路径穿越和同域同形字攻击在结构上不可表达,而非事后检测。
在九种托管 LLM 上的 A/B 评估中,333/335 次处理组分发被拒绝。攻击子形态包括:元字符(;|&)、命令替换($())、反引号、通配符、换行注入、路径穿越(../)、西里尔同形字 IDN 和 punycode IDN。
分层防御的独立贡献:在工具参数注入攻击类别上,Cedar 策略拒绝 = 0(因为 whois_lookup 被任务 Agent 的策略允许),内容消毒器剥离 = 0(因为攻击在参数中而非存储内容中),ToolClad 拒绝 = 333。
#3.3 工具列表通告与执行的差距
Spring AI 的 CVE-2026-59318 揭示了一个架构级问题:按请求通告的工具列表被作为边界呈现给模型,但在工具调用分发时未被完全执行。在某些条件下,未被通告的工具可能被调用,导致权限提升。
Verifier Tax 现象进一步量化了安全执行的成本:在多步工具使用 Agent 中,运行时执行验证器中介(评估拟议动作是否违反预定义策略)会影响端到端任务性能,影响程度取决于任务的时间跨度。
#4. 工具调用的状态机
模型提出调用 → 程序校验 Schema → 检查权限和前置条件 → 执行/超时 → 记录结果 → 将结果作为低信任观察交回模型 → 验证最终回答。
| 边界 | 失效方式 | 保护原则 |
|---|---|---|
| 模型→工具 | 参数幻觉、越权 | 白名单、类型与业务规则校验、ToolClad |
| 工具→模型 | 返回包含伪系统命令 | 返回值只作为数据呈现 |
| 工具→环境 | 重复执行导致副作用 | 幂等键或显式去重 |
| 多次调用 | 状态过期、竞态 | 版本戳与前置条件重查 |
| 通告→执行 | 通告列表与实际执行不一致 | 执行时重新验证 |
工具返回值若是异常、空结果或部分成功,模型应区分这些状态;将异常文本包装成“成功”会掩盖真实失败。
#5. 工具与 RAG、Agent 的关系
RAG 的检索器本身可作为一个只读工具,但 RAG 的核心问题是证据选择与引用;工具调用的核心问题是结构化动作契约;Agent 的核心是多步决策和状态更新。概念路线:自然语言生成 → 结构化动作 → 执行观察闭环 → 有规划和停止条件的 Agent。Skill 位于工具与 Agent 之间,强调职责单一、结构化 I/O 与可组合性。
#6. Skill 的设计与评估
#6.1 Skill 的五种设计模式
- 工具包装器:将底层工具封装为有领域语义的高层接口。
- 生成器:生成模板、代码或结构化数据。
- 审阅者:检查输入或输出是否符合规范。
- 参考知识包:提供领域知识文档,模型按需读取。
- 可组合编排:定义多步骤工作流,调用多个底层 Skill。
#6.2 Skill 的评估指标
- 调度正确率:Skill 是否在正确情境下被激活。推荐阈值 ≥ 0.85。
- 内部轨迹合规率:Skill 定义的步骤是否按序执行。推荐阈值 ≥ 0.90。
- 输出集成质量:Skill 的输出是否正确整合到最终回答中。推荐阈值 ≥ 0.80。
#6.3 Skill 的安全边界
Skill 运行在代码执行沙箱中,但脚本以完整环境访问权限运行。企业部署需要 Skills Registry 进行发布前扫描、签名验证、沙箱隔离和权限最小化。
#7. 工具使用的评估
#7.1 最新基准
| 基准 | 规模 | 覆盖维度 | 关键发现 |
|---|---|---|---|
| CompToolBench | 200 任务,106 真实工具 | 单步、顺序、并行、图组合 | Selection Gap 平均 13.2 个百分点 |
| Live API-Bench | 2500+ API,11 数据库 | 错误处理、顺序推理、参数生成 | 任务完成率 7–47%,交互式提升至 50% |
| MCP-Bench | 真实多步任务 | 工具使用、跨工具协调 | — |
| MultiCAT-Bench | 多类别 Agent 工具使用 | Grok 4.1 Fast 83.8%,GPT-5 Mini 83.7% | — |
#7.2 评估维度
分别测工具选择准确率、参数准确率、权限拒绝率、执行成功率、最终任务成功率和成本。只测 JSON 可解析率,会忽略“合法调用了错误工具”这一核心错误。CompToolBench 的 Selection Gap 揭示了一个关键区分:正确选择工具的模型经常无法产生有效调用,这两个能力需要分开评估。
危险操作应在测试环境或模拟器中评估,且将权限边界作为独立指标。对工具评测,除了参数完全匹配,还需测试:无效值、权限边界、工具异常、重复响应、顺序颠倒、伪指令混入返回值。
#8. Schema 的表达能力与权限分离
Schema 可表达字段类型、枚举、取值范围和嵌套结构,却通常无法单独判断“这个用户是否能访问该文件”“这个金额是否与用户真实意图一致”。前者需要身份与资源权限系统,后者可能需要明确确认。
对读操作可施加最小权限的资源范围;对写操作应定义副作用、前置条件、幂等行为和失败回滚语义。若工具在部分执行后超时,简单重试可能重复副作用,故返回结果需区分“未开始”“已完成”“状态未知”。
#9. 不确定状态下的决策
模型可能猜测某个参数,例如数据库记录 ID。正确动作是先调用只读查询确认,而非对猜测 ID 执行写操作。多步工具使用可抽象为先降低状态不确定度再执行影响环境的动作。
原始资料: