Skip to content

Commit dc22185

Browse files
Merge branch 'master' into major/3.0
2 parents 05de28f + 8af6a69 commit dc22185

14 files changed

Lines changed: 128 additions & 89 deletions

File tree

‎pyproject.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ typing = [
7979
"openai>=3.7.0",
8080
"tiktoken>=0.14.0",
8181
"aiohttp>=3.14.3",
82+
"openai-agents>=0.22.0",
8283
]
8384
test = [
8485
"dataclasses ; python_full_version < '3.7'",

‎sentry_sdk/integrations/openai_agents/__init__.py‎

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@
3434
# https://github.com/openai/openai-agents-python/commit/3ce7c24d349b77bb750062b7e0e856d9ff48a5d5#diff-7470b3a5c5cbe2fcbb2703dc24f326f45a5819d853be2b1f395d122d278cd911
3535
from agents.run_internal import run_loop, turn_preparation, turn_resolution
3636
except ImportError:
37-
run_loop = None
38-
turn_preparation = None
39-
turn_resolution = None
37+
run_loop = None # type: ignore[assignment]
38+
turn_preparation = None # type: ignore[assignment]
39+
turn_resolution = None # type: ignore[assignment]
4040

4141
from typing import TYPE_CHECKING
4242

@@ -50,13 +50,13 @@ def _patch_runner(use_run_hooks: "bool") -> None:
5050
# Create the root span for one full agent run (including eventual handoffs)
5151
# Note agents.run.DEFAULT_AGENT_RUNNER.run_sync is a wrapper around
5252
# agents.run.DEFAULT_AGENT_RUNNER.run. It does not need to be wrapped separately.
53-
agents.run.DEFAULT_AGENT_RUNNER.run = _create_run_wrapper(
53+
agents.run.DEFAULT_AGENT_RUNNER.run = _create_run_wrapper( # type: ignore[method-assign]
5454
agents.run.DEFAULT_AGENT_RUNNER.run,
5555
use_run_hooks=use_run_hooks,
5656
)
5757

5858
# Patch streaming runner
59-
agents.run.DEFAULT_AGENT_RUNNER.run_streamed = _create_run_streamed_wrapper(
59+
agents.run.DEFAULT_AGENT_RUNNER.run_streamed = _create_run_streamed_wrapper( # type: ignore[method-assign]
6060
agents.run.DEFAULT_AGENT_RUNNER.run_streamed,
6161
use_run_hooks=use_run_hooks,
6262
)
@@ -177,9 +177,9 @@ async def new_wrapped_final_output(
177177
return
178178

179179
if not use_run_hooks:
180-
original_get_all_tools = AgentRunner._get_all_tools
180+
original_get_all_tools = AgentRunner._get_all_tools # type: ignore[attr-defined]
181181

182-
@wraps(AgentRunner._get_all_tools.__func__)
182+
@wraps(AgentRunner._get_all_tools.__func__) # type: ignore[attr-defined]
183183
async def old_wrapped_get_all_tools(
184184
cls: "agents.Runner",
185185
agent: "agents.Agent",
@@ -189,44 +189,44 @@ async def old_wrapped_get_all_tools(
189189
original_get_all_tools, agent, context_wrapper
190190
)
191191

192-
agents.run.AgentRunner._get_all_tools = classmethod(
193-
old_wrapped_get_all_tools
192+
agents.run.AgentRunner._get_all_tools = classmethod( # type: ignore[attr-defined]
193+
old_wrapped_get_all_tools # type: ignore[arg-type]
194194
)
195195

196-
original_get_model = AgentRunner._get_model
196+
original_get_model = AgentRunner._get_model # type: ignore[attr-defined]
197197

198-
@wraps(AgentRunner._get_model.__func__)
198+
@wraps(AgentRunner._get_model.__func__) # type: ignore[attr-defined]
199199
def old_wrapped_get_model(
200200
cls: "agents.Runner", agent: "agents.Agent", run_config: "agents.RunConfig"
201201
) -> "agents.Model":
202202
return _get_model(original_get_model, agent, run_config)
203203

204-
agents.run.AgentRunner._get_model = classmethod(old_wrapped_get_model)
204+
agents.run.AgentRunner._get_model = classmethod(old_wrapped_get_model) # type: ignore[arg-type,attr-defined]
205205

206-
original_run_single_turn = AgentRunner._run_single_turn
206+
original_run_single_turn = AgentRunner._run_single_turn # type: ignore[attr-defined]
207207

208-
@wraps(AgentRunner._run_single_turn.__func__)
208+
@wraps(AgentRunner._run_single_turn.__func__) # type: ignore[attr-defined]
209209
async def old_wrapped_run_single_turn(
210210
cls: "agents.Runner", *args: "Any", **kwargs: "Any"
211211
) -> "SingleStepResult":
212212
return await _run_single_turn(original_run_single_turn, *args, **kwargs)
213213

214-
agents.run.AgentRunner._run_single_turn = classmethod(
215-
old_wrapped_run_single_turn
214+
agents.run.AgentRunner._run_single_turn = classmethod( # type: ignore[attr-defined]
215+
old_wrapped_run_single_turn # type: ignore[arg-type]
216216
)
217217

218-
original_run_single_turn_streamed = AgentRunner._run_single_turn_streamed
218+
original_run_single_turn_streamed = AgentRunner._run_single_turn_streamed # type: ignore[attr-defined]
219219

220-
@wraps(AgentRunner._run_single_turn_streamed.__func__)
220+
@wraps(AgentRunner._run_single_turn_streamed.__func__) # type: ignore[attr-defined]
221221
async def old_wrapped_run_single_turn_streamed(
222222
cls: "agents.Runner", *args: "Any", **kwargs: "Any"
223223
) -> "SingleStepResult":
224224
return await _run_single_turn_streamed(
225225
original_run_single_turn_streamed, *args, **kwargs
226226
)
227227

228-
agents.run.AgentRunner._run_single_turn_streamed = classmethod(
229-
old_wrapped_run_single_turn_streamed
228+
agents.run.AgentRunner._run_single_turn_streamed = classmethod( # type: ignore[attr-defined]
229+
old_wrapped_run_single_turn_streamed # type: ignore[arg-type]
230230
)
231231

232232
original_execute_handoffs = agents._run_impl.RunImpl.execute_handoffs
@@ -238,7 +238,7 @@ async def old_wrapped_execute_handoffs(
238238
return await _execute_handoffs(original_execute_handoffs, *args, **kwargs)
239239

240240
agents._run_impl.RunImpl.execute_handoffs = classmethod(
241-
old_wrapped_execute_handoffs
241+
old_wrapped_execute_handoffs # type: ignore[arg-type]
242242
)
243243

244244
original_execute_final_output = agents._run_impl.RunImpl.execute_final_output
@@ -252,5 +252,5 @@ async def old_wrapped_final_output(
252252
)
253253

254254
agents._run_impl.RunImpl.execute_final_output = classmethod(
255-
old_wrapped_final_output
255+
old_wrapped_final_output # type: ignore[arg-type]
256256
)

‎sentry_sdk/integrations/openai_agents/patches/agent_run.py‎

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
)
1414

1515
if TYPE_CHECKING:
16-
from typing import Any, Awaitable, Callable, Optional, Union
16+
from typing import Any, Awaitable, Callable, Coroutine, Optional, Union
1717

1818
from agents.run_internal.run_steps import SingleStepResult
1919

@@ -46,8 +46,8 @@ def _close_streaming_workflow_span(agent: "Optional[agents.Agent]") -> None:
4646

4747

4848
def _maybe_start_agent_span(
49-
context_wrapper: "agents.RunContextWrapper",
50-
agent: "agents.Agent",
49+
context_wrapper: "Optional[agents.RunContextWrapper]",
50+
agent: "Optional[agents.Agent]",
5151
should_run_agent_start_hooks: bool,
5252
span_kwargs: "dict[str, Any]",
5353
is_streaming: bool = False,
@@ -74,10 +74,10 @@ def _maybe_start_agent_span(
7474
delattr(context_wrapper, "_sentry_agent_span")
7575

7676
# Store the agent on the context wrapper so we can access it later
77-
context_wrapper._sentry_current_agent = agent
77+
context_wrapper._sentry_current_agent = agent # type: ignore[attr-defined]
7878
span = invoke_agent_span(context_wrapper, agent, span_kwargs)
79-
context_wrapper._sentry_agent_span = span
80-
agent._sentry_agent_span = span
79+
context_wrapper._sentry_agent_span = span # type: ignore[attr-defined]
80+
agent._sentry_agent_span = span # type: ignore[attr-defined]
8181

8282
if not is_streaming:
8383
return span
@@ -102,12 +102,14 @@ async def _run_single_turn(
102102
"""
103103
# openai-agents >= 0.14 passes `bindings: AgentBindings` instead of `agent`.
104104
bindings = kwargs.get("bindings")
105-
agent = (
105+
agent: "Optional[agents.Agent]" = (
106106
getattr(bindings, "public_agent", None)
107107
if bindings is not None
108108
else kwargs.get("agent")
109109
)
110-
context_wrapper = kwargs.get("context_wrapper")
110+
context_wrapper: "Optional[agents.RunContextWrapper]" = kwargs.get(
111+
"context_wrapper"
112+
)
111113
should_run_agent_start_hooks = kwargs.get("should_run_agent_start_hooks", False)
112114

113115
span = _maybe_start_agent_span(
@@ -224,7 +226,7 @@ async def _run_single_turn_streamed(
224226

225227

226228
async def _execute_handoffs(
227-
original_execute_handoffs: "Callable[..., SingleStepResult]",
229+
original_execute_handoffs: "Callable[..., Coroutine[Any, Any, SingleStepResult]]",
228230
*args: "Any",
229231
**kwargs: "Any",
230232
) -> "SingleStepResult":
@@ -235,10 +237,12 @@ async def _execute_handoffs(
235237
- ends the workflow span if the response is streamed and an exception is raised in `execute_handoffs()`.
236238
"""
237239

238-
context_wrapper = kwargs.get("context_wrapper")
240+
context_wrapper: "Optional[agents.RunContextWrapper]" = kwargs.get(
241+
"context_wrapper"
242+
)
239243
run_handoffs = kwargs.get("run_handoffs")
240244
# openai-agents >= 0.14 renamed `agent` to `public_agent`.
241-
agent = kwargs.get("public_agent", kwargs.get("agent"))
245+
agent: "Optional[agents.Agent]" = kwargs.get("public_agent", kwargs.get("agent"))
242246

243247
# Create Sentry handoff span for the first handoff (agents library only processes the first one)
244248
if run_handoffs:
@@ -282,7 +286,7 @@ async def _execute_handoffs(
282286

283287

284288
async def _execute_final_output(
285-
original_execute_final_output: "Callable[..., SingleStepResult]",
289+
original_execute_final_output: "Callable[..., Coroutine[Any, Any, SingleStepResult]]",
286290
*args: "Any",
287291
**kwargs: "Any",
288292
) -> "SingleStepResult":

‎sentry_sdk/integrations/openai_agents/patches/error_tracing.py‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ def sentry_attach_error_to_current_span(
6969
# Call the original function
7070
return original_attach_error(error, *args, **kwargs)
7171

72-
error_tracing_module.attach_error_to_current_span = (
73-
sentry_attach_error_to_current_span
72+
setattr(
73+
error_tracing_module,
74+
"attach_error_to_current_span",
75+
sentry_attach_error_to_current_span,
7476
)

‎sentry_sdk/integrations/openai_agents/patches/models.py‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ def _get_model(
7373

7474
# Capture the request model name for spans (agent.model can be None when using defaults)
7575
request_model_name = model.model if hasattr(model, "model") else str(model)
76-
agent._sentry_request_model = request_model_name
76+
agent._sentry_request_model = request_model_name # type: ignore[attr-defined]
7777

7878
# Wrap _fetch_response if it exists (for OpenAI models) to capture response model
7979
if hasattr(model, "_fetch_response"):
@@ -83,7 +83,7 @@ def _get_model(
8383
async def wrapped_fetch_response(*args: "Any", **kwargs: "Any") -> "Any":
8484
response = await original_fetch_response(*args, **kwargs)
8585
if hasattr(response, "model") and response.model:
86-
agent._sentry_response_model = str(response.model)
86+
agent._sentry_response_model = str(response.model) # type: ignore[attr-defined]
8787
return response
8888

8989
model._fetch_response = wrapped_fetch_response
@@ -114,7 +114,7 @@ async def wrapped_get_response(*args: "Any", **kwargs: "Any") -> "Any":
114114

115115
return result
116116

117-
model.get_response = wrapped_get_response
117+
model.get_response = wrapped_get_response # type: ignore[method-assign]
118118

119119
# Also wrap stream_response for streaming support
120120
if hasattr(model, "stream_response"):
@@ -177,6 +177,6 @@ async def wrapped_stream_response(*args: "Any", **kwargs: "Any") -> "Any":
177177
span, streaming_response, response_model, agent
178178
)
179179

180-
model.stream_response = wrapped_stream_response
180+
model.stream_response = wrapped_stream_response # type: ignore[method-assign]
181181

182182
return model

‎sentry_sdk/integrations/openai_agents/patches/runner.py‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
TContext = TypeVar("TContext")
3838

3939

40-
class _SentryRunHooks(RunHooks[TContext]): # type: ignore[misc]
40+
class _SentryRunHooks(RunHooks[TContext]):
4141
"""
4242
Responsible for creating and managing Execute Tool spans. These spans are
4343
stored on the ToolContext reference that is shared between `on_tool_start()`
@@ -120,9 +120,9 @@ async def on_tool_end(
120120
await sentry_hooks.on_tool_end(context, agent, tool, result)
121121
await original_on_tool_end(context, agent, tool, result)
122122

123-
hooks._sentry_is_patched = True
124-
hooks.on_tool_start = on_tool_start
125-
hooks.on_tool_end = on_tool_end
123+
hooks._sentry_is_patched = True # type: ignore[attr-defined]
124+
hooks.on_tool_start = on_tool_start # type: ignore[method-assign]
125+
hooks.on_tool_end = on_tool_end # type: ignore[method-assign]
126126

127127

128128
def _create_run_wrapper(

‎sentry_sdk/integrations/openai_agents/patches/tools.py‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
try:
1717
import agents
18+
from agents import FunctionTool
1819
except ImportError:
1920
raise DidNotEnable("OpenAI Agents not installed")
2021

@@ -30,18 +31,18 @@ async def _get_all_tools(
3031
# Get the original tools
3132
tools = await original_get_all_tools(agent, context_wrapper)
3233

33-
wrapped_tools = []
34+
wrapped_tools: "list[agents.Tool]" = []
3435
for tool in tools:
3536
# Wrap only the function tools (for now)
36-
if tool.__class__.__name__ != "FunctionTool":
37+
if not isinstance(tool, FunctionTool):
3738
wrapped_tools.append(tool)
3839
continue
3940

4041
# Create a new FunctionTool with our wrapped invoke method
4142
original_on_invoke = tool.on_invoke_tool
4243

4344
def create_wrapped_invoke(
44-
current_tool: "agents.Tool", current_on_invoke: "Callable[..., Any]"
45+
current_tool: "FunctionTool", current_on_invoke: "Callable[..., Any]"
4546
) -> "Callable[..., Any]":
4647
@wraps(current_on_invoke)
4748
async def sentry_wrapped_on_invoke_tool(

‎sentry_sdk/integrations/openai_agents/spans/ai_client.py‎

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,23 @@
2525
try:
2626
from agents import ApplyPatchTool, ShellTool
2727
except ImportError:
28-
ShellTool = None
29-
ApplyPatchTool = None
28+
ShellTool = None # type: ignore[assignment,misc]
29+
ApplyPatchTool = None # type: ignore[assignment,misc]
3030

3131
try:
3232
from agents import ToolSearchTool
3333
except ImportError:
34-
ToolSearchTool = None
34+
ToolSearchTool = None # type: ignore[assignment,misc]
3535

3636
try:
3737
from agents import CustomTool
3838
except ImportError:
39-
CustomTool = None
39+
CustomTool = None # type: ignore[assignment,misc]
4040

4141
try:
4242
from agents import ProgrammaticToolCallingTool
4343
except ImportError:
44-
ProgrammaticToolCallingTool = None
44+
ProgrammaticToolCallingTool = None # type: ignore[assignment,misc]
4545

4646

4747
from ..consts import SPAN_ORIGIN
@@ -201,7 +201,6 @@ def ai_client_span(
201201
agent: "Agent", get_response_kwargs: "dict[str, Any]"
202202
) -> "Union[sentry_sdk.tracing.Span, StreamedSpan]":
203203
# TODO-anton: implement other types of operations. Now "chat" is hardcoded.
204-
# Get model name from agent.model or fall back to request model (for when agent.model is None/default)
205204
model_name = None
206205
if agent.model:
207206
model_name = agent.model.model if hasattr(agent.model, "model") else agent.model

‎sentry_sdk/integrations/openai_agents/spans/execute_tool.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818

1919
def execute_tool_span(
20-
tool: "agents.Tool", *args: "Any", **kwargs: "Any"
20+
tool: "agents.FunctionTool", *args: "Any", **kwargs: "Any"
2121
) -> "Union[sentry_sdk.tracing.Span, StreamedSpan]":
2222
span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options)
2323

‎sentry_sdk/integrations/openai_agents/spans/handoff.py‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,20 @@
77
from ..consts import SPAN_ORIGIN
88

99
if TYPE_CHECKING:
10+
from typing import Optional
11+
1012
import agents
1113

1214

1315
def handoff_span(
14-
context: "agents.RunContextWrapper", from_agent: "agents.Agent", to_agent_name: str
16+
context: "Optional[agents.RunContextWrapper]",
17+
from_agent: "Optional[agents.Agent]",
18+
to_agent_name: str,
1519
) -> None:
1620
span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options)
1721
if span_streaming:
1822
with sentry_sdk.traces.start_span(
19-
name=f"handoff from {from_agent.name} to {to_agent_name}",
23+
name=f"handoff from {from_agent.name} to {to_agent_name}", # type: ignore[union-attr]
2024
attributes={
2125
"sentry.op": OP.GEN_AI_HANDOFF,
2226
"sentry.origin": SPAN_ORIGIN,
@@ -30,7 +34,7 @@ def handoff_span(
3034
else:
3135
with sentry_sdk.start_span(
3236
op=OP.GEN_AI_HANDOFF,
33-
name=f"handoff from {from_agent.name} to {to_agent_name}",
37+
name=f"handoff from {from_agent.name} to {to_agent_name}", # type: ignore[union-attr]
3438
origin=SPAN_ORIGIN,
3539
) as span:
3640
span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "handoff")

0 commit comments

Comments
 (0)