Skip to content

fix(responses): normalize chat tool_choice for completions→responses bridge - #27634

Merged
mateo-berri merged 2 commits into
litellm_internal_stagingfrom
litellm_responses_tool_choice_chat_bridge
May 11, 2026
Merged

fix(responses): normalize chat tool_choice for completions→responses bridge#27634
mateo-berri merged 2 commits into
litellm_internal_stagingfrom
litellm_responses_tool_choice_chat_bridge

Conversation

@Sameerlite

@Sameerlite Sameerlite commented May 11, 2026

Copy link
Copy Markdown
Contributor

When routing chat completions to the Responses API, OpenAI rejects chat-style tool_choice ({type, function: {name}}) with unknown_parameter: tool_choice.function.

  • Add LiteLLMResponsesTransformationHandler._normalize_tool_choice_for_responses_api and apply it in _map_optional_params_to_responses_api_request for tool_choice.
  • Regression test: test_map_optional_params_tool_choice_chat_nested_to_responses_api.
image

Curl in litellm
image

Fixes #27611
Fixes LIT-2975


Note

Low Risk
Low risk: small request-shaping change limited to tool_choice mapping with targeted regression tests; main risk is unintended normalization of uncommon tool_choice dict shapes.

Overview
Fixes a Responses API compatibility issue when routing Chat Completions requests by normalizing tool_choice from chat-style {type:"function", function:{name}} to the Responses API shape {type:"function", name} and stripping the stray function key before sending upstream.

Adds regression coverage to ensure nested chat tool_choice is 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.

…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-apps

greptile-apps Bot commented May 11, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a unknown_parameter: tool_choice.function rejection from OpenAI's Responses API by normalizing chat-style tool_choice dicts ({type, function: {name}}) to the Responses API shape ({type, name}) in the completions→responses bridge.

  • Introduces _normalize_tool_choice_for_responses_api which handles all four cases: string pass-throughs ("auto", "none"), already-normalized dicts, chat-style nested dicts, and mixed dicts with both top-level name and a stray function sub-key — the returned value always omits the function key.
  • Wires the normalizer into _map_optional_params_to_responses_api_request and backs it with a new integration test plus a parametrized unit test covering all edge cases.

Confidence Score: 5/5

Safe 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.

Important Files Changed

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

Comment thread litellm/completion_extras/litellm_responses_transformation/transformation.py Outdated
@codecov

codecov Bot commented May 11, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.30769% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...litellm_responses_transformation/transformation.py 92.30% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@Sameerlite

Copy link
Copy Markdown
Contributor Author

@greptile re review

@Sameerlite

Copy link
Copy Markdown
Contributor Author

bugbot run

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ 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.

@mateo-berri mateo-berri left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM; thanks!

@mateo-berri
mateo-berri merged commit 5e016f9 into litellm_internal_staging May 11, 2026
117 checks passed
@mateo-berri
mateo-berri deleted the litellm_responses_tool_choice_chat_bridge branch May 11, 2026 17:24
fzowl pushed a commit to fzowl/litellm that referenced this pull request Jun 24, 2026
…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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Chat Completions → Responses API bridge does not transform tool_choice named function format, causing 400 on all GPT-5.4/5.5 models

3 participants