fix(model/openaimodel): pin function tools to non-strict validation - #1389
fix(model/openaimodel): pin function tools to non-strict validation#1389hanorik wants to merge 1 commit into
Conversation
|
The change is right, and there is a measurement that makes a stronger case for it than the description does. I ran the three-way comparison against the live Responses API. With So the pre-change behavior was not only that the mode was chosen by the server and invisible. For any tool with an optional argument the API forced a value into that argument: the empty string in One thing I would fix before merge. TestConvertFunctionDeclarationKeepsOptionalParameters is the test that pins "do not rewrite Smaller: the exception list at doc.go:28-29 reads as closed — "unless the argument struct uses omitempty or omitzero" — and there is a third case. A map-typed field emits The rest of the doc claim holds, for what it is worth: I ran each declaration shape through |
907ce14 to
8daa97f
Compare
|
The test fix holds up. I injected One correction on the new comment text, though. tools.go:81-82 says Same prompt as before, "What is the weather in Paris? Do not specify units.", tool call forced, Your conclusion is unaffected and I think it gets stronger: you still cannot express an optional argument through |
Problem:
convertFunctionDeclarationnever setFunctionToolParam.Strict. openai-gotags that field
json:"strict,omitzero", so leaving it unset drops the key fromthe request body entirely, and the Responses API reads an absent
strictas"attempt strict mode; if the schema cannot be made compatible, fall back to
non-strict, best-effort function calling". The validation mode a tool runs under
was therefore inferred by the server from the shape of whatever parameter schema
the caller happened to produce, rather than chosen by this package.
That makes the mode inconsistent and invisible. Tools built with
functiontool.NewgetadditionalProperties:falseand a fullrequiredlistfrom jsonschema-go, so they ran strict; tools declared with a hand-written
genai.Schemaemit noadditionalPropertiesand never did. Addingomitemptyto a single Go struct field silently flipped that tool from validated to best
effort. The API reports the mode it settled on on the response tool, which this
package discards, so there was no way to tell which you got.
Solution:
Pin
Stricttofalse, making the mode this package's decision rather than anemergent property of the caller's struct tags. This matches adk-python's
Responses path. Pinning it on is the breaking direction: strict requires every
property to appear in
required, so an optional argument would have to bedeclared nullable (
"type": ["string", "null"]) and listed there anyway,changing what existing agents send. The trade is that tools whose schema already
qualified lose strict validation and drop to best effort; the package doc and
the conversion site record this and tell callers to validate arguments in the
tool.
Testing Plan
Unit Tests: added
TestConvertFunctionDeclarationPinsStrictOff(all threeparameter paths),
TestConvertFunctionDeclarationMarshalsStrict(guards theomitzerowire format),TestConvertFunctionDeclarationKeepsOptionalParameters(pins that
enforceStrictOpenAISchemais not applied to tool parameters),TestBuildOpenAIParams_ToolsPinStrictOff(asserts on the marshalled requestbody), plus a strict assertion in
TestConvertTools.