diff --git a/src/agents/extensions/models/any_llm_model.py b/src/agents/extensions/models/any_llm_model.py index 02f58dcf68..911c46dcb3 100644 --- a/src/agents/extensions/models/any_llm_model.py +++ b/src/agents/extensions/models/any_llm_model.py @@ -360,6 +360,13 @@ async def _get_response_via_responses( prompt=prompt, ) + status = getattr(response, "status", None) + if status in {"failed", "incomplete"}: + raise response_terminal_failure_error( + f"response.{status}", + response if isinstance(response, Response) else None, + ) + if _debug.DONT_LOG_MODEL_DATA: logger.debug("LLM responded") else: diff --git a/src/agents/models/openai_responses.py b/src/agents/models/openai_responses.py index 3af75481bf..fb77767a2d 100644 --- a/src/agents/models/openai_responses.py +++ b/src/agents/models/openai_responses.py @@ -472,6 +472,13 @@ async def get_response( prompt=prompt, ) + status = getattr(response, "status", None) + if status in {"failed", "incomplete"}: + raise response_terminal_failure_error( + f"response.{status}", + response if isinstance(response, Response) else None, + ) + if _debug.DONT_LOG_MODEL_DATA: logger.debug("LLM responded") else: diff --git a/tests/models/test_any_llm_model.py b/tests/models/test_any_llm_model.py index 684baadb38..8ffdc96b50 100644 --- a/tests/models/test_any_llm_model.py +++ b/tests/models/test_any_llm_model.py @@ -623,6 +623,35 @@ async def response_stream() -> AsyncIterator[ResponseErrorEvent]: assert events[0].code == "invalid_request_error" +@pytest.mark.allow_call_model_methods +@pytest.mark.asyncio +@pytest.mark.parametrize("status", ["failed", "incomplete"]) +async def test_any_llm_responses_path_rejects_failed_or_incomplete_status( + monkeypatch, + status: str, +) -> None: + response = _response("partial", response_id="resp-terminal") + response.status = status # type: ignore[assignment] + provider = FakeAnyLLMProvider(supports_responses=True, responses_response=response) + module, _create_calls = _import_any_llm_module(monkeypatch, provider) + AnyLLMModel = module.AnyLLMModel + + model = AnyLLMModel(model="openai/gpt-5.4-mini") + with pytest.raises(ModelBehaviorError, match=f"response.{status}"): + await model.get_response( + system_instructions=None, + input="hi", + model_settings=ModelSettings(), + tools=[], + output_schema=None, + handoffs=[], + tracing=ModelTracing.DISABLED, + previous_response_id=None, + conversation_id=None, + prompt=None, + ) + + @pytest.mark.allow_call_model_methods @pytest.mark.asyncio async def test_any_llm_responses_path_passes_transport_kwargs_via_private_provider_api( diff --git a/tests/models/test_openai_responses.py b/tests/models/test_openai_responses.py index 7d329da6f8..2e4e31efbc 100644 --- a/tests/models/test_openai_responses.py +++ b/tests/models/test_openai_responses.py @@ -312,6 +312,34 @@ def __init__(self): } +@pytest.mark.allow_call_model_methods +@pytest.mark.asyncio +@pytest.mark.parametrize("status", ["failed", "incomplete"]) +async def test_get_response_rejects_failed_or_incomplete_response_status(status: str) -> None: + class DummyResponses: + async def create(self, **kwargs: Any) -> Any: + response = get_response_obj([], response_id="resp-terminal") + response.status = status # type: ignore[assignment] + return response + + class DummyResponsesClient: + def __init__(self) -> None: + self.responses = DummyResponses() + + model = OpenAIResponsesModel(model="gpt-4", openai_client=DummyResponsesClient()) # type: ignore[arg-type] + + with pytest.raises(ModelBehaviorError, match=f"response.{status}"): + await model.get_response( + system_instructions=None, + input="hi", + model_settings=ModelSettings(), + tools=[], + output_schema=None, + handoffs=[], + tracing=ModelTracing.DISABLED, + ) + + def test_get_client_disables_provider_managed_retries_on_runner_retry() -> None: class DummyResponsesClient: def __init__(self) -> None: