Function Calling 参数校验与重试机制
Agent 调用工具时的参数校验、错误修复与重试策略,覆盖 Schema 校验、运行时验证、repair 流程和高风险操作兜底。
#ai
#synthesis
#growing
[!info] related notes
- 前置概念: Function Calling, 面向 Agent 的工具设计
- 参数校验: Tool Argument Validation
- 执行重试: Retry Policy
- 关系笔记: AI 的能力以及对应的协议
Function Calling 参数校验与重试机制
一句话定义
Function Calling 参数校验与重试机制,是在 Agent 调用工具时,通过 Schema 定义、运行时校验、错误反馈重试和高风险操作兜底,减少错误参数进入执行层的一套工程方案;结构校验、意图确认、权限与业务验证需要分别完成。
核心机制 / 工作原理
两层校验
1. 模型侧:Function Schema / JSON Schema
工具定义时就声明参数的 JSON Schema,约束类型、必填项、枚举值、格式。
{
"name": "refund_order",
"description": "对指定订单执行退款操作",
"parameters": {
"type": "object",
"properties": {
"orderId": { "type": "string", "minLength": 1, "description": "订单 ID" },
"amount": { "type": "number", "exclusiveMinimum": 0 },
"reason": { "type": "string", "enum": ["user_request", "quality_issue", "other"] }
},
"required": ["orderId", "amount", "reason"],
"additionalProperties": false
}
}
2. 运行时侧:Zod / Ajv 校验
模型返回的参数不能直接信任,必须在执行前做运行时校验。
import { z } from 'zod';
const RefundParams = z.object({
orderId: z.string().min(1),
amount: z.number().positive(),
reason: z.enum(['user_request', 'quality_issue', 'other']),
}).strict();
type RefundInput = z.infer<typeof RefundParams>; // 类型从 schema 推导
金额示例仅演示正数约束;真实退款还应规定币种、最小货币单位或精确小数表示、可退款余额与并发扣减规则。
校验失败后按任务策略选择有限 repair 或返回失败。schema 校验只修复结构;缺少用户意图不能靠补默认答案解决。
Repair-and-Retry 流程
- 模型返回参数
- Zod/Ajv 校验
- 校验通过 → 验证资源、权限、业务状态与当前授权,再决定是否执行
- 校验失败 → 提供筛选后的字段路径和约束,要求修复候选,不回显秘密或无关原始数据
- 每个新候选重新解析和校验;例如最多修复 3 次,同时受总时间预算限制
- 连续失败 → 抛错,进入人工处理或降级
关键点:每次重试前要把具体校验错误反馈给模型,而不是简单重复请求。
高风险操作的额外兜底
退款、删除、支付等操作,光做参数校验不够,还需要:
- 幂等设计:同一次逻辑操作重试使用稳定标识;同样参数也可能是两次不同的合法操作
- 业务校验:订单是否存在、是否属于当前用户、是否已退款、金额是否超限
- 授权:检查任务已有授权;确需新增批准时提交具体提案,dry-run 预览本身不是授权
- 审计日志:记录操作标识、审批引用、筛选后的输入/输出摘要和执行结果
最小例子 / 最小场景
用户说”帮我退款订单 A001,50 元”。模型返回 { orderId: "A001", amount: 50 },但漏了 reason 字段。Zod 报告缺少合法的 reason(具体错误文案随版本变化)。若用户请求足以确认是主动退款,可提出 reason: "user_request" 的修复候选;再次校验并检查订单归属、退款余额与授权后才能执行。没有理由依据时应澄清,不能只为通过 enum 校验编造业务原因。
边界与常见误解
- JSON Schema 只约束格式,不约束业务语义;业务校验必须在代码里做
as type断言不是校验,是绕过类型系统;运行时校验才是真正的保障- 参数 repair 发生在执行之前;执行后超时可能结果未知,不能重新生成参数或操作 ID 盲目再执行
- 三次只是示例预算,没有通用的固定次数
- 幂等约束重复操作的预期效果,不保证每次读取结果逐字相同;去重与响应重放见 Tool Idempotency