From 44a928b631a1bc6221c3c997837d8d00c7ea0a4d Mon Sep 17 00:00:00 2001 From: Cesar Garcia <128240629+Chesars@users.noreply.github.com> Date: Wed, 5 Nov 2025 00:05:17 -0300 Subject: [PATCH] fix(openai): Remove automatic summary from reasoning_effort transformation (#16210) * Fix: Remove automatic summary field from reasoning_effort transformation Problem: The _map_reasoning_effort() function was automatically adding reasoning.summary field when users specified reasoning_effort parameter, causing 400 errors for users with unverified OpenAI organizations. Root Cause: According to OpenAI's official documentation, the summary field is opt-in and requires organization verification: "Reasoning summary output [...] will not be included unless you explicitly opt in to including reasoning summaries." "Before using summarizers with our latest reasoning models, you may need to complete organization verification" Source: https://platform.openai.com/docs/guides/reasoning#reasoning-summaries Solution: Remove the automatic inclusion of summary field from all reasoning_effort levels (high, medium, low, minimal). Users who want reasoning summaries can explicitly pass reasoning={"effort": "high", "summary": "auto"} in their requests. Impact: - Fixes #16032 - Works for all organizations (verified and unverified) - Maintains backward compatibility for users passing reasoning object directly - Follows OpenAI's recommended opt-in approach Testing: - All existing tests pass (4/4 tests in transformation suite) - Manual verification confirms only effort field is included * test: Fix MockResponse missing headers attribute in test_openai_responses_api The MockResponse class was missing the 'headers' attribute which caused APIConnectionError when processing the mock response. Added headers={} to fix the test. * feat: Add dict support to reasoning_effort parameter Allow users to pass reasoning_effort as either: - String: reasoning_effort="high" (no summary, safe default) - Dict: reasoning_effort={"effort": "high", "summary": "detailed"} (opt-in) This preserves backward compatibility while giving users flexibility to explicitly opt-in to the summary field when needed (for verified OpenAI organizations). --------- Co-authored-by: Krish Dholakia --- .../transformation.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/litellm/completion_extras/litellm_responses_transformation/transformation.py b/litellm/completion_extras/litellm_responses_transformation/transformation.py index b060f22d355..cb358498968 100644 --- a/litellm/completion_extras/litellm_responses_transformation/transformation.py +++ b/litellm/completion_extras/litellm_responses_transformation/transformation.py @@ -538,16 +538,20 @@ class LiteLLMResponsesTransformationHandler(CompletionTransformationBridge): return cast(List["ALL_RESPONSES_API_TOOL_PARAMS"], responses_tools) - def _map_reasoning_effort(self, reasoning_effort: str) -> Optional[Reasoning]: + def _map_reasoning_effort(self, reasoning_effort: Union[str, Dict[str, Any]]) -> Optional[Reasoning]: + # If dict is passed, convert it directly to Reasoning object + if isinstance(reasoning_effort, dict): + return Reasoning(**reasoning_effort) + + # If string is passed, map without summary (default) if reasoning_effort == "high": - return Reasoning(effort="high", summary="detailed") + return Reasoning(effort="high") elif reasoning_effort == "medium": - # docs say "summary": "concise" is also an option, but it was rejected in practice, so defaulting "auto" - return Reasoning(effort="medium", summary="auto") + return Reasoning(effort="medium") elif reasoning_effort == "low": - return Reasoning(effort="low", summary="auto") + return Reasoning(effort="low") elif reasoning_effort == "minimal": - return Reasoning(effort="minimal", summary="auto") + return Reasoning(effort="minimal") return None def _map_responses_status_to_finish_reason(self, status: Optional[str]) -> str: