Send strict: false for function tools on the Responses API to preserve Chat Completions behavior#844
Open
bdegomme wants to merge 1 commit into
Open
Conversation
The Responses API defaults function tool strict to true, unlike Chat Completions where it defaults to false. Since RubyLLM never sent the field, switching OpenAI to the Responses API silently enabled strict mode for every tool: the model becomes grammar-constrained to emit all schema properties on each call, so parameters left out of 'required' stop being optional. Send strict: false explicitly to preserve the 1.x Chat Completions behavior. Tools can opt back into strict validation with 'provider_options strict: true'. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
81712be to
966014e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #843
This is AI generated but I understand every line. I'm also fine with accepting the new default strict true, but then it should be mentioned in the upcoming 2.0 upgrading guide.
What this PR does
Explicitly sends
strict: falsein function tool definitions rendered byProtocols::Responses::Tools.tool_for, restoring the tool-calling behavior applications had on Chat Completions. Tools can opt into strict validation per class withprovider_options strict: true.The problem
OpenAI's two APIs have opposite server-side defaults for function tool
strict:FunctionObject.strict: defaultfalse(OpenAPI spec)FunctionTool.strict: defaulttrue("Whether to enforce strict parameter validation. Defaulttrue.")RubyLLM never sends the
strictfield, so when OpenAI switched to defaulting to the Responses API, every existing tool silently flipped into strict mode. Under strict mode the model's output is grammar-constrained to emit every property in the schema — parameters left out ofrequiredstop being optional (strict mode expresses optionality as nullable types + membership inrequiredinstead).Concretely: a search tool with a dozen optional filters that previously received only the relevant ones now gets a value for every filter on every call, changing tool behavior without any application code change. The upgrade guide covers the Responses API switch but doesn't mention this side effect, and there's no way to notice it except by observing degraded tool calls.
The fix
tool_fornow always includesstrict: falsein the flat function definition.provider_optionsis merged after, soprovider_options strict: trueon a tool class opts back in for schemas that meet the strict-mode requirements.Docs updated:
docs/_reference/upgrading.md— note under "OpenAI now defaults to the Responses API" explaining tools stay non-strict and how to opt in.docs/_core_features/tool-parameters.md— new "Strict Mode on the OpenAI Responses API" subsection with an opt-in example (nullable optional params, all properties inrequired).Tests
spec/ruby_llm/protocols/responses/chat_spec.rband added an opt-in test forprovider_options strict: true.CI=true bundle exec rspec spec/ruby_llm/chat_tools_spec.rb -e openai— 18 examples, 0 failures.