From d1f6f8d63cfaf52ef0876a2c260b3abc0e8f1977 Mon Sep 17 00:00:00 2001 From: Alexander Alderman Webb Date: Wed, 8 Apr 2026 10:55:30 +0200 Subject: [PATCH 1/4] fix(pydantic-ai): Determine if response is streamed based on the method --- sentry_sdk/integrations/pydantic_ai/patches/graph_nodes.py | 5 +++++ sentry_sdk/integrations/pydantic_ai/spans/ai_client.py | 4 ---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/sentry_sdk/integrations/pydantic_ai/patches/graph_nodes.py b/sentry_sdk/integrations/pydantic_ai/patches/graph_nodes.py index afb10395f4..221be25a5f 100644 --- a/sentry_sdk/integrations/pydantic_ai/patches/graph_nodes.py +++ b/sentry_sdk/integrations/pydantic_ai/patches/graph_nodes.py @@ -2,6 +2,7 @@ from functools import wraps from sentry_sdk.integrations import DidNotEnable +from sentry_sdk.consts import SPANDATA from ..spans import ( ai_client_span, @@ -60,6 +61,8 @@ async def wrapped_model_request_run(self: "Any", ctx: "Any") -> "Any": messages, model, model_settings = _extract_span_data(self, ctx) with ai_client_span(messages, None, model, model_settings) as span: + span.set_data(SPANDATA.GEN_AI_RESPONSE_STREAMING, True) + result = await original_model_request_run(self, ctx) # Extract response from result if available @@ -87,6 +90,8 @@ async def wrapped_model_request_stream(self: "Any", ctx: "Any") -> "Any": # Create chat span for streaming request with ai_client_span(messages, None, model, model_settings) as span: + span.set_data(SPANDATA.GEN_AI_RESPONSE_STREAMING, False) + # Call the original stream method async with original_stream_method(self, ctx) as stream: yield stream diff --git a/sentry_sdk/integrations/pydantic_ai/spans/ai_client.py b/sentry_sdk/integrations/pydantic_ai/spans/ai_client.py index dc95acad45..e376f8097c 100644 --- a/sentry_sdk/integrations/pydantic_ai/spans/ai_client.py +++ b/sentry_sdk/integrations/pydantic_ai/spans/ai_client.py @@ -17,7 +17,6 @@ _should_send_prompts, _get_model_name, get_current_agent, - get_is_streaming, ) from .utils import ( _serialize_binary_content_item, @@ -264,9 +263,6 @@ def ai_client_span( _set_agent_data(span, agent) _set_model_data(span, model, model_settings) - # Set streaming flag from contextvar - span.set_data(SPANDATA.GEN_AI_RESPONSE_STREAMING, get_is_streaming()) - # Add available tools if agent is available agent_obj = agent or get_current_agent() _set_available_tools(span, agent_obj) From d7483fae191164595bb35491dba4e46bdef4b6fb Mon Sep 17 00:00:00 2001 From: Alexander Alderman Webb Date: Wed, 8 Apr 2026 10:58:01 +0200 Subject: [PATCH 2/4] remove function --- sentry_sdk/integrations/pydantic_ai/utils.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/sentry_sdk/integrations/pydantic_ai/utils.py b/sentry_sdk/integrations/pydantic_ai/utils.py index 62d36fb912..6d6d1431cf 100644 --- a/sentry_sdk/integrations/pydantic_ai/utils.py +++ b/sentry_sdk/integrations/pydantic_ai/utils.py @@ -41,14 +41,6 @@ def get_current_agent() -> "Any": return None -def get_is_streaming() -> bool: - """Get the streaming flag from the contextvar stack.""" - stack = _agent_context_stack.get() - if stack: - return stack[-1].get("is_streaming", False) - return False - - def _should_send_prompts() -> bool: """ Check if prompts should be sent to Sentry. From 57268a9bb47f2eedbe33312b7afb09b110aefe34 Mon Sep 17 00:00:00 2001 From: Alexander Alderman Webb Date: Wed, 8 Apr 2026 11:11:59 +0200 Subject: [PATCH 3/4] flip bool values --- sentry_sdk/integrations/pydantic_ai/patches/graph_nodes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sentry_sdk/integrations/pydantic_ai/patches/graph_nodes.py b/sentry_sdk/integrations/pydantic_ai/patches/graph_nodes.py index 221be25a5f..c159a2b067 100644 --- a/sentry_sdk/integrations/pydantic_ai/patches/graph_nodes.py +++ b/sentry_sdk/integrations/pydantic_ai/patches/graph_nodes.py @@ -61,7 +61,7 @@ async def wrapped_model_request_run(self: "Any", ctx: "Any") -> "Any": messages, model, model_settings = _extract_span_data(self, ctx) with ai_client_span(messages, None, model, model_settings) as span: - span.set_data(SPANDATA.GEN_AI_RESPONSE_STREAMING, True) + span.set_data(SPANDATA.GEN_AI_RESPONSE_STREAMING, False) result = await original_model_request_run(self, ctx) @@ -90,7 +90,7 @@ async def wrapped_model_request_stream(self: "Any", ctx: "Any") -> "Any": # Create chat span for streaming request with ai_client_span(messages, None, model, model_settings) as span: - span.set_data(SPANDATA.GEN_AI_RESPONSE_STREAMING, False) + span.set_data(SPANDATA.GEN_AI_RESPONSE_STREAMING, True) # Call the original stream method async with original_stream_method(self, ctx) as stream: From d538ae2a53e67b56a2b847bb92f319d07805153d Mon Sep 17 00:00:00 2001 From: Alexander Alderman Webb Date: Wed, 8 Apr 2026 11:14:49 +0200 Subject: [PATCH 4/4] simplify context stack --- sentry_sdk/integrations/pydantic_ai/patches/agent_run.py | 4 ++-- sentry_sdk/integrations/pydantic_ai/utils.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sentry_sdk/integrations/pydantic_ai/patches/agent_run.py b/sentry_sdk/integrations/pydantic_ai/patches/agent_run.py index eaa4385834..cc6bd602b0 100644 --- a/sentry_sdk/integrations/pydantic_ai/patches/agent_run.py +++ b/sentry_sdk/integrations/pydantic_ai/patches/agent_run.py @@ -58,7 +58,7 @@ async def __aenter__(self) -> "Any": # Push agent to contextvar stack after span is successfully created and entered # This ensures proper pairing with pop_agent() in __aexit__ even if exceptions occur - push_agent(self.agent, self.is_streaming) + push_agent(self.agent) # Enter the original context manager result = await self.original_ctx_manager.__aenter__() @@ -113,7 +113,7 @@ async def wrapper(self: "Any", *args: "Any", **kwargs: "Any") -> "Any": ) as span: # Push agent to contextvar stack after span is successfully created and entered # This ensures proper pairing with pop_agent() in finally even if exceptions occur - push_agent(self, is_streaming) + push_agent(self) try: result = await original_func(self, *args, **kwargs) diff --git a/sentry_sdk/integrations/pydantic_ai/utils.py b/sentry_sdk/integrations/pydantic_ai/utils.py index 6d6d1431cf..c6dd658d20 100644 --- a/sentry_sdk/integrations/pydantic_ai/utils.py +++ b/sentry_sdk/integrations/pydantic_ai/utils.py @@ -18,10 +18,10 @@ ) -def push_agent(agent: "Any", is_streaming: bool = False) -> None: - """Push an agent context onto the stack along with its streaming flag.""" +def push_agent(agent: "Any") -> None: + """Push an agent context onto the stack.""" stack = _agent_context_stack.get().copy() - stack.append({"agent": agent, "is_streaming": is_streaming}) + stack.append(agent) _agent_context_stack.set(stack) @@ -37,7 +37,7 @@ def get_current_agent() -> "Any": """Get the current agent from the contextvar stack.""" stack = _agent_context_stack.get() if stack: - return stack[-1]["agent"] + return stack[-1] return None