From 2d243a3f4a3f8b4476c53977b0f01089144c29e4 Mon Sep 17 00:00:00 2001 From: mateo-berri <277851410+mateo-berri@users.noreply.github.com> Date: Fri, 6 Nov 2026 13:43:08 -0800 Subject: [PATCH] fix(anthropic): apply the background check to extra_body on the /v1/messages Responses bridge litellm merges extra_body into the upstream Responses request, so background inside it started a background run past the top-level check. It now answers 400 without drop_params and is stripped from extra_body when dropped. --- .../messages/responses_adapters/handler.py | 15 ++++++++++++- .../test_responses_adapters_handler.py | 21 +++++++++++++++---- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/litellm/llms/anthropic/messages/responses_adapters/handler.py b/litellm/llms/anthropic/messages/responses_adapters/handler.py index 4e4cdb0ee0f..12716195f06 100644 --- a/litellm/llms/anthropic/messages/responses_adapters/handler.py +++ b/litellm/llms/anthropic/messages/responses_adapters/handler.py @@ -179,8 +179,19 @@ def _drops_background(forwarded_kwargs: Mapping[str, object]) -> bool: ) +def _requests_background(forwarded_kwargs: Mapping[str, object]) -> bool: + extra_body: Final = as_str_mapping(forwarded_kwargs.get("extra_body")) + return forwarded_kwargs.get("background") is not None or ( + extra_body is not None and extra_body.get("background") is not None + ) + + +def _without_background(extra_body: Mapping[str, object]) -> Mapping[str, object]: + return {key: value for key, value in extra_body.items() if key != "background"} + + def _reject_background_mode(model: str, forwarded_kwargs: Mapping[str, object]) -> None: - if forwarded_kwargs.get("background") is None or _drops_background(forwarded_kwargs): + if not _requests_background(forwarded_kwargs) or _drops_background(forwarded_kwargs): return provider: Final = forwarded_kwargs.get("custom_llm_provider") raise litellm.UnsupportedParamsError( @@ -396,6 +407,8 @@ def _build_responses_kwargs( # Responses API result back to a ModelResponse for the row. setattr(value, "call_type", CallTypes.anthropic_messages.value) responses_kwargs[key] = value + elif key == "extra_body" and (extra_body := as_str_mapping(value)) is not None: + responses_kwargs[key] = _without_background(extra_body) elif key not in excluded and key not in responses_kwargs and value is not None: responses_kwargs[key] = value diff --git a/tests/unit/llms/anthropic/messages/responses_adapters/test_responses_adapters_handler.py b/tests/unit/llms/anthropic/messages/responses_adapters/test_responses_adapters_handler.py index 6ecd79af531..c5575a8c150 100644 --- a/tests/unit/llms/anthropic/messages/responses_adapters/test_responses_adapters_handler.py +++ b/tests/unit/llms/anthropic/messages/responses_adapters/test_responses_adapters_handler.py @@ -684,12 +684,19 @@ def test_tool_result_text_block_without_text_still_reaches_the_model_as_empty_te ] -@pytest.mark.parametrize("background", [True, False]) -def test_background_answers_400_without_drop_params(background: bool) -> None: +@pytest.mark.parametrize( + "background_request", + [ + pytest.param({"background": True}, id="background-true"), + pytest.param({"background": False}, id="background-false"), + pytest.param({"extra_body": {"background": True}}, id="extra-body-background"), + ], +) +def test_background_answers_400_without_drop_params(background_request: Mapping[str, object]) -> None: with pytest.raises(litellm.UnsupportedParamsError) as rejected: _build_responses_kwargs( model="openai/gpt-5.6", - extra_kwargs={**OPENAI_API, "background": background}, + extra_kwargs={**OPENAI_API, **background_request}, max_tokens=1024, messages=MESSAGES, ) @@ -708,12 +715,18 @@ def test_background_answers_400_without_drop_params(background: bool) -> None: def test_dropped_background_never_reaches_the_responses_request(drop_setting: Mapping[str, object]) -> None: responses_kwargs: Final = _build_responses_kwargs( model="openai/gpt-5.6", - extra_kwargs={**OPENAI_API, **drop_setting, "background": True}, + extra_kwargs={ + **OPENAI_API, + **drop_setting, + "background": True, + "extra_body": {"background": True, "service_tier": "priority"}, + }, max_tokens=1024, messages=MESSAGES, ) assert "background" not in responses_kwargs + assert responses_kwargs["extra_body"] == {"service_tier": "priority"} assert responses_kwargs["max_output_tokens"] == 1024