Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions sentry_sdk/integrations/openai_agents/patches/agent_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ def _patch_agent_run():
original_execute_handoffs = agents._run_impl.RunImpl.execute_handoffs
original_execute_final_output = agents._run_impl.RunImpl.execute_final_output

def _start_invoke_agent_span(context_wrapper, agent):
# type: (agents.RunContextWrapper, agents.Agent) -> None
def _start_invoke_agent_span(context_wrapper, agent, kwargs):
# type: (agents.RunContextWrapper, agents.Agent, dict[str, Any]) -> None
"""Start an agent invocation span"""
# Store the agent on the context wrapper so we can access it later
context_wrapper._sentry_current_agent = agent
invoke_agent_span(context_wrapper, agent)
invoke_agent_span(context_wrapper, agent, kwargs)

def _end_invoke_agent_span(context_wrapper, agent, output=None):
# type: (agents.RunContextWrapper, agents.Agent, Optional[Any]) -> None
Expand Down Expand Up @@ -72,7 +72,7 @@ async def patched_run_single_turn(cls, *args, **kwargs):
if current_agent and current_agent != agent:
_end_invoke_agent_span(context_wrapper, current_agent)

_start_invoke_agent_span(context_wrapper, agent)
_start_invoke_agent_span(context_wrapper, agent, kwargs)

# Call original method with all the correct parameters
result = await original_run_single_turn(*args, **kwargs)
Expand Down
53 changes: 48 additions & 5 deletions sentry_sdk/integrations/openai_agents/spans/invoke_agent.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import sentry_sdk
from sentry_sdk.ai.utils import set_data_normalized
from sentry_sdk.consts import OP, SPANDATA
from sentry_sdk.scope import should_send_default_pii
from sentry_sdk.utils import safe_serialize

from ..consts import SPAN_ORIGIN
from ..utils import _set_agent_data
Expand All @@ -11,8 +14,8 @@
from typing import Any


def invoke_agent_span(context, agent):
# type: (agents.RunContextWrapper, agents.Agent) -> sentry_sdk.tracing.Span
def invoke_agent_span(context, agent, kwargs):
# type: (agents.RunContextWrapper, agents.Agent, dict[str, Any]) -> sentry_sdk.tracing.Span
span = sentry_sdk.start_span(
op=OP.GEN_AI_INVOKE_AGENT,
name=f"invoke_agent {agent.name}",
Expand All @@ -22,13 +25,53 @@ def invoke_agent_span(context, agent):

span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "invoke_agent")

if should_send_default_pii():
messages = []
if agent.instructions:
message = (
agent.instructions
if isinstance(agent.instructions, str)
else safe_serialize(agent.instructions)
)
messages.append(
{
"content": [{"text": message, "type": "text"}],
"role": "system",
}
)

original_input = kwargs.get("original_input")
if original_input is not None:
message = (
original_input
if isinstance(original_input, str)
else safe_serialize(original_input)
)
messages.append(
{
"content": [{"text": message, "type": "text"}],
"role": "user",
}
)

if len(messages) > 0:
set_data_normalized(
span, SPANDATA.GEN_AI_REQUEST_MESSAGES, messages, unpack=False
)

_set_agent_data(span, agent)

return span


def update_invoke_agent_span(context, agent, output):
# type: (agents.RunContextWrapper, agents.Agent, Any) -> None
current_span = sentry_sdk.get_current_span()
if current_span:
current_span.__exit__(None, None, None)
span = sentry_sdk.get_current_span()

if span:
if should_send_default_pii():
set_data_normalized(
span, SPANDATA.GEN_AI_RESPONSE_TEXT, output, unpack=False
)

span.__exit__(None, None, None)
16 changes: 16 additions & 0 deletions tests/integrations/openai_agents/test_openai_agents.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ async def test_agent_invocation_span(
sentry_init(
integrations=[OpenAIAgentsIntegration()],
traces_sample_rate=1.0,
send_default_pii=True,
)

events = capture_events()
Expand All @@ -134,6 +135,21 @@ async def test_agent_invocation_span(
assert transaction["contexts"]["trace"]["origin"] == "auto.ai.openai_agents"

assert invoke_agent_span["description"] == "invoke_agent test_agent"
assert invoke_agent_span["data"]["gen_ai.request.messages"] == safe_serialize(
[
{
"content": [
{"text": "You are a helpful test assistant.", "type": "text"}
],
"role": "system",
},
{"content": [{"text": "Test input", "type": "text"}], "role": "user"},
]
)
assert (
invoke_agent_span["data"]["gen_ai.response.text"]
== "Hello, how can I help you?"
)
assert invoke_agent_span["data"]["gen_ai.operation.name"] == "invoke_agent"
assert invoke_agent_span["data"]["gen_ai.system"] == "openai"
assert invoke_agent_span["data"]["gen_ai.agent.name"] == "test_agent"
Expand Down