From 9ed71de96b8c516f6d3da95c98d4b461b97dcef6 Mon Sep 17 00:00:00 2001 From: Nikolay Tretyak Date: Tue, 1 Jul 2025 09:02:44 +0200 Subject: [PATCH 1/3] Fix ValidatorIterator serialization --- .../contrib/openai_agents/invoke_model_activity.py | 3 ++- tests/contrib/test_openai.py | 10 +++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/temporalio/contrib/openai_agents/invoke_model_activity.py b/temporalio/contrib/openai_agents/invoke_model_activity.py index 10b7370cb..198517fe2 100644 --- a/temporalio/contrib/openai_agents/invoke_model_activity.py +++ b/temporalio/contrib/openai_agents/invoke_model_activity.py @@ -24,6 +24,7 @@ WebSearchTool, ) from agents.models.multi_provider import MultiProvider +from pydantic_core import to_jsonable_python from typing_extensions import Required, TypedDict from temporalio import activity, workflow @@ -139,7 +140,7 @@ async def empty_on_invoke_handoff( # workaround for https://github.com/pydantic/pydantic/issues/9541 # ValidatorIterator returned - input_json = json.dumps(input["input"], default=str) + input_json = json.dumps(to_jsonable_python(input["input"])) input_input = json.loads(input_json) def make_tool(tool: ToolInput) -> Tool: diff --git a/tests/contrib/test_openai.py b/tests/contrib/test_openai.py index a3e83e53a..dbfbcb42f 100644 --- a/tests/contrib/test_openai.py +++ b/tests/contrib/test_openai.py @@ -97,6 +97,7 @@ def __init__( ) -> None: global response_index response_index = 0 + self.inputs = [] super().__init__(model, openai_client) async def get_response( @@ -114,6 +115,7 @@ async def get_response( global response_index response = self.responses[response_index] response_index += 1 + self.inputs.append(input) return response @@ -804,11 +806,12 @@ async def test_agents_as_tools_workflow(client: Client): model_params = ModelActivityParameters(start_to_close_timeout=timedelta(seconds=10)) with set_open_ai_agent_temporal_overrides(model_params): + model = AgentAsToolsModel( # type: ignore + "", openai_client=AsyncOpenAI(api_key="Fake key") + ) model_activity = ModelActivity( TestProvider( - AgentAsToolsModel( # type: ignore - "", openai_client=AsyncOpenAI(api_key="Fake key") - ) + model, ) ) async with new_worker( @@ -857,6 +860,7 @@ async def test_agents_as_tools_workflow(client: Client): .activity_task_completed_event_attributes.result.payloads[0] .data.decode() ) + assert isinstance(model.inputs[3][3]["content"], list) class AirlineAgentContext(BaseModel): From 1af5ad5a75b8d1d2ea7b3bb96dcb039ce5a05420 Mon Sep 17 00:00:00 2001 From: Nikolay Tretyak Date: Tue, 1 Jul 2025 20:24:54 +0200 Subject: [PATCH 2/3] add typehints --- tests/contrib/openai_agents/test_openai.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/contrib/openai_agents/test_openai.py b/tests/contrib/openai_agents/test_openai.py index f06430b0d..13eaf112c 100644 --- a/tests/contrib/openai_agents/test_openai.py +++ b/tests/contrib/openai_agents/test_openai.py @@ -98,7 +98,7 @@ def __init__( ) -> None: global response_index response_index = 0 - self.inputs = [] + self.inputs: list[Union[str, list[TResponseInputItem]]] = [] super().__init__(model, openai_client) async def get_response( From 89e83ca43c03aaaef62fc5ae118ae7b9f85e4f1a Mon Sep 17 00:00:00 2001 From: Nikolay Tretyak Date: Tue, 1 Jul 2025 20:34:48 +0200 Subject: [PATCH 3/3] assert --- tests/contrib/openai_agents/test_openai.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/contrib/openai_agents/test_openai.py b/tests/contrib/openai_agents/test_openai.py index 13eaf112c..d6fee8a7b 100644 --- a/tests/contrib/openai_agents/test_openai.py +++ b/tests/contrib/openai_agents/test_openai.py @@ -2,7 +2,7 @@ import uuid from dataclasses import dataclass from datetime import timedelta -from typing import Any, Optional, Union, no_type_check +from typing import Any, Optional, Union, cast, no_type_check import pytest from pydantic import ConfigDict, Field @@ -865,6 +865,7 @@ async def test_agents_as_tools_workflow(client: Client, use_local_model: bool): .activity_task_completed_event_attributes.result.payloads[0] .data.decode() ) + assert isinstance(model.inputs[3][3]["content"], list) # type: ignore class AirlineAgentContext(BaseModel):