From 953f01589beee6edfbd4fed7a332d1dcccec5e16 Mon Sep 17 00:00:00 2001 From: Henry Su Date: Thu, 20 Aug 2026 12:47:02 -0500 Subject: [PATCH] fix(extensions): nest extra_body on the any-llm chat path Flattening extra_body into acompletion kwargs collided with named parameters such as temperature and diverged from the Responses and LiteLLM adapters. --- src/agents/extensions/models/any_llm_model.py | 8 ++-- tests/models/test_any_llm_model.py | 41 +++++++++++++++++++ 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/agents/extensions/models/any_llm_model.py b/src/agents/extensions/models/any_llm_model.py index a737bb8389..8a12fdbd9c 100644 --- a/src/agents/extensions/models/any_llm_model.py +++ b/src/agents/extensions/models/any_llm_model.py @@ -1363,12 +1363,12 @@ def _consume_background_cleanup_task_result(task: asyncio.Future[Any]) -> None: def _build_chat_extra_kwargs(self, model_settings: ModelSettings) -> dict[str, Any]: extra_kwargs: dict[str, Any] = {} - if model_settings.extra_query: + if model_settings.extra_query is not None: extra_kwargs["extra_query"] = copy(model_settings.extra_query) - if model_settings.metadata: + if model_settings.metadata is not None: extra_kwargs["metadata"] = copy(model_settings.metadata) - if isinstance(model_settings.extra_body, dict): - extra_kwargs.update(model_settings.extra_body) + if model_settings.extra_body is not None: + extra_kwargs["extra_body"] = copy(model_settings.extra_body) if model_settings.extra_args: extra_kwargs.update(model_settings.extra_args) return extra_kwargs diff --git a/tests/models/test_any_llm_model.py b/tests/models/test_any_llm_model.py index b80f7c0395..3e02b28ebd 100644 --- a/tests/models/test_any_llm_model.py +++ b/tests/models/test_any_llm_model.py @@ -371,6 +371,47 @@ def __bool__(self) -> bool: assert provider.chat_calls[0]["reasoning_effort"] == "low" +@pytest.mark.allow_call_model_methods +@pytest.mark.asyncio +async def test_any_llm_chat_nests_extra_body_instead_of_flattening( + monkeypatch: pytest.MonkeyPatch, +) -> None: + provider = FakeAnyLLMProvider(supports_responses=False, chat_response=_chat_completion("Hello")) + module, _create_calls = _import_any_llm_module(monkeypatch, provider) + model = module.AnyLLMModel(model="openrouter/openai/gpt-5.4-mini") + extra_body = {"cached_content": "some_cache", "foo": 123, "temperature": 0.9} + settings = ModelSettings( + temperature=0.1, + extra_body=extra_body, + extra_query={}, + metadata={}, + ) + + await model.get_response( + system_instructions=None, + input="hi", + model_settings=settings, + tools=[], + output_schema=None, + handoffs=[], + tracing=ModelTracing.DISABLED, + previous_response_id=None, + conversation_id=None, + prompt=None, + ) + + call = provider.chat_calls[0] + assert call["temperature"] == 0.1 + assert call["extra_body"] == extra_body + assert call["extra_body"] is not extra_body + assert call["extra_query"] == {} + assert call["metadata"] == {} + assert "cached_content" not in call + assert "foo" not in call + extra_body["foo"] = 999 + assert call["extra_body"]["foo"] == 123 + + @pytest.mark.allow_call_model_methods @pytest.mark.asyncio @pytest.mark.parametrize("provider_name", ["gemini", "vertexai"])