From 56e5a3886512ee03525e47c4cd5e703f06b4e520 Mon Sep 17 00:00:00 2001 From: Alexander Alderman Webb Date: Mon, 5 Oct 2026 09:16:45 +0200 Subject: [PATCH] chore(pydantic-ai): Stop setting request parameters on Invoke Agent spans --- .../pydantic_ai/spans/ai_client.py | 31 ++++++++++++++++++- .../pydantic_ai/spans/invoke_agent.py | 2 +- sentry_sdk/integrations/pydantic_ai/utils.py | 31 ------------------- 3 files changed, 31 insertions(+), 33 deletions(-) diff --git a/sentry_sdk/integrations/pydantic_ai/spans/ai_client.py b/sentry_sdk/integrations/pydantic_ai/spans/ai_client.py index bd9137c39c..5dcb79fc02 100644 --- a/sentry_sdk/integrations/pydantic_ai/spans/ai_client.py +++ b/sentry_sdk/integrations/pydantic_ai/spans/ai_client.py @@ -290,7 +290,36 @@ def ai_client_context( ) _set_agent_data(context.span, agent) - _set_model_data(context.span, agent, model, model_settings) + _set_model_data(context.span, agent, model) + + # Extract model settings + settings = model_settings + if not settings and agent and hasattr(agent, "model_settings"): + settings = agent.model_settings + + if settings: + settings_map = { + "max_tokens": SPANDATA.GEN_AI_REQUEST_MAX_TOKENS, + "temperature": SPANDATA.GEN_AI_REQUEST_TEMPERATURE, + "top_p": SPANDATA.GEN_AI_REQUEST_TOP_P, + "frequency_penalty": SPANDATA.GEN_AI_REQUEST_FREQUENCY_PENALTY, + "presence_penalty": SPANDATA.GEN_AI_REQUEST_PRESENCE_PENALTY, + } + + # ModelSettings is a TypedDict (dict at runtime), so use dict access + if isinstance(settings, dict): + for setting_name, spandata_key in settings_map.items(): + value = settings.get(setting_name) + if value is not None: + context.span.set_attribute(spandata_key, value) # type: ignore[arg-type] + else: + # Fallback for object-style settings + for setting_name, spandata_key in settings_map.items(): + if hasattr(settings, setting_name): + value = getattr(settings, setting_name) + if value is not None: + context.span.set_attribute(spandata_key, value) + _set_available_tools(context.span, agent) # Set input messages (full conversation history) diff --git a/sentry_sdk/integrations/pydantic_ai/spans/invoke_agent.py b/sentry_sdk/integrations/pydantic_ai/spans/invoke_agent.py index f1aff085a6..c8422a6ec0 100644 --- a/sentry_sdk/integrations/pydantic_ai/spans/invoke_agent.py +++ b/sentry_sdk/integrations/pydantic_ai/spans/invoke_agent.py @@ -55,7 +55,7 @@ def invoke_agent_span( ) _set_agent_data(span, agent) - _set_model_data(span, agent, model, model_settings) + _set_model_data(span, agent, model) # Add user prompt and system prompts if available and prompts are enabled if not sentry_sdk.get_client().options["data_collection"]["gen_ai"]["inputs"]: diff --git a/sentry_sdk/integrations/pydantic_ai/utils.py b/sentry_sdk/integrations/pydantic_ai/utils.py index ad9fd62c05..d7273514e1 100644 --- a/sentry_sdk/integrations/pydantic_ai/utils.py +++ b/sentry_sdk/integrations/pydantic_ai/utils.py @@ -13,8 +13,6 @@ from pydantic_ai import Agent from pydantic_ai.models import AbstractModel, Model - from pydantic_ai.realtime.settings import RealtimeModelSettings - from pydantic_ai.settings import ModelSettings def _set_agent_data(span: "Span", agent: "Optional[Agent]") -> None: @@ -59,7 +57,6 @@ def _set_model_data( span: "Span", agent: "Optional[Agent]", model: "Union[Model, AbstractModel]", - model_settings: "Optional[Union[ModelSettings, RealtimeModelSettings]]", ) -> None: """Set model-related data on a span. @@ -83,34 +80,6 @@ def _set_model_data( if model_name: span.set_attribute(SPANDATA.GEN_AI_REQUEST_MODEL, model_name) - # Extract model settings - settings = model_settings - if not settings and agent and hasattr(agent, "model_settings"): - settings = agent.model_settings - - if settings: - settings_map = { - "max_tokens": SPANDATA.GEN_AI_REQUEST_MAX_TOKENS, - "temperature": SPANDATA.GEN_AI_REQUEST_TEMPERATURE, - "top_p": SPANDATA.GEN_AI_REQUEST_TOP_P, - "frequency_penalty": SPANDATA.GEN_AI_REQUEST_FREQUENCY_PENALTY, - "presence_penalty": SPANDATA.GEN_AI_REQUEST_PRESENCE_PENALTY, - } - - # ModelSettings is a TypedDict (dict at runtime), so use dict access - if isinstance(settings, dict): - for setting_name, spandata_key in settings_map.items(): - value = settings.get(setting_name) - if value is not None: - span.set_attribute(spandata_key, value) # type: ignore[arg-type] - else: - # Fallback for object-style settings - for setting_name, spandata_key in settings_map.items(): - if hasattr(settings, setting_name): - value = getattr(settings, setting_name) - if value is not None: - span.set_attribute(spandata_key, value) - def _set_available_tools(span: "Span", agent: "Optional[Agent[Any, Any]]") -> None: """Set available tools data on a span from an agent's function toolset.