diff --git a/pydantic_ai_slim/pydantic_ai/models/openai.py b/pydantic_ai_slim/pydantic_ai/models/openai.py index 40b629a903..ce9b18e483 100644 --- a/pydantic_ai_slim/pydantic_ai/models/openai.py +++ b/pydantic_ai_slim/pydantic_ai/models/openai.py @@ -1148,10 +1148,10 @@ async def _responses_create( + list(model_settings.get('openai_builtin_tools', [])) + self._get_tools(model_request_parameters) ) - + profile = OpenAIModelProfile.from_profile(self.profile) if not tools: tool_choice: Literal['none', 'required', 'auto'] | None = None - elif not model_request_parameters.allow_text_output: + elif not model_request_parameters.allow_text_output and profile.openai_supports_tool_choice_required: tool_choice = 'required' else: tool_choice = 'auto' @@ -1184,7 +1184,6 @@ async def _responses_create( text = text or {} text['verbosity'] = verbosity - profile = OpenAIModelProfile.from_profile(self.profile) unsupported_model_settings = profile.openai_unsupported_model_settings for setting in unsupported_model_settings: model_settings.pop(setting, None) diff --git a/tests/models/test_openai.py b/tests/models/test_openai.py index e4357c3414..d937c0a6a3 100644 --- a/tests/models/test_openai.py +++ b/tests/models/test_openai.py @@ -45,7 +45,14 @@ from pydantic_ai.usage import RequestUsage from ..conftest import IsDatetime, IsNow, IsStr, TestEnv, try_import -from .mock_openai import MockOpenAI, completion_message, get_mock_chat_completion_kwargs +from .mock_openai import ( + MockOpenAI, + MockOpenAIResponses, + completion_message, + get_mock_chat_completion_kwargs, + get_mock_responses_kwargs, + response_message, +) with try_import() as imports_successful: from openai import APIStatusError, AsyncOpenAI @@ -2978,6 +2985,25 @@ async def test_tool_choice_fallback(allow_model_requests: None) -> None: assert get_mock_chat_completion_kwargs(mock_client)[0]['tool_choice'] == 'auto' +async def test_tool_choice_fallback_response_api(allow_model_requests: None) -> None: + """Ensure tool_choice falls back to 'auto' for Responses API when 'required' unsupported.""" + profile = OpenAIModelProfile(openai_supports_tool_choice_required=False).update(openai_model_profile('stub')) + + mock_client = MockOpenAIResponses.create_mock(response_message([])) + model = OpenAIResponsesModel('openai/gpt-oss', provider=OpenAIProvider(openai_client=mock_client), profile=profile) + + params = ModelRequestParameters(function_tools=[ToolDefinition(name='x')], allow_text_output=False) + + await model._responses_create( # pyright: ignore[reportPrivateUsage] + messages=[], + stream=False, + model_settings={}, + model_request_parameters=params, + ) + + assert get_mock_responses_kwargs(mock_client)[0]['tool_choice'] == 'auto' + + async def test_openai_model_settings_temperature_ignored_on_gpt_5(allow_model_requests: None, openai_api_key: str): m = OpenAIChatModel('gpt-5', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent(m)