openai_agents: tool wrapper is re-applied on every turn
@alexander-alderman-webb ci sta già lavorando.
Dal 31/8/2026.
Valutazione
Questa issue non è ancora stata valutata.
Descrizione
How do you use Sentry?
Sentry SaaS (sentry.io)
Version
2.68.1
Steps to Reproduce
We ran into the tool-rebuild problem that #6961 fixed. Our agent crash-looped on UserError: ToolSearchTool() requires at least one searchable Responses surface, because defer_loading came back False on every tool. Moving to 2.67.0 fixed it for us, and the switch to RunHooks in #6994 looks like the right call.
While reading that fix I noticed one thing still worth reporting in patches/tools.py. It now sets on_invoke_tool in place:
tool.on_invoke_tool = create_wrapped_invoke(tool, original_on_invoke)
get_all_tools returns the agent's own tool objects and runs once per turn, so the wrapper goes on again on each turn and the previous one stays underneath it.
That file is only wired up for openai-agents < 0.3.2, so this repro calls _get_all_tools directly with a stub standing in for the original:
import asyncio, sentry_sdk
sentry_sdk.init(dsn="https://a@b.ingest.sentry.io/1", traces_sample_rate=1.0)
from sentry_sdk.integrations.openai_agents.patches.tools import _get_all_tools
from agents import Agent, FunctionTool
async def invoke(ctx, args): return "ok"
tool = FunctionTool(
name="t", description="d",
params_json_schema={"type": "object", "properties": {}, "additionalProperties": False},
on_invoke_tool=invoke,
)
agent = Agent(name="a", tools=[tool])
async def original(a, c): return list(a.tools) # stands in for get_all_tools
async def main():
for turn in range(1, 6):
await _get_all_tools(original, agent, None)
f, depth = agent.tools[0].on_invoke_tool, 0
while hasattr(f, "__wrapped__"):
f, depth = f.__wrapped__, depth + 1
print(f"after turn {turn}: wrapper depth = {depth}")
asyncio.run(main())
Expected Result
A tool gets wrapped once, however many turns a run takes, and one tool call produces one gen_ai.execute_tool span.
Actual Result
after turn 1: wrapper depth = 1
after turn 2: wrapper depth = 2
after turn 3: wrapper depth = 3
after turn 4: wrapper depth = 4
after turn 5: wrapper depth = 5
A tool call on turn N opens N nested gen_ai.execute_tool spans, and the wrapping stays on the caller's Agent after the run.
_patch_run_hooks in patches/runner.py already guards against this with _sentry_is_patched. The same flag on the tool would cover it.
Tested on Python 3.13 with openai-agents 0.17.5.
- Lingua principale
- Python
- Stelle
- 2.2k
- Fork
- 672
- Merge medio
- 23h 14m
- PR unite (30g)
- 218
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di getsentry/sentry-python
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
getsentry/sentry-python#7543 · 2 commenti · 1 assegnatario ·
-
Python
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
getsentry/sentry-python#6992 · 1 commento ·
-
Improvement Python
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
getsentry/sentry-python#6970 · 1 commento ·
-
Bug Python
Difficoltà 2/5 1-3 ore Idoneità per principianti 74/100
getsentry/sentry-python#6504 · 1 commento ·
-
Improvement Python Spans
Difficoltà 2/5 1-3 ore Idoneità per principianti 85/100
getsentry/sentry-python#5833 · 1 commento ·
Tutte le issue di getsentry/sentry-python
Issue simili
-
Add: hunch Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 74/100
AbdelStark/awesome-typesafe#104 ·
-
enhancement
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
DiamondLightSource/dodal#2211 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
openml/openml-python#1749 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
sipyourdrink-ltd/bernstein#6191 ·