-
Notifications
You must be signed in to change notification settings - Fork 647
ref(openai-agents): Use first class agent hooks when available #7029
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
12c28ac
d982006
0fa5385
4501d34
47a1914
b9c3cb0
1f1e5d3
881ff72
9822982
537e996
78d5d6f
364b172
bb76a15
4fd1a4f
3cef85d
83de0ca
ed6b6d2
dffd885
eb9bd68
f60881e
0e7155a
b273a1d
b5ae6b3
9c8074d
573480b
9210726
d555e9c
517d837
8eb6c80
002ec0a
bca6ba6
9fe9910
01fd3b1
0759b8b
a0adffd
8343310
c9a3196
327a4d8
2f01eb7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,6 +15,7 @@ | |
| if TYPE_CHECKING: | ||
| from typing import Any, Awaitable, Callable, Optional, Union | ||
|
|
||
| from agents import TResponseInputItem | ||
| from agents.run_internal.run_steps import SingleStepResult | ||
|
|
||
| from sentry_sdk.tracing import Span | ||
|
|
@@ -49,7 +50,7 @@ | |
| context_wrapper: "agents.RunContextWrapper", | ||
| agent: "agents.Agent", | ||
| should_run_agent_start_hooks: bool, | ||
| span_kwargs: "dict[str, Any]", | ||
| turn_input: "Optional[list[TResponseInputItem]]", | ||
| is_streaming: bool = False, | ||
| ) -> "Optional[Union[Span, StreamedSpan]]": | ||
| """ | ||
|
|
@@ -68,14 +69,14 @@ | |
| span = getattr(context_wrapper, "_sentry_agent_span", None) | ||
| if span: | ||
| update_invoke_agent_span( | ||
| span=span, context=context_wrapper, agent=agent | ||
| span=span, usage=context_wrapper.usage, agent=agent | ||
| ) | ||
| span.__exit__(None, None, None) | ||
| delattr(context_wrapper, "_sentry_agent_span") | ||
|
|
||
| # Store the agent on the context wrapper so we can access it later | ||
| context_wrapper._sentry_current_agent = agent | ||
| span = invoke_agent_span(context_wrapper, agent, span_kwargs) | ||
| span = invoke_agent_span(agent, turn_input) | ||
| context_wrapper._sentry_agent_span = span | ||
| agent._sentry_agent_span = span | ||
|
|
||
|
|
@@ -92,6 +93,7 @@ | |
|
|
||
| async def _run_single_turn( | ||
| original_run_single_turn: "Callable[..., Awaitable[SingleStepResult]]", | ||
| use_run_hooks: "bool", | ||
| *args: "Any", | ||
| **kwargs: "Any", | ||
| ) -> "SingleStepResult": | ||
|
|
@@ -107,39 +109,56 @@ | |
| if bindings is not None | ||
| else kwargs.get("agent") | ||
| ) | ||
| context_wrapper = kwargs.get("context_wrapper") | ||
| should_run_agent_start_hooks = kwargs.get("should_run_agent_start_hooks", False) | ||
|
|
||
| span = _maybe_start_agent_span( | ||
| context_wrapper, agent, should_run_agent_start_hooks, kwargs | ||
| ) | ||
| context_wrapper: "agents.RunContextWrapper[Any]" = kwargs.get("context_wrapper") | ||
| if not use_run_hooks: | ||
| should_run_agent_start_hooks = kwargs.get("should_run_agent_start_hooks", False) | ||
|
|
||
| if ( | ||
| span is None | ||
| or (isinstance(span, StreamedSpan) and span.end_timestamp is not None) | ||
| or (not isinstance(span, StreamedSpan) and span.timestamp is not None) | ||
| ): | ||
| return await original_run_single_turn(*args, **kwargs) | ||
| span = _maybe_start_agent_span( | ||
| context_wrapper, | ||
| agent, | ||
| should_run_agent_start_hooks, | ||
| kwargs.get("input"), | ||
| ) | ||
|
|
||
| if ( | ||
| span is None | ||
| or (isinstance(span, StreamedSpan) and span.end_timestamp is not None) | ||
| or (not isinstance(span, StreamedSpan) and span.timestamp is not None) | ||
| ): | ||
| return await original_run_single_turn(*args, **kwargs) | ||
|
|
||
| try: | ||
| result = await original_run_single_turn(*args, **kwargs) | ||
| except Exception: | ||
| exc_info = sys.exc_info() | ||
| with capture_internal_exceptions(): | ||
| span = getattr(context_wrapper, "_sentry_agent_span", None) | ||
| if span: | ||
| update_invoke_agent_span( | ||
| span=span, context=context_wrapper, agent=agent | ||
| ) | ||
| span.__exit__(*exc_info) | ||
| delattr(context_wrapper, "_sentry_agent_span") | ||
| if use_run_hooks: | ||
| run_hooks = kwargs.get("hooks") | ||
| if run_hooks is not None: | ||
|
Comment on lines
+136
to
+138
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To confirm my understanding of what's happening here - are run hooks something that are passed in by users (which is why they could potentially be |
||
| span = getattr(run_hooks, "_sentry_invoke_agent_span", None) | ||
|
alexander-alderman-webb marked this conversation as resolved.
|
||
| if span is not None: | ||
| update_invoke_agent_span( | ||
| span=span, usage=context_wrapper.usage, agent=agent | ||
|
alexander-alderman-webb marked this conversation as resolved.
|
||
| ) | ||
| del run_hooks._sentry_invoke_agent_span | ||
| span.__exit__(*exc_info) | ||
| else: | ||
| span = getattr(context_wrapper, "_sentry_agent_span", None) | ||
| if span: | ||
| update_invoke_agent_span( | ||
| span=span, usage=context_wrapper.usage, agent=agent | ||
| ) | ||
| span.__exit__(*exc_info) | ||
| delattr(context_wrapper, "_sentry_agent_span") | ||
| reraise(*exc_info) | ||
|
|
||
| return result | ||
|
|
||
|
|
||
| async def _run_single_turn_streamed( | ||
| original_run_single_turn_streamed: "Callable[..., Awaitable[SingleStepResult]]", | ||
| use_run_hooks: "bool", | ||
| *args: "Any", | ||
| **kwargs: "Any", | ||
| ) -> "SingleStepResult": | ||
|
|
@@ -181,42 +200,59 @@ | |
| args[1] if len(args) > 1 else kwargs.get("bindings", kwargs.get("agent")) | ||
| ) | ||
| agent = getattr(agent_or_bindings, "public_agent", agent_or_bindings) | ||
| context_wrapper = args[3] if len(args) > 3 else kwargs.get("context_wrapper") | ||
| should_run_agent_start_hooks = bool( | ||
| args[5] if len(args) > 5 else kwargs.get("should_run_agent_start_hooks", False) | ||
|
|
||
| context_wrapper: "agents.RunContextWrapper[Any]" = ( | ||
| args[3] if len(args) > 3 else kwargs.get("context_wrapper") | ||
| ) | ||
| if not use_run_hooks: | ||
| should_run_agent_start_hooks = bool( | ||
| args[5] | ||
| if len(args) > 5 | ||
| else kwargs.get("should_run_agent_start_hooks", False) | ||
| ) | ||
|
|
||
| span_kwargs: "dict[str, Any]" = {} | ||
| if streamed_result and hasattr(streamed_result, "input"): | ||
| span_kwargs["original_input"] = streamed_result.input | ||
| span_kwargs: "dict[str, Any]" = {} | ||
| if streamed_result and hasattr(streamed_result, "input"): | ||
| span_kwargs["original_input"] = streamed_result.input | ||
|
|
||
| span = _maybe_start_agent_span( | ||
| context_wrapper, | ||
| agent, | ||
| should_run_agent_start_hooks, | ||
| span_kwargs, | ||
| is_streaming=True, | ||
| ) | ||
| span = _maybe_start_agent_span( | ||
| context_wrapper, | ||
| agent, | ||
| should_run_agent_start_hooks, | ||
| getattr(streamed_result, "input", None), | ||
| is_streaming=True, | ||
| ) | ||
|
|
||
| if ( | ||
| span is None | ||
| or (isinstance(span, StreamedSpan) and span.end_timestamp is not None) | ||
| or (not isinstance(span, StreamedSpan) and span.timestamp is not None) | ||
| ): | ||
| return await original_run_single_turn_streamed(*args, **kwargs) | ||
| if ( | ||
| span is None | ||
| or (isinstance(span, StreamedSpan) and span.end_timestamp is not None) | ||
| or (not isinstance(span, StreamedSpan) and span.timestamp is not None) | ||
| ): | ||
| return await original_run_single_turn_streamed(*args, **kwargs) | ||
|
|
||
| try: | ||
| result = await original_run_single_turn_streamed(*args, **kwargs) | ||
| except Exception: | ||
| exc_info = sys.exc_info() | ||
| with capture_internal_exceptions(): | ||
| span = getattr(context_wrapper, "_sentry_agent_span", None) | ||
| if span: | ||
| update_invoke_agent_span( | ||
| span=span, context=context_wrapper, agent=agent | ||
| ) | ||
| span.__exit__(*exc_info) | ||
| delattr(context_wrapper, "_sentry_agent_span") | ||
| if use_run_hooks: | ||
| run_hooks = args[2] if len(args) > 2 else kwargs.get("hooks") | ||
| if run_hooks is not None: | ||
| span = getattr(run_hooks, "_sentry_invoke_agent_span", None) | ||
|
Check warning on line 241 in sentry_sdk/integrations/openai_agents/patches/agent_run.py
|
||
| if span is not None: | ||
| update_invoke_agent_span( | ||
| span=span, usage=context_wrapper.usage, agent=agent | ||
| ) | ||
| del run_hooks._sentry_invoke_agent_span | ||
| span.__exit__(*exc_info) | ||
| else: | ||
| span = getattr(context_wrapper, "_sentry_agent_span", None) | ||
| if span: | ||
|
alexander-alderman-webb marked this conversation as resolved.
|
||
| update_invoke_agent_span( | ||
| span=span, usage=context_wrapper.usage, agent=agent | ||
| ) | ||
| span.__exit__(*exc_info) | ||
| delattr(context_wrapper, "_sentry_agent_span") | ||
| _close_streaming_workflow_span(agent) | ||
| reraise(*exc_info) | ||
|
|
||
|
|
@@ -225,6 +261,7 @@ | |
|
|
||
| async def _execute_handoffs( | ||
| original_execute_handoffs: "Callable[..., SingleStepResult]", | ||
| use_run_hooks: "bool", | ||
| *args: "Any", | ||
| **kwargs: "Any", | ||
| ) -> "SingleStepResult": | ||
|
|
@@ -241,12 +278,17 @@ | |
| agent = kwargs.get("public_agent", kwargs.get("agent")) | ||
|
|
||
| # Create Sentry handoff span for the first handoff (agents library only processes the first one) | ||
| if run_handoffs: | ||
| if not use_run_hooks and run_handoffs: | ||
| first_handoff = run_handoffs[0] | ||
| handoff_agent_name = first_handoff.handoff.agent_name | ||
| handoff_span(context_wrapper, agent, handoff_agent_name) | ||
|
|
||
| if not agent or not context_wrapper or not _has_active_agent_span(context_wrapper): | ||
| if ( | ||
| use_run_hooks | ||
| or not agent | ||
| or not context_wrapper | ||
| or not _has_active_agent_span(context_wrapper) | ||
| ): | ||
|
sentry[bot] marked this conversation as resolved.
alexander-alderman-webb marked this conversation as resolved.
|
||
| # Call original method with all parameters | ||
| try: | ||
| return await original_execute_handoffs(*args, **kwargs) | ||
|
|
@@ -266,15 +308,15 @@ | |
| span = getattr(context_wrapper, "_sentry_agent_span", None) | ||
| if span: | ||
| update_invoke_agent_span( | ||
| span=span, context=context_wrapper, agent=agent | ||
| span=span, usage=context_wrapper.usage, agent=agent | ||
| ) | ||
| span.__exit__(*exc_info) | ||
| delattr(context_wrapper, "_sentry_agent_span") | ||
| reraise(*exc_info) | ||
|
|
||
| span = getattr(context_wrapper, "_sentry_agent_span", None) | ||
| if span: | ||
| update_invoke_agent_span(span=span, context=context_wrapper, agent=agent) | ||
| update_invoke_agent_span(span=span, usage=context_wrapper.usage, agent=agent) | ||
| span.__exit__(None, None, None) | ||
| delattr(context_wrapper, "_sentry_agent_span") | ||
|
|
||
|
|
@@ -315,7 +357,10 @@ | |
| span = getattr(context_wrapper, "_sentry_agent_span", None) | ||
| if span: | ||
| update_invoke_agent_span( | ||
| span=span, context=context_wrapper, agent=agent, output=final_output | ||
| span=span, | ||
| usage=context_wrapper.usage, | ||
| agent=agent, | ||
| output=final_output, | ||
| ) | ||
| span.__exit__(*exc_info) | ||
| delattr(context_wrapper, "_sentry_agent_span") | ||
|
|
@@ -324,7 +369,7 @@ | |
| span = getattr(context_wrapper, "_sentry_agent_span", None) | ||
| if span: | ||
| update_invoke_agent_span( | ||
| span=span, context=context_wrapper, agent=agent, output=final_output | ||
| span=span, usage=context_wrapper.usage, agent=agent, output=final_output | ||
| ) | ||
| span.__exit__(None, None, None) | ||
| delattr(context_wrapper, "_sentry_agent_span") | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.