From fac75ed44b1dc1c9c9bb276cdb3b2abdfdec4c17 Mon Sep 17 00:00:00 2001 From: Anton Pirker Date: Wed, 10 Sep 2025 11:43:49 +0200 Subject: [PATCH 1/4] Add input and output to invoke agent span. --- .../openai_agents/patches/agent_run.py | 8 ++-- .../openai_agents/spans/invoke_agent.py | 41 ++++++++++++++++--- 2 files changed, 40 insertions(+), 9 deletions(-) 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..0d36ae959b 100644 --- a/sentry_sdk/integrations/openai_agents/spans/invoke_agent.py +++ b/sentry_sdk/integrations/openai_agents/spans/invoke_agent.py @@ -1,5 +1,7 @@ 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 ..consts import SPAN_ORIGIN from ..utils import _set_agent_data @@ -11,8 +13,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 +24,29 @@ 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: + messages.append( + { + "content": [{"text": agent.instructions, "type": "text"}], + "role": "system", + } + ) + + if "original_input" in kwargs and kwargs["original_input"] is not None: + messages.append( + { + "content": [{"text": kwargs["original_input"], "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 +54,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) From 86ee82425df41c1179bc59307a009523ac5c95be Mon Sep 17 00:00:00 2001 From: Anton Pirker Date: Wed, 10 Sep 2025 11:47:42 +0200 Subject: [PATCH 2/4] updated tests --- tests/integrations/openai_agents/test_openai_agents.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/integrations/openai_agents/test_openai_agents.py b/tests/integrations/openai_agents/test_openai_agents.py index fab8d9e13f..aaee9016ab 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,14 @@ 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"] + == '[{"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" From d0776336934e275e5d39f174e1e2375e12b23a0e Mon Sep 17 00:00:00 2001 From: Anton Pirker Date: Wed, 10 Sep 2025 12:00:05 +0200 Subject: [PATCH 3/4] improve --- .../integrations/openai_agents/spans/invoke_agent.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/sentry_sdk/integrations/openai_agents/spans/invoke_agent.py b/sentry_sdk/integrations/openai_agents/spans/invoke_agent.py index 0d36ae959b..ebce5e647b 100644 --- a/sentry_sdk/integrations/openai_agents/spans/invoke_agent.py +++ b/sentry_sdk/integrations/openai_agents/spans/invoke_agent.py @@ -2,6 +2,7 @@ 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 @@ -29,15 +30,20 @@ def invoke_agent_span(context, agent, kwargs): if agent.instructions: messages.append( { - "content": [{"text": agent.instructions, "type": "text"}], + "content": [ + {"text": safe_serialize(agent.instructions), "type": "text"} + ], "role": "system", } ) - if "original_input" in kwargs and kwargs["original_input"] is not None: + original_input = kwargs.get("original_input") + if original_input is not None: messages.append( { - "content": [{"text": kwargs["original_input"], "type": "text"}], + "content": [ + {"text": safe_serialize(original_input), "type": "text"} + ], "role": "user", } ) From 224a3da4e146872fd2aa7efee03ca4d0b6328657 Mon Sep 17 00:00:00 2001 From: Anton Pirker Date: Wed, 10 Sep 2025 12:19:23 +0200 Subject: [PATCH 4/4] fix --- .../openai_agents/spans/invoke_agent.py | 18 ++++++++++++------ .../openai_agents/test_openai_agents.py | 13 ++++++++++--- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/sentry_sdk/integrations/openai_agents/spans/invoke_agent.py b/sentry_sdk/integrations/openai_agents/spans/invoke_agent.py index ebce5e647b..d76d39f338 100644 --- a/sentry_sdk/integrations/openai_agents/spans/invoke_agent.py +++ b/sentry_sdk/integrations/openai_agents/spans/invoke_agent.py @@ -28,22 +28,28 @@ def invoke_agent_span(context, agent, kwargs): 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": safe_serialize(agent.instructions), "type": "text"} - ], + "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": safe_serialize(original_input), "type": "text"} - ], + "content": [{"text": message, "type": "text"}], "role": "user", } ) diff --git a/tests/integrations/openai_agents/test_openai_agents.py b/tests/integrations/openai_agents/test_openai_agents.py index aaee9016ab..047b919213 100644 --- a/tests/integrations/openai_agents/test_openai_agents.py +++ b/tests/integrations/openai_agents/test_openai_agents.py @@ -135,9 +135,16 @@ 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"] - == '[{"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.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"]