diff --git a/sentry_sdk/integrations/pydantic_ai/patches/tools.py b/sentry_sdk/integrations/pydantic_ai/patches/tools.py index 958d729fbb..a88e1d5712 100644 --- a/sentry_sdk/integrations/pydantic_ai/patches/tools.py +++ b/sentry_sdk/integrations/pydantic_ai/patches/tools.py @@ -1,4 +1,5 @@ import sys +from contextlib import nullcontext from functools import wraps from typing import TYPE_CHECKING @@ -60,11 +61,15 @@ async def wrapped_execute_tool_call( # Create execute_tool span # Nesting is handled by isolation_scope() to ensure proper parent-child relationships with sentry_sdk.isolation_scope(): - with execute_tool_span( - name, - args_dict, - agent, - tool_definition=selected_tool_definition, + with ( + execute_tool_span( + name, + args_dict, + agent, + tool_definition=selected_tool_definition, + ) + if validated.args_valid + else nullcontext() ) as span: try: result = await original_execute_tool_call( @@ -73,7 +78,8 @@ async def wrapped_execute_tool_call( *args, **kwargs, ) - update_execute_tool_span(span, result) + if span is not None: + update_execute_tool_span(span, result) return result except ToolRetryError as exc: exc_info = sys.exc_info() diff --git a/tests/integrations/pydantic_ai/test_pydantic_ai.py b/tests/integrations/pydantic_ai/test_pydantic_ai.py index 03f468e497..b862a11dfa 100644 --- a/tests/integrations/pydantic_ai/test_pydantic_ai.py +++ b/tests/integrations/pydantic_ai/test_pydantic_ai.py @@ -1022,24 +1022,6 @@ def add_numbers(a: Annotated[int, Field(gt=0, lt=0)], b: int) -> int: chat_spans = [ s for s in spans if s["attributes"].get("sentry.op", "") == "gen_ai.chat" ] - tool_spans = [ - s - for s in spans - if s["attributes"].get("sentry.op", "") == "gen_ai.execute_tool" - ] - - # Should have tool spans - assert len(tool_spans) >= 1 - - # Check tool spans - model_retry_tool_span = tool_spans[0] - assert "execute_tool" in model_retry_tool_span["name"] - assert ( - model_retry_tool_span["attributes"]["gen_ai.operation.name"] - == "execute_tool" - ) - assert model_retry_tool_span["attributes"]["gen_ai.tool.name"] == "add_numbers" - assert "gen_ai.tool.input" in model_retry_tool_span["attributes"] # Check chat spans have available_tools assert "gen_ai.request.available_tools" in chat_spans[0]["attributes"] @@ -1073,17 +1055,6 @@ def add_numbers(a: Annotated[int, Field(gt=0, lt=0)], b: int) -> int: # Find child span types (invoke_agent is the transaction, not a child span) chat_spans = [s for s in spans if s["op"] == "gen_ai.chat"] - tool_spans = [s for s in spans if s["op"] == "gen_ai.execute_tool"] - - # Should have tool spans - assert len(tool_spans) >= 1 - - # Check tool spans - model_retry_tool_span = tool_spans[0] - assert "execute_tool" in model_retry_tool_span["description"] - assert model_retry_tool_span["data"]["gen_ai.operation.name"] == "execute_tool" - assert model_retry_tool_span["data"]["gen_ai.tool.name"] == "add_numbers" - assert "gen_ai.tool.input" in model_retry_tool_span["data"] # Check chat spans have available_tools assert "gen_ai.request.available_tools" in chat_spans[0]["data"]