fix(responses): normalize chat tool_choice for completions→responses bridge - #27634
Conversation
…rom completions
OpenAI /v1/responses rejects tool_choice.function. Normalize forced-function
choice from chat shape to {type, name} in LiteLLMResponsesTransformationHandler.
Co-authored-by: Cursor <cursoragent@cursor.com>
Greptile SummaryThis PR fixes a
Confidence Score: 5/5Safe to merge — the change is narrowly scoped to the tool_choice normalization step in the completions→responses bridge and does not touch any auth, routing, or request-path logic. The normalization logic is straightforward, the returned dict is always reconstructed from scratch (no stray keys leak through), and the parametrized test now covers every branch including strings, already-normalized dicts, mixed-key inputs, and non-function types. No regressions are introduced to existing paths. No files require special attention.
|
| Filename | Overview |
|---|---|
| litellm/completion_extras/litellm_responses_transformation/transformation.py | Adds _normalize_tool_choice_for_responses_api to strip the chat-style function sub-key and promote function.name to top-level; applies it in _map_optional_params_to_responses_api_request. Logic is correct: string pass-throughs, already-normalized dicts, and mixed-format dicts are all handled, and the returned value always omits stray function keys. |
| tests/test_litellm/completion_extras/litellm_responses_transformation/test_completion_extras_litellm_responses_transformation_transformation.py | Adds two new tests: an integration test for the full _map_optional_params_to_responses_api_request path and a parametrized unit test for _normalize_tool_choice_for_responses_api covering strings, already-normalized dicts, mixed-key dicts, and non-function types. No real network calls are made. |
Reviews (2): Last reviewed commit: "fix(responses): strip tool_choice.functi..." | Re-trigger Greptile
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
|
@greptile re review |
|
bugbot run |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 8dd31f2. Configure here.
…bridge (BerriAI#27634) * fix(responses): map chat tool_choice to Responses API when bridging from completions OpenAI /v1/responses rejects tool_choice.function. Normalize forced-function choice from chat shape to {type, name} in LiteLLMResponsesTransformationHandler. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(responses): strip tool_choice.function when top-level name is set --------- Co-authored-by: Cursor <cursoragent@cursor.com>
When routing chat completions to the Responses API, OpenAI rejects chat-style
tool_choice({type, function: {name}}) withunknown_parameter: tool_choice.function.LiteLLMResponsesTransformationHandler._normalize_tool_choice_for_responses_apiand apply it in_map_optional_params_to_responses_api_requestfortool_choice.test_map_optional_params_tool_choice_chat_nested_to_responses_api.Curl in litellm

Fixes #27611
Fixes LIT-2975
Note
Low Risk
Low risk: small request-shaping change limited to
tool_choicemapping with targeted regression tests; main risk is unintended normalization of uncommontool_choicedict shapes.Overview
Fixes a Responses API compatibility issue when routing Chat Completions requests by normalizing
tool_choicefrom chat-style{type:"function", function:{name}}to the Responses API shape{type:"function", name}and stripping the strayfunctionkey before sending upstream.Adds regression coverage to ensure nested chat
tool_choiceis converted correctly and that non-function/standard values (e.g.,auto,none,required) pass through unchanged.Reviewed by Cursor Bugbot for commit 8dd31f2. Bugbot is set up for automated code reviews on this repo. Configure here.