报错是这么冒出来的。工具参数里有一层 address 对象,只在外层写了 additionalProperties:false,打开 strict 后报 address 缺少 required 字段,报错路径直接指到第二层。
中间走过弯路,把「数组 items 里的 object 同样受这条约束」当成主因,改完现象没变。
排查方向其实有限,先把可能性排一排。嵌套的每个 object 节点都要单独写 additionalProperties: false。另一种情况是嵌套层的 required 必须覆盖该层所有 properties。
还有一种情况,用 $ref 复用定义时 strict 不会自动展开,必须内联。
递归检查每个 object 节点的 additionalProperties
python -c "import json;s=json.load(open('schema.json'));print(s['properties']['address'].get('additionalProperties'))"
给嵌套层补上 additionalProperties
python -c "import json;s=json.load(open('schema.json'));s['properties']['address']['additionalProperties']=False;json.dump(s,open('s2.json','w'))"
然后确认 schema 里是否还在用 ref 引用
python -c "import json;s=open('schema.json').read();print('$ref' in s)"
剩下的就是用最小请求验证服务端接受这个工具
curl -s https://api.openai.com/v1/chat/completions -H "Authorization: Bearer $OPENAI_API_KEY" -H "Content-Type: application/json" -d @payload.json | jq '.error.message'
这台环境是别人交接的,不少默认值被动过,只能一项项核。
怎么算真的好了,看的是同一批现象。payload 请求返回 200,工具出现在 choices 的 tool_calls 中,嵌套对象参数结构与 schema 完全对应,不再报 required 缺失。
strict 的校验是逐层递归的,外层合规不代表内层合规,写工具定义时把 schema 当成树来遍历,别只看顶层。监控比日志更早给出信号,事后回看经常能提前半小时发现异常。
