From 2353ccd84d9f377a902b0006633781b27c2cfc79 Mon Sep 17 00:00:00 2001 From: mikemikimike <13286568797@163.com> Date: Sun, 16 Aug 2026 21:32:14 +0800 Subject: [PATCH 1/4] fix(messages): honor chat completions opt-in --- .../messages/handler.py | 12 +++++++--- ...erimental_pass_through_messages_handler.py | 22 +++++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/litellm/llms/anthropic/experimental_pass_through/messages/handler.py b/litellm/llms/anthropic/experimental_pass_through/messages/handler.py index c4b5cc628e2..f7716c80c2e 100644 --- a/litellm/llms/anthropic/experimental_pass_through/messages/handler.py +++ b/litellm/llms/anthropic/experimental_pass_through/messages/handler.py @@ -42,13 +42,16 @@ from .utils import AnthropicMessagesRequestUtils, mock_response _RESPONSES_API_PROVIDERS: Final = frozenset({"openai"}) -def _should_route_to_responses_api(custom_llm_provider: str | None) -> bool: +def _should_route_to_responses_api( + custom_llm_provider: str | None, + use_chat_completions_api: bool | None = None, +) -> bool: """Return True when the provider should use the Responses API path. Set ``litellm.use_chat_completions_url_for_anthropic_messages = True`` to opt out and route OpenAI/Azure requests through chat/completions instead. """ - if litellm.use_chat_completions_url_for_anthropic_messages: + if litellm.use_chat_completions_url_for_anthropic_messages or use_chat_completions_api is True: return False return custom_llm_provider in _RESPONSES_API_PROVIDERS @@ -551,7 +554,10 @@ def anthropic_messages_handler( custom_llm_provider=custom_llm_provider, **kwargs, ) - if _should_route_to_responses_api(custom_llm_provider): + if _should_route_to_responses_api( + custom_llm_provider=custom_llm_provider, + use_chat_completions_api=kwargs.get("use_chat_completions_api"), + ): return LiteLLMMessagesToResponsesAPIHandler.anthropic_messages_handler(**_shared_kwargs) # The in-gateway context_management polyfill runs inside 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 f11324ca376..0ac051fa612 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 @@ -939,6 +939,28 @@ def test_gate_translates_when_supported_endpoints_absent(monkeypatch): assert "config" not in captured +def test_gate_uses_chat_completions_when_requested(monkeypatch): + """The per-deployment chat-completions opt-in must bypass Responses API.""" + from litellm.llms.anthropic.experimental_pass_through.messages.handler import ( + anthropic_messages_handler, + ) + + captured, translation_calls = _gate_stubs(monkeypatch) + + result = anthropic_messages_handler( + max_tokens=100, + messages=[{"role": "user", "content": "Hello"}], + model="openai/some-model", + api_key="sk-test", + api_base="https://host/v1", + use_chat_completions_api=True, + ) + + assert result == "translated" + assert translation_calls["count"] == 1 + assert "config" not in captured + + def test_gate_passthrough_skipped_when_only_chat_completions_supported(monkeypatch): """A deployment that lists only /v1/chat/completions is still translated; the opt-in is specifically the /v1/messages entry.""" From 1d83c2851656f54f3c045bc33f8c76715d089356 Mon Sep 17 00:00:00 2001 From: mikemikimike <13286568797@163.com> Date: Sun, 16 Aug 2026 22:28:05 +0800 Subject: [PATCH 2/4] test: distinguish anthropic translation routing paths --- ...erimental_pass_through_messages_handler.py | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) 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 0ac051fa612..ee30638e015 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 @@ -867,26 +867,30 @@ def _gate_stubs(monkeypatch): from litellm.llms.anthropic.experimental_pass_through.messages import handler captured = {} - translation_calls = {"count": 0} + translation_calls = {"responses": 0, "chat_completions": 0} def fake_native(**kwargs): captured["config"] = kwargs.get("anthropic_messages_provider_config") return "native-passthrough" - def fake_translation(**kwargs): - translation_calls["count"] += 1 - return "translated" + def fake_responses(**kwargs): + translation_calls["responses"] += 1 + return "responses" + + def fake_chat_completions(**kwargs): + translation_calls["chat_completions"] += 1 + return "chat-completions" monkeypatch.setattr(handler.base_llm_http_handler, "anthropic_messages_handler", fake_native) monkeypatch.setattr( handler.LiteLLMMessagesToResponsesAPIHandler, "anthropic_messages_handler", - staticmethod(fake_translation), + staticmethod(fake_responses), ) monkeypatch.setattr( handler.LiteLLMMessagesToCompletionTransformationHandler, "anthropic_messages_handler", - staticmethod(fake_translation), + staticmethod(fake_chat_completions), ) return captured, translation_calls @@ -934,8 +938,9 @@ def test_gate_translates_when_supported_endpoints_absent(monkeypatch): api_base="https://host/v1", ) - assert result == "translated" - assert translation_calls["count"] == 1 + assert result == "chat-completions" + assert translation_calls["responses"] == 0 + assert translation_calls["chat_completions"] == 1 assert "config" not in captured From a3ed9a04f3b82456b467b4c1e551c79ca23f9d65 Mon Sep 17 00:00:00 2001 From: mikemikimike <13286568797@163.com> Date: Sun, 16 Aug 2026 22:28:46 +0800 Subject: [PATCH 3/4] fix: assert each anthropic routing path --- ...erimental_pass_through_messages_handler.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) 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 ee30638e015..e48fc8dd2c5 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 @@ -918,7 +918,8 @@ def test_gate_passthrough_when_supported_endpoints_opts_in(monkeypatch): assert result == "native-passthrough" assert isinstance(captured["config"], OpenAILikeAnthropicMessagesConfig) - assert translation_calls["count"] == 0 + assert translation_calls["responses"] == 0 + assert translation_calls["chat_completions"] == 0 def test_gate_translates_when_supported_endpoints_absent(monkeypatch): @@ -938,9 +939,9 @@ def test_gate_translates_when_supported_endpoints_absent(monkeypatch): api_base="https://host/v1", ) - assert result == "chat-completions" - assert translation_calls["responses"] == 0 - assert translation_calls["chat_completions"] == 1 + assert result == "responses" + assert translation_calls["responses"] == 1 + assert translation_calls["chat_completions"] == 0 assert "config" not in captured @@ -961,8 +962,9 @@ def test_gate_uses_chat_completions_when_requested(monkeypatch): use_chat_completions_api=True, ) - assert result == "translated" - assert translation_calls["count"] == 1 + assert result == "chat-completions" + assert translation_calls["responses"] == 0 + assert translation_calls["chat_completions"] == 1 assert "config" not in captured @@ -984,6 +986,7 @@ def test_gate_passthrough_skipped_when_only_chat_completions_supported(monkeypat model_info={"supported_endpoints": ["/v1/chat/completions"]}, ) - assert result == "translated" - assert translation_calls["count"] == 1 + assert result == "chat-completions" + assert translation_calls["responses"] == 0 + assert translation_calls["chat_completions"] == 1 assert "config" not in captured From c4f3bf837d7b391aeb21f2900f8460922f5d68ee Mon Sep 17 00:00:00 2001 From: mikemikimike <13286568797@163.com> Date: Sat, 22 Aug 2026 10:57:43 +0800 Subject: [PATCH 4/4] test(messages): fix openai routing expectation --- ..._anthropic_experimental_pass_through_messages_handler.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 e48fc8dd2c5..899d96bc2e1 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 @@ -986,7 +986,7 @@ def test_gate_passthrough_skipped_when_only_chat_completions_supported(monkeypat model_info={"supported_endpoints": ["/v1/chat/completions"]}, ) - assert result == "chat-completions" - assert translation_calls["responses"] == 0 - assert translation_calls["chat_completions"] == 1 + assert result == "responses" + assert translation_calls["responses"] == 1 + assert translation_calls["chat_completions"] == 0 assert "config" not in captured