Skip to content

Commit 5c59668

Browse files
committed
Bring back handoff span
1 parent 99ccbee commit 5c59668

File tree

3 files changed

+61
-9
lines changed

3 files changed

+61
-9
lines changed

sentry_sdk/integrations/openai_agents/patches/runner.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
invoke_agent_span,
1111
update_invoke_agent_span,
1212
)
13+
from ..utils import _wrap_hooks
1314

1415
from typing import TYPE_CHECKING
1516

@@ -36,6 +37,7 @@ async def async_wrapper(cls, *args, **kwargs):
3637
# type: (agents.Runner, *Any, **Any) -> Any
3738
agent = args[0]
3839
with agent_workflow_span(agent) as span:
40+
kwargs["hooks"] = _wrap_hooks(kwargs.get("hooks"))
3941
result = await original_func(*args, **kwargs)
4042
update_agent_workflow_span(span, agent, result)
4143

@@ -46,6 +48,7 @@ async def async_wrapper(cls, *args, **kwargs):
4648
)
4749
def sync_wrapper(cls, *args, **kwargs):
4850
# type: (agents.Runner, *Any, **Any) -> Any
51+
kwargs["hooks"] = _wrap_hooks(kwargs.get("hooks"))
4952
# The sync version (.run_sync()) is just a wrapper around the async version (.run())
5053
return original_func(*args, **kwargs)
5154

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import sentry_sdk
22
from sentry_sdk.consts import OP, SPANDATA
33

4+
from ..consts import SPAN_ORIGIN
5+
46
from typing import TYPE_CHECKING
57

68
if TYPE_CHECKING:
@@ -9,12 +11,9 @@
911

1012
def handoff_span(context, from_agent, to_agent):
1113
# type: (agents.RunContextWrapper, agents.Agent, agents.Agent) -> None
12-
current_span = sentry_sdk.get_current_span()
13-
if current_span:
14-
with current_span.start_child(
15-
op=OP.GEN_AI_HANDOFF,
16-
name=f"handoff from {from_agent.name} to {to_agent.name}",
17-
) as span:
18-
span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "handoff")
19-
20-
current_span.__exit__(None, None, None)
14+
with sentry_sdk.start_span(
15+
op=OP.GEN_AI_HANDOFF,
16+
name=f"handoff from {from_agent.name} to {to_agent.name}",
17+
origin=SPAN_ORIGIN,
18+
) as span:
19+
span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "handoff")

sentry_sdk/integrations/openai_agents/utils.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from functools import wraps
12
import sentry_sdk
23
from sentry_sdk.consts import SPANDATA
34
from sentry_sdk.integrations import DidNotEnable
@@ -155,3 +156,52 @@ def _set_output_data(span, result):
155156

156157
if len(output_messages["response"]) > 0:
157158
span.set_data(SPANDATA.GEN_AI_RESPONSE_TEXT, output_messages["response"])
159+
160+
161+
def _create_hook_wrapper(original_hook, sentry_hook):
162+
# type: (Callable[..., Any], Callable[..., Any]) -> Callable[..., Any]
163+
@wraps(original_hook)
164+
async def async_wrapper(*args, **kwargs):
165+
# type: (*Any, **Any) -> Any
166+
await sentry_hook(*args, **kwargs)
167+
return await original_hook(*args, **kwargs)
168+
169+
return async_wrapper
170+
171+
172+
def _wrap_hooks(hooks):
173+
# type: (agents.RunHooks) -> agents.RunHooks
174+
"""
175+
Our integration uses RunHooks to create spans. This function will either
176+
enable our SentryRunHooks or if the users has given custom RunHooks wrap
177+
them so the Sentry hooks and the users hooks are both called
178+
"""
179+
import ipdb
180+
181+
ipdb.set_trace()
182+
from .run_hooks import SentryRunHooks
183+
184+
sentry_hooks = SentryRunHooks()
185+
186+
if hooks is None:
187+
return sentry_hooks
188+
189+
wrapped_hooks = type("SentryWrappedHooks", (hooks.__class__,), {})
190+
191+
# Wrap all methods from RunHooks
192+
for method_name in dir(agents.RunHooks):
193+
if method_name.startswith("on_"):
194+
original_method = getattr(hooks, method_name)
195+
# Only wrap if the method exists in SentryRunHooks
196+
try:
197+
sentry_method = getattr(sentry_hooks, method_name)
198+
setattr(
199+
wrapped_hooks,
200+
method_name,
201+
_create_hook_wrapper(original_method, sentry_method),
202+
)
203+
except AttributeError:
204+
# If method doesn't exist in SentryRunHooks, just use the original method
205+
setattr(wrapped_hooks, method_name, original_method)
206+
207+
return wrapped_hooks()

0 commit comments

Comments
 (0)