diff --git a/sentry_sdk/integrations/openai_agents/patches/agent_run.py b/sentry_sdk/integrations/openai_agents/patches/agent_run.py index 29002f6619..5473915b48 100644 --- a/sentry_sdk/integrations/openai_agents/patches/agent_run.py +++ b/sentry_sdk/integrations/openai_agents/patches/agent_run.py @@ -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 @@ -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) diff --git a/sentry_sdk/integrations/openai_agents/spans/invoke_agent.py b/sentry_sdk/integrations/openai_agents/spans/invoke_agent.py index 549ade1246..d76d39f338 100644 --- a/sentry_sdk/integrations/openai_agents/spans/invoke_agent.py +++ b/sentry_sdk/integrations/openai_agents/spans/invoke_agent.py @@ -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 @@ -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}", @@ -22,6 +25,40 @@ 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 @@ -29,6 +66,12 @@ def invoke_agent_span(context, agent): 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) diff --git a/tests/integrations/openai_agents/test_openai_agents.py b/tests/integrations/openai_agents/test_openai_agents.py index fab8d9e13f..047b919213 100644 --- a/tests/integrations/openai_agents/test_openai_agents.py +++ b/tests/integrations/openai_agents/test_openai_agents.py @@ -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() @@ -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"