From 6bc3edbb35c72459b3c66751f48c44ca8da067f7 Mon Sep 17 00:00:00 2001 From: Tim Conley Date: Mon, 21 Jul 2025 15:22:03 -0700 Subject: [PATCH 1/4] Add argument validation for the types of provided tools --- .../contrib/openai_agents/_openai_runner.py | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/temporalio/contrib/openai_agents/_openai_runner.py b/temporalio/contrib/openai_agents/_openai_runner.py index f43d01388..b99a157f8 100644 --- a/temporalio/contrib/openai_agents/_openai_runner.py +++ b/temporalio/contrib/openai_agents/_openai_runner.py @@ -1,23 +1,20 @@ from dataclasses import replace -from datetime import timedelta -from typing import Optional, Union +from typing import Union from agents import ( Agent, RunConfig, - RunHooks, RunResult, RunResultStreaming, TContext, + Tool, TResponseInputItem, ) from agents.run import DEFAULT_AGENT_RUNNER, DEFAULT_MAX_TURNS, AgentRunner from temporalio import workflow -from temporalio.common import Priority, RetryPolicy from temporalio.contrib.openai_agents._model_parameters import ModelActivityParameters from temporalio.contrib.openai_agents._temporal_model_stub import _TemporalModelStub -from temporalio.workflow import ActivityCancellationType, VersioningIntent class TemporalOpenAIRunner(AgentRunner): @@ -46,6 +43,12 @@ async def run( **kwargs, ) + for t in starting_agent.tools: + if not isinstance(t, Tool): + raise ValueError( + "Provided tool is not a tool type. If using an activity, make sure to wrap it with openai_agents.workflow.activity_as_tool." + ) + context = kwargs.get("context") max_turns = kwargs.get("max_turns", DEFAULT_MAX_TURNS) hooks = kwargs.get("hooks") @@ -67,16 +70,15 @@ async def run( ), ) - with workflow.unsafe.imports_passed_through(): - return await self._runner.run( - starting_agent=starting_agent, - input=input, - context=context, - max_turns=max_turns, - hooks=hooks, - run_config=updated_run_config, - previous_response_id=previous_response_id, - ) + return await self._runner.run( + starting_agent=starting_agent, + input=input, + context=context, + max_turns=max_turns, + hooks=hooks, + run_config=updated_run_config, + previous_response_id=previous_response_id, + ) def run_sync( self, From 7b95525b5b0130e785900caa5b71ba67b449c9ac Mon Sep 17 00:00:00 2001 From: Tim Conley Date: Mon, 21 Jul 2025 15:32:25 -0700 Subject: [PATCH 2/4] Specifically check if it is a callable, as Union isn't supported in isinstance --- temporalio/contrib/openai_agents/_openai_runner.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/temporalio/contrib/openai_agents/_openai_runner.py b/temporalio/contrib/openai_agents/_openai_runner.py index b99a157f8..9b684ae84 100644 --- a/temporalio/contrib/openai_agents/_openai_runner.py +++ b/temporalio/contrib/openai_agents/_openai_runner.py @@ -1,3 +1,4 @@ +from collections.abc import Callable from dataclasses import replace from typing import Union @@ -7,7 +8,6 @@ RunResult, RunResultStreaming, TContext, - Tool, TResponseInputItem, ) from agents.run import DEFAULT_AGENT_RUNNER, DEFAULT_MAX_TURNS, AgentRunner @@ -44,7 +44,7 @@ async def run( ) for t in starting_agent.tools: - if not isinstance(t, Tool): + if isinstance(t, Callable): raise ValueError( "Provided tool is not a tool type. If using an activity, make sure to wrap it with openai_agents.workflow.activity_as_tool." ) From e4da8aa9a32bd096f381f72267a98d21c34544ec Mon Sep 17 00:00:00 2001 From: Tim Conley Date: Mon, 21 Jul 2025 15:49:28 -0700 Subject: [PATCH 3/4] Fix type check with typing.get_args --- temporalio/contrib/openai_agents/_invoke_model_activity.py | 2 +- temporalio/contrib/openai_agents/_openai_runner.py | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/temporalio/contrib/openai_agents/_invoke_model_activity.py b/temporalio/contrib/openai_agents/_invoke_model_activity.py index 069ea001e..96cd7e05e 100644 --- a/temporalio/contrib/openai_agents/_invoke_model_activity.py +++ b/temporalio/contrib/openai_agents/_invoke_model_activity.py @@ -160,7 +160,7 @@ def make_tool(tool: ToolInput) -> Tool: raise UserError(f"Unknown tool type: {tool.name}") tools = [make_tool(x) for x in input.get("tools", [])] - handoffs = [ + handoffs: list[Handoff[Any, Any]] = [ Handoff( tool_name=x.tool_name, tool_description=x.tool_description, diff --git a/temporalio/contrib/openai_agents/_openai_runner.py b/temporalio/contrib/openai_agents/_openai_runner.py index 9b684ae84..5deb11a59 100644 --- a/temporalio/contrib/openai_agents/_openai_runner.py +++ b/temporalio/contrib/openai_agents/_openai_runner.py @@ -1,4 +1,4 @@ -from collections.abc import Callable +import typing from dataclasses import replace from typing import Union @@ -8,6 +8,7 @@ RunResult, RunResultStreaming, TContext, + Tool, TResponseInputItem, ) from agents.run import DEFAULT_AGENT_RUNNER, DEFAULT_MAX_TURNS, AgentRunner @@ -43,8 +44,9 @@ async def run( **kwargs, ) + tool_types = typing.get_args(Tool) for t in starting_agent.tools: - if isinstance(t, Callable): + if isinstance(t, tool_types): raise ValueError( "Provided tool is not a tool type. If using an activity, make sure to wrap it with openai_agents.workflow.activity_as_tool." ) From 443b2b65e5ec57bb682771ab3e7fd6e228c0262a Mon Sep 17 00:00:00 2001 From: Tim Conley Date: Tue, 22 Jul 2025 10:30:29 -0700 Subject: [PATCH 4/4] Fix check --- temporalio/contrib/openai_agents/_openai_runner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/temporalio/contrib/openai_agents/_openai_runner.py b/temporalio/contrib/openai_agents/_openai_runner.py index 638a559dc..1ccbc5f4d 100644 --- a/temporalio/contrib/openai_agents/_openai_runner.py +++ b/temporalio/contrib/openai_agents/_openai_runner.py @@ -46,7 +46,7 @@ async def run( tool_types = typing.get_args(Tool) for t in starting_agent.tools: - if isinstance(t, tool_types): + if not isinstance(t, tool_types): raise ValueError( "Provided tool is not a tool type. If using an activity, make sure to wrap it with openai_agents.workflow.activity_as_tool." )