From 376e3e168b409a7536a510635c85403d089ba31c Mon Sep 17 00:00:00 2001 From: Kazuhiro Sera Date: Tue, 22 Jul 2025 12:51:58 +0900 Subject: [PATCH 1/2] Fix #980 Chat Completions: fails with function name for tool_choice parameter w/ streaming enabled --- src/agents/models/openai_chatcompletions.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/agents/models/openai_chatcompletions.py b/src/agents/models/openai_chatcompletions.py index 6de431b4d..dfbde5035 100644 --- a/src/agents/models/openai_chatcompletions.py +++ b/src/agents/models/openai_chatcompletions.py @@ -3,7 +3,7 @@ import json import time from collections.abc import AsyncIterator -from typing import TYPE_CHECKING, Any, Literal, cast, overload +from typing import TYPE_CHECKING, Any, Literal, overload from openai import NOT_GIVEN, AsyncOpenAI, AsyncStream from openai.types import ChatModel @@ -28,6 +28,7 @@ from .chatcmpl_stream_handler import ChatCmplStreamHandler from .fake_id import FAKE_RESPONSES_ID from .interface import Model, ModelTracing +from .openai_responses import Converter as OpenAIResponsesConverter if TYPE_CHECKING: from ..model_settings import ModelSettings @@ -296,15 +297,27 @@ async def _fetch_response( if isinstance(ret, ChatCompletion): return ret + responses_tool_choice = OpenAIResponsesConverter.convert_tool_choice( + model_settings.tool_choice + ) + if responses_tool_choice is None or responses_tool_choice == NOT_GIVEN: + # For Responses API data compatibility with Chat Completions patterns, + # we need to set "none" if tool_choice is absent. + # Without this fix, you'll get the following error: + # pydantic_core._pydantic_core.ValidationError: 4 validation errors for Response + # tool_choice.literal['none','auto','required'] + # Input should be 'none', 'auto' or 'required' + # [type=literal_error, input_value=NOT_GIVEN, input_type=NotGiven] + # see also: https://github.com/openai/openai-agents-python/issues/980 + responses_tool_choice = "none" + response = Response( id=FAKE_RESPONSES_ID, created_at=time.time(), model=self.model, object="response", output=[], - tool_choice=cast(Literal["auto", "required", "none"], tool_choice) - if tool_choice != NOT_GIVEN - else "auto", + tool_choice=responses_tool_choice, # type: ignore[arg-type] top_p=model_settings.top_p, temperature=model_settings.temperature, tools=[], From 9a52e2499c2cd14d64e435351dc63d37dd8debcf Mon Sep 17 00:00:00 2001 From: Kazuhiro Sera Date: Wed, 23 Jul 2025 10:42:13 +0900 Subject: [PATCH 2/2] Update src/agents/models/openai_chatcompletions.py --- src/agents/models/openai_chatcompletions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/agents/models/openai_chatcompletions.py b/src/agents/models/openai_chatcompletions.py index dfbde5035..3798e100d 100644 --- a/src/agents/models/openai_chatcompletions.py +++ b/src/agents/models/openai_chatcompletions.py @@ -309,7 +309,7 @@ async def _fetch_response( # Input should be 'none', 'auto' or 'required' # [type=literal_error, input_value=NOT_GIVEN, input_type=NotGiven] # see also: https://github.com/openai/openai-agents-python/issues/980 - responses_tool_choice = "none" + responses_tool_choice = "auto" response = Response( id=FAKE_RESPONSES_ID,