Skip to content
Merged
Changes from 2 commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
b64d076
.
alexander-alderman-webb May 7, 2026
2fce29b
fix openai-agents
alexander-alderman-webb May 7, 2026
81c4c33
openai-agents round 2
alexander-alderman-webb May 7, 2026
f2cb5b4
fix(mcp): Add None checks (#6219)
alexander-alderman-webb May 7, 2026
90b64f2
fix(dramatiq): Assign an empty tuple instead of an empty list (#6220)
alexander-alderman-webb May 7, 2026
c813311
fix(opentelemetry): Handle `ImportError` (#6221)
alexander-alderman-webb May 7, 2026
d34d61b
ci: Change type ignores and remove duplicate declarations (#6222)
alexander-alderman-webb May 7, 2026
8e76cd7
ci(cloud_resource_context): Avoid not indexable `mypy` errors (#6223)
alexander-alderman-webb May 7, 2026
8adb3f2
ci(grpc): Do not re-declare parameter (#6224)
alexander-alderman-webb May 7, 2026
4902c5e
ci(sanic): Widen type annotation (#6226)
alexander-alderman-webb May 7, 2026
7b68600
ci(starlette): Add type ignore (#6228)
alexander-alderman-webb May 7, 2026
f79b4d6
fix(wsgi): Do not catch `None` (#6229)
alexander-alderman-webb May 7, 2026
235829c
ci(gnu-backtrace): Use distinct variable name (#6231)
alexander-alderman-webb May 7, 2026
b63ef99
ci(django): Widen type annotation and remove unused type ignore (#6232)
alexander-alderman-webb May 7, 2026
3530c60
Make URI check consistent with prior behavior
alexander-alderman-webb May 7, 2026
d226d31
Merge branch 'webb/test-ci-3' of github.com:getsentry/sentry-python i…
alexander-alderman-webb May 7, 2026
b74e17d
simplify mcp URI type check
alexander-alderman-webb May 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 61 additions & 53 deletions sentry_sdk/integrations/openai_agents/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,72 +99,80 @@
0,
8,
):

@wraps(run_loop.get_all_tools)
async def new_wrapped_get_all_tools(
agent: "agents.Agent",
context_wrapper: "agents.RunContextWrapper",
) -> "list[agents.Tool]":
return await _get_all_tools(
run_loop.get_all_tools, agent, context_wrapper
if run_loop is not None:

@wraps(run_loop.get_all_tools)
async def new_wrapped_get_all_tools(
agent: "agents.Agent",
context_wrapper: "agents.RunContextWrapper",
) -> "list[agents.Tool]":
return await _get_all_tools(
run_loop.get_all_tools, agent, context_wrapper
)

agents.run.get_all_tools = new_wrapped_get_all_tools

@wraps(run_loop.run_single_turn)
async def new_wrapped_run_single_turn(
*args: "Any", **kwargs: "Any"
) -> "SingleStepResult":
return await _run_single_turn(
run_loop.run_single_turn, *args, **kwargs
)

agents.run.run_single_turn = new_wrapped_run_single_turn

@wraps(run_loop.run_single_turn_streamed)
async def new_wrapped_run_single_turn_streamed(
*args: "Any", **kwargs: "Any"
) -> "SingleStepResult":
return await _run_single_turn_streamed(
run_loop.run_single_turn_streamed, *args, **kwargs
)

agents.run.run_single_turn_streamed = (
new_wrapped_run_single_turn_streamed
)

agents.run.get_all_tools = new_wrapped_get_all_tools

@wraps(turn_preparation.get_model)
def new_wrapped_get_model(
agent: "agents.Agent", run_config: "agents.RunConfig"
) -> "agents.Model":
return _get_model(turn_preparation.get_model, agent, run_config)

agents.run_internal.run_loop.get_model = new_wrapped_get_model

@wraps(run_loop.run_single_turn)
async def new_wrapped_run_single_turn(
*args: "Any", **kwargs: "Any"
) -> "SingleStepResult":
return await _run_single_turn(run_loop.run_single_turn, *args, **kwargs)
if turn_preparation is not None:

agents.run.run_single_turn = new_wrapped_run_single_turn
@wraps(turn_preparation.get_model)
def new_wrapped_get_model(
agent: "agents.Agent", run_config: "agents.RunConfig"
) -> "agents.Model":
return _get_model(turn_preparation.get_model, agent, run_config)

@wraps(run_loop.run_single_turn_streamed)
async def new_wrapped_run_single_turn_streamed(
*args: "Any", **kwargs: "Any"
) -> "SingleStepResult":
return await _run_single_turn_streamed(
run_loop.run_single_turn_streamed, *args, **kwargs
)
agents.run_internal.run_loop.get_model = new_wrapped_get_model

agents.run.run_single_turn_streamed = new_wrapped_run_single_turn_streamed
original_execute_handoffs = turn_resolution.execute_handoffs

original_execute_handoffs = turn_resolution.execute_handoffs
@wraps(original_execute_handoffs)
async def new_wrapped_execute_handoffs(
*args: "Any", **kwargs: "Any"
) -> "SingleStepResult":
return await _execute_handoffs(
original_execute_handoffs, *args, **kwargs
)

@wraps(original_execute_handoffs)
async def new_wrapped_execute_handoffs(
*args: "Any", **kwargs: "Any"
) -> "SingleStepResult":
return await _execute_handoffs(
original_execute_handoffs, *args, **kwargs
agents.run_internal.turn_resolution.execute_handoffs = (
new_wrapped_execute_handoffs
)

Check warning on line 159 in sentry_sdk/integrations/openai_agents/__init__.py

View check run for this annotation

@sentry/warden / warden: find-bugs

execute_handoffs patch gated on turn_preparation instead of turn_resolution

The block guarded by `if turn_preparation is not None:` (line 137) contains the patching logic for `turn_resolution.execute_handoffs` (lines 147-159). If `turn_preparation` is None but `turn_resolution` is not (e.g., a future partial refactor of the agents library), the handoffs patch is silently skipped. Conversely, if `turn_preparation` is not None but `turn_resolution` is None, accessing `turn_resolution.execute_handoffs` will raise AttributeError on None and crash setup_once(). The handoffs patch should be moved into the `if turn_resolution is not None:` block.
Comment thread
alexander-alderman-webb marked this conversation as resolved.

agents.run_internal.turn_resolution.execute_handoffs = (
new_wrapped_execute_handoffs
)
if turn_resolution is not None:
original_execute_final_output = turn_resolution.execute_final_output

original_execute_final_output = turn_resolution.execute_final_output
@wraps(turn_resolution.execute_final_output)
async def new_wrapped_final_output(
*args: "Any", **kwargs: "Any"
) -> "SingleStepResult":
return await _execute_final_output(
original_execute_final_output, *args, **kwargs
)

@wraps(turn_resolution.execute_final_output)
async def new_wrapped_final_output(
*args: "Any", **kwargs: "Any"
) -> "SingleStepResult":
return await _execute_final_output(
original_execute_final_output, *args, **kwargs
agents.run_internal.turn_resolution.execute_final_output = (
new_wrapped_final_output
)

agents.run_internal.turn_resolution.execute_final_output = (
new_wrapped_final_output
)

return

original_get_all_tools = AgentRunner._get_all_tools
Expand Down
Loading