openai_agents: tool wrapper is re-applied on every turn
@alexander-alderman-webb 已经在做这个了。
开始于 2026年8月31日。
评估
这个 Issue 还没有评估数据。
描述
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.
- 主要语言
- Python
- 星标
- 2.2k
- 派生
- 672
- 平均合并
- 22 小时 47 分钟
- 30 天内合并 PR
- 224
贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
getsentry/sentry-python 的其他 Issue
-
Python
难度 2/5 1-3 小时 新手友好度 65/100
getsentry/sentry-python#7569 · 1 条评论 ·
-
Python
难度 1/5 1 小时以内 新手友好度 85/100
getsentry/sentry-python#7568 · 2 条评论 ·
-
Python
难度 2/5 1-3 小时 新手友好度 65/100
getsentry/sentry-python#7567 · 1 条评论 ·
-
难度 2/5 1-3 小时 新手友好度 78/100
getsentry/sentry-python#7543 · 2 条评论 · 已指派 1 人 ·
-
Python
难度 2/5 1-3 小时 新手友好度 68/100
getsentry/sentry-python#6992 · 1 条评论 ·
查看 getsentry/sentry-python 的全部 Issue
相似的 Issue
-
enhancement
难度 2/5 1-3 小时 新手友好度 70/100
canonical/paas-charm#368 · 1 条评论 ·
-
难度 2/5 1-3 小时 新手友好度 75/100
-
tech debt
难度 2/5 1-3 小时 新手友好度 75/100
-
难度 1/5 1 小时以内 新手友好度 90/100
StevenBlack/hosts#3256 ·
-
难度 1/5 1 小时以内 新手友好度 90/100
qualcomm/qai-appbuilder#275 ·