Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

openai_agents: tool wrapper is re-applied on every turn

オープン
#7,301 コメント 2 件 リアクション 0 件 担当者 1 名 GitHub で見る

@alexander-alderman-webb がすでに取り組んでいます。

2026年8月31日 から。

評価

この issue はまだ評価されていません。

説明

Bug Python Spans
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分
マージ済み PR(30日)
224

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

getsentry/sentry-python のほかの issue

getsentry/sentry-python の issue をすべて見る

似ている issue

Python の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。