Skip to content

Commit 932993d

Browse files
committed
fix(integrations): properly handle exceptions in tool calls
1 parent e910302 commit 932993d

File tree

3 files changed

+26
-23
lines changed

3 files changed

+26
-23
lines changed

sentry_sdk/integrations/pydantic_ai/patches/agent_run.py

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
from functools import wraps
22

33
import sentry_sdk
4-
from sentry_sdk.tracing_utils import set_span_errored
5-
from sentry_sdk.utils import event_from_exception
64

75
from ..spans import invoke_agent_span, update_invoke_agent_span
6+
from ..utils import _capture_exception
87

98
from typing import TYPE_CHECKING
109
from pydantic_ai.agent import Agent # type: ignore
@@ -13,18 +12,6 @@
1312
from typing import Any, Callable, Optional
1413

1514

16-
def _capture_exception(exc):
17-
# type: (Any) -> None
18-
set_span_errored()
19-
20-
event, hint = event_from_exception(
21-
exc,
22-
client_options=sentry_sdk.get_client().options,
23-
mechanism={"type": "pydantic_ai", "handled": False},
24-
)
25-
sentry_sdk.capture_event(event, hint=hint)
26-
27-
2815
class _StreamingContextManagerWrapper:
2916
"""Wrapper for streaming methods that return async context managers."""
3017

sentry_sdk/integrations/pydantic_ai/patches/tools.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import sentry_sdk
66

77
from ..spans import execute_tool_span, update_execute_tool_span
8+
from ..utils import _capture_exception
89

910
from typing import TYPE_CHECKING
1011

@@ -61,11 +62,15 @@ async def wrapped_call_tool(self, call, allow_partial, wrap_validation_errors):
6162
args_dict = call.args if isinstance(call.args, dict) else {}
6263

6364
with execute_tool_span(name, args_dict, agent, tool_type=tool_type) as span:
64-
result = await original_call_tool(
65-
self, call, allow_partial, wrap_validation_errors
66-
)
67-
update_execute_tool_span(span, result)
68-
return result
65+
try:
66+
result = await original_call_tool(
67+
self, call, allow_partial, wrap_validation_errors
68+
)
69+
update_execute_tool_span(span, result)
70+
return result
71+
except Exception as exc:
72+
_capture_exception(exc)
73+
raise exc from None
6974

7075
# No span context - just call original
7176
return await original_call_tool(

sentry_sdk/integrations/pydantic_ai/utils.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
import sentry_sdk
2-
from sentry_sdk.ai.utils import set_data_normalized
32
from sentry_sdk.consts import SPANDATA
43
from sentry_sdk.scope import should_send_default_pii
5-
from sentry_sdk.utils import safe_serialize
4+
from sentry_sdk.tracing_utils import set_span_errored
5+
from sentry_sdk.utils import event_from_exception, safe_serialize
66

77
from typing import TYPE_CHECKING
88

99
if TYPE_CHECKING:
10-
from typing import Any, List, Dict
11-
from pydantic_ai.usage import RequestUsage # type: ignore
10+
from typing import Any # type: ignore
1211

1312

1413
def _should_send_prompts():
@@ -173,3 +172,15 @@ def _set_available_tools(span, agent):
173172
except Exception:
174173
# If we can't extract tools, just skip it
175174
pass
175+
176+
177+
def _capture_exception(exc):
178+
# type: (Any) -> None
179+
set_span_errored()
180+
181+
event, hint = event_from_exception(
182+
exc,
183+
client_options=sentry_sdk.get_client().options,
184+
mechanism={"type": "pydantic_ai", "handled": False},
185+
)
186+
sentry_sdk.capture_event(event, hint=hint)

0 commit comments

Comments
 (0)