From 79c9a68305b58c4d3d313ad5c770ef8544f38d99 Mon Sep 17 00:00:00 2001 From: san-tian Date: Thu, 27 Aug 2026 07:48:27 +0000 Subject: [PATCH] fix: thinking lost on /v1/messages for OpenAI-compatible backends (e.g. sglang) OpenAI-compatible backends such as sglang already return reasoning_content over chat/completions, but _route_openai_thinking_to_responses_api_if_needed rewrote enabled thinking to openai/responses/*. sglang's /v1/responses reasoning item shape (content vs summary) then triggered 'Unknown items in responses API response' and dropped the thinking block. Honor use_chat_completions_url_for_anthropic_messages and keep the chat/completions route when opted in. Add a regression test. --- .../adapters/handler.py | 5 ++++ ...erimental_pass_through_messages_handler.py | 26 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/litellm/llms/anthropic/experimental_pass_through/adapters/handler.py b/litellm/llms/anthropic/experimental_pass_through/adapters/handler.py index 9d61701d26d..8c04b4290ad 100644 --- a/litellm/llms/anthropic/experimental_pass_through/adapters/handler.py +++ b/litellm/llms/anthropic/experimental_pass_through/adapters/handler.py @@ -334,6 +334,11 @@ class LiteLLMMessagesToCompletionTransformationHandler: If the user provides a `summary` field in the thinking dict, it is passed through to the OpenAI reasoning params (opt-in per OpenAI spec). """ + if litellm.use_chat_completions_url_for_anthropic_messages: + # Honor the chat/completions opt-out; OpenAI-compatible backends + # (e.g. sglang) already return reasoning_content over chat/completions. + return + custom_llm_provider = completion_kwargs.get("custom_llm_provider") if custom_llm_provider is None: try: diff --git a/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_anthropic_experimental_pass_through_messages_handler.py b/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_anthropic_experimental_pass_through_messages_handler.py index b690b3448ec..ae135087032 100644 --- a/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_anthropic_experimental_pass_through_messages_handler.py +++ b/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_anthropic_experimental_pass_through_messages_handler.py @@ -429,6 +429,32 @@ class TestThinkingParameterTransformation: class TestThinkingSummaryPreservation: """Tests for thinking.summary preservation and reasoning_auto_summary flag.""" + def test_use_chat_completions_url_skips_responses_api_routing(self): + """Enabled thinking + use_chat_completions_url_for_anthropic_messages should NOT + rewrite the model to openai/responses/* (stays on chat/completions).""" + import litellm + + from litellm.llms.anthropic.experimental_pass_through.adapters.handler import ( + LiteLLMMessagesToCompletionTransformationHandler, + ) + + original = litellm.use_chat_completions_url_for_anthropic_messages + try: + litellm.use_chat_completions_url_for_anthropic_messages = True + completion_kwargs = { + "model": "openai/gpt-5.1", + "custom_llm_provider": "openai", + "reasoning_effort": "medium", + } + LiteLLMMessagesToCompletionTransformationHandler._route_openai_thinking_to_responses_api_if_needed( + completion_kwargs, thinking={"type": "enabled", "budget_tokens": 5000} + ) + # model must remain on chat/completions, not be rewritten to openai/responses/* + assert completion_kwargs["model"] == "openai/gpt-5.1" + assert "responses/" not in completion_kwargs["model"] + finally: + litellm.use_chat_completions_url_for_anthropic_messages = original + def test_thinking_summary_concise_preserved_for_openai(self): """User-provided summary='concise' should not be replaced with 'detailed'.""" from litellm.llms.anthropic.experimental_pass_through.adapters.handler import (