From bd0b8161c54a825cd5d3d485f91fe3f15b56b863 Mon Sep 17 00:00:00 2001 From: harryautomazione Date: Fri, 20 Mar 2026 20:16:18 +0100 Subject: [PATCH 1/6] fix(ai): remove setting of GEN_AI_AGENT_NAME from langchain --- sentry_sdk/integrations/langchain.py | 55 ---------------------------- 1 file changed, 55 deletions(-) diff --git a/sentry_sdk/integrations/langchain.py b/sentry_sdk/integrations/langchain.py index d19d9bbdd5..28723058da 100644 --- a/sentry_sdk/integrations/langchain.py +++ b/sentry_sdk/integrations/langchain.py @@ -154,43 +154,6 @@ def _transform_langchain_message_content(content: "Any") -> "Any": # Contextvar to track agent names in a stack for re-entrant agent support -_agent_stack: "contextvars.ContextVar[Optional[List[Optional[str]]]]" = ( - contextvars.ContextVar("langchain_agent_stack", default=None) -) - - -def _push_agent(agent_name: "Optional[str]") -> None: - """Push an agent name onto the stack.""" - stack = _agent_stack.get() - if stack is None: - stack = [] - else: - # Copy the list to maintain contextvar isolation across async contexts - stack = stack.copy() - stack.append(agent_name) - _agent_stack.set(stack) - - -def _pop_agent() -> "Optional[str]": - """Pop an agent name from the stack and return it.""" - stack = _agent_stack.get() - if stack: - # Copy the list to maintain contextvar isolation across async contexts - stack = stack.copy() - agent_name = stack.pop() - _agent_stack.set(stack) - return agent_name - return None - - -def _get_current_agent() -> "Optional[str]": - """Get the current agent name (top of stack) without removing it.""" - stack = _agent_stack.get() - if stack: - return stack[-1] - return None - - def _get_system_instructions(messages: "List[List[BaseMessage]]") -> "List[str]": system_instructions = [] @@ -455,10 +418,6 @@ def on_chat_model_start( elif "openai" in ai_type: span.set_data(SPANDATA.GEN_AI_SYSTEM, "openai") - agent_name = _get_current_agent() - if agent_name: - span.set_data(SPANDATA.GEN_AI_AGENT_NAME, agent_name) - for key, attribute in DATA_FIELDS.items(): if key in all_params and all_params[key] is not None: set_data_normalized(span, attribute, all_params[key], unpack=False) @@ -655,10 +614,6 @@ def on_tool_start( if tool_description is not None: span.set_data(SPANDATA.GEN_AI_TOOL_DESCRIPTION, tool_description) - agent_name = _get_current_agent() - if agent_name: - span.set_data(SPANDATA.GEN_AI_AGENT_NAME, agent_name) - if should_send_default_pii() and self.include_prompts: set_data_normalized( span, @@ -985,10 +940,7 @@ def new_invoke(self: "Any", *args: "Any", **kwargs: "Any") -> "Any": name=f"invoke_agent {agent_name}" if agent_name else "invoke_agent", origin=LangchainIntegration.origin, ) as span: - _push_agent(agent_name) try: - if agent_name: - span.set_data(SPANDATA.GEN_AI_AGENT_NAME, agent_name) span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "invoke_agent") span.set_data(SPANDATA.GEN_AI_RESPONSE_STREAMING, False) @@ -1028,7 +980,6 @@ def new_invoke(self: "Any", *args: "Any", **kwargs: "Any") -> "Any": return result finally: # Ensure agent is popped even if an exception occurs - _pop_agent() return new_invoke @@ -1050,10 +1001,6 @@ def new_stream(self: "Any", *args: "Any", **kwargs: "Any") -> "Any": ) span.__enter__() - _push_agent(agent_name) - - if agent_name: - span.set_data(SPANDATA.GEN_AI_AGENT_NAME, agent_name) span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "invoke_agent") span.set_data(SPANDATA.GEN_AI_RESPONSE_STREAMING, True) @@ -1107,7 +1054,6 @@ def new_iterator() -> "Iterator[Any]": raise finally: # Ensure cleanup happens even if iterator is abandoned or fails - _pop_agent() span.__exit__(*exc_info) async def new_iterator_async() -> "AsyncIterator[Any]": @@ -1133,7 +1079,6 @@ async def new_iterator_async() -> "AsyncIterator[Any]": raise finally: # Ensure cleanup happens even if iterator is abandoned or fails - _pop_agent() span.__exit__(*exc_info) if str(type(result)) == "": From 85279b5a95dd45cc9e3fd4bbc231fbdb6e9c3c6d Mon Sep 17 00:00:00 2001 From: harryautomazione Date: Fri, 20 Mar 2026 23:21:34 +0100 Subject: [PATCH 2/6] Fix Pydantic AI docs: update class docstring with correct install command, parameter name, and attribute - Change install command to include [pydantic_ai] extra - Change result_type to output_type in example - Change result.data to result.output in example This ensures the docstring matches the current Pydantic AI API and correct installation instructions. Fixes #5293 --- .../integrations/pydantic_ai/__init__.py | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/sentry_sdk/integrations/pydantic_ai/__init__.py b/sentry_sdk/integrations/pydantic_ai/__init__.py index 0f0de53fa5..9a9b9ab671 100644 --- a/sentry_sdk/integrations/pydantic_ai/__init__.py +++ b/sentry_sdk/integrations/pydantic_ai/__init__.py @@ -16,6 +16,40 @@ class PydanticAIIntegration(Integration): + """ + Integration for Pydantic AI. + + This integration instruments Pydantic AI agents to capture traces and errors. + + Example: + Install the integration: + + .. code-block:: bash + + pip install sentry-sdk[pydantic_ai] + + Configure the integration: + + .. code-block:: python + + import sentry_sdk + from sentry_sdk.integrations.pydantic_ai import PydanticAIIntegration + + sentry_sdk.init( + dsn="your-dsn", + integrations=[PydanticAIIntegration()], + ) + + Use Pydantic AI: + + .. code-block:: python + + from pydantic_ai import Agent + + agent = Agent("test", output_type=SupportResponse) + result = await agent.run("Hello") + print(result.output) + """ identifier = "pydantic_ai" origin = f"auto.ai.{identifier}" From bcce29d68cf87ee49be157104171b890f059ab97 Mon Sep 17 00:00:00 2001 From: harryautomazione Date: Fri, 20 Mar 2026 23:52:38 +0100 Subject: [PATCH 3/6] Fix Langchain GEN_AI_AGENT_NAME regression by adding contextvar propagation - Add CURRENT_LANGCHAIN_AGENT_NAME contextvar to track agent name across spans - Set agent name in agent executor wrappers (invoke/stream) - Propagate agent name to all child spans via _create_span - Add test to verify agent name is set on all spans --- sentry_sdk/integrations/langchain.py | 20 +++++++++- .../integrations/langchain/test_langchain.py | 40 +++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/sentry_sdk/integrations/langchain.py b/sentry_sdk/integrations/langchain.py index 28723058da..28413be078 100644 --- a/sentry_sdk/integrations/langchain.py +++ b/sentry_sdk/integrations/langchain.py @@ -23,6 +23,13 @@ from sentry_sdk.tracing_utils import _get_value, set_span_errored from sentry_sdk.utils import capture_internal_exceptions, logger +CURRENT_LANGCHAIN_AGENT_NAME = contextvars.ContextVar("CURRENT_LANGCHAIN_AGENT_NAME", default=None) + + +def _get_current_langchain_agent_name() -> "Optional[str]": + return CURRENT_LANGCHAIN_AGENT_NAME.get(None) + + if TYPE_CHECKING: from typing import ( Any, @@ -290,6 +297,11 @@ def _create_span( watched_span = WatchedSpan(sentry_sdk.start_span(**kwargs)) watched_span.span.__enter__() + + agent_name = _get_current_langchain_agent_name() + if agent_name: + watched_span.span.set_data(SPANDATA.GEN_AI_AGENT_NAME, agent_name) + self.span_map[run_id] = watched_span self.gc_span_map() return watched_span @@ -933,9 +945,10 @@ def new_invoke(self: "Any", *args: "Any", **kwargs: "Any") -> "Any": return f(self, *args, **kwargs) agent_name, tools = _get_request_data(self, args, kwargs) + token = CURRENT_LANGCHAIN_AGENT_NAME.set(agent_name) start_span_function = get_start_span_function() - with start_span_function( + try: op=OP.GEN_AI_INVOKE_AGENT, name=f"invoke_agent {agent_name}" if agent_name else "invoke_agent", origin=LangchainIntegration.origin, @@ -980,6 +993,8 @@ def new_invoke(self: "Any", *args: "Any", **kwargs: "Any") -> "Any": return result finally: # Ensure agent is popped even if an exception occurs + finally: + CURRENT_LANGCHAIN_AGENT_NAME.reset(token) return new_invoke @@ -992,6 +1007,7 @@ def new_stream(self: "Any", *args: "Any", **kwargs: "Any") -> "Any": return f(self, *args, **kwargs) agent_name, tools = _get_request_data(self, args, kwargs) + token = CURRENT_LANGCHAIN_AGENT_NAME.set(agent_name) start_span_function = get_start_span_function() span = start_span_function( @@ -1055,6 +1071,7 @@ def new_iterator() -> "Iterator[Any]": finally: # Ensure cleanup happens even if iterator is abandoned or fails span.__exit__(*exc_info) + CURRENT_LANGCHAIN_AGENT_NAME.reset(token) async def new_iterator_async() -> "AsyncIterator[Any]": exc_info: "tuple[Any, Any, Any]" = (None, None, None) @@ -1080,6 +1097,7 @@ async def new_iterator_async() -> "AsyncIterator[Any]": finally: # Ensure cleanup happens even if iterator is abandoned or fails span.__exit__(*exc_info) + CURRENT_LANGCHAIN_AGENT_NAME.reset(token) if str(type(result)) == "": result = new_iterator_async() diff --git a/tests/integrations/langchain/test_langchain.py b/tests/integrations/langchain/test_langchain.py index 132da0a9a0..1e73ef9634 100644 --- a/tests/integrations/langchain/test_langchain.py +++ b/tests/integrations/langchain/test_langchain.py @@ -313,6 +313,46 @@ def test_langchain_agent( ) +def test_langchain_agent_name_propagation(sentry_init, capture_events, monkeypatch): + sentry_init( + integrations=[LangchainIntegration(include_prompts=True)], + traces_sample_rate=1.0, + send_default_pii=True, + ) + events = capture_events() + + prompt = ChatPromptTemplate.from_messages( + [ + ( + "system", + "You are very powerful assistant, but don't know current events", + ), + ("user", "{input}"), + MessagesPlaceholder(variable_name="agent_scratchpad"), + ] + ) + + llm = MockOpenAI(model_name="gpt-3.5-turbo", temperature=0, openai_api_key="badkey") + agent = create_openai_tools_agent(llm, [get_word_length], prompt) + agent_executor = AgentExecutor(agent=agent, tools=[get_word_length], verbose=True) + + # Mock _get_request_data to return a test agent name + def mock_get_request_data(self, args, kwargs): + return "test_agent_name", [get_word_length] + + monkeypatch.setattr( + "sentry_sdk.integrations.langchain._get_request_data", mock_get_request_data + ) + + with start_transaction(): + list(agent_executor.stream({"input": "How many letters in the word eudca"})) + + tx = events[0] + assert tx["type"] == "transaction" + for span in tx["spans"]: + assert span["data"].get(SPANDATA.GEN_AI_AGENT_NAME) == "test_agent_name" + + def test_langchain_error(sentry_init, capture_events): sentry_init( integrations=[LangchainIntegration(include_prompts=True)], From 556b6d5cb5131ac269e09db82ab680264feb6395 Mon Sep 17 00:00:00 2001 From: harryautomazione Date: Sat, 21 Mar 2026 00:11:39 +0100 Subject: [PATCH 4/6] Fix _wrap_agent_executor_stream token reset leak on exception during initial setup --- sentry_sdk/integrations/langchain.py | 50 +++++++++++++++------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/sentry_sdk/integrations/langchain.py b/sentry_sdk/integrations/langchain.py index 28413be078..eaaad0a99e 100644 --- a/sentry_sdk/integrations/langchain.py +++ b/sentry_sdk/integrations/langchain.py @@ -1017,33 +1017,37 @@ def new_stream(self: "Any", *args: "Any", **kwargs: "Any") -> "Any": ) span.__enter__() + try: + span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "invoke_agent") + span.set_data(SPANDATA.GEN_AI_RESPONSE_STREAMING, True) - span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "invoke_agent") - span.set_data(SPANDATA.GEN_AI_RESPONSE_STREAMING, True) - - _set_tools_on_span(span, tools) + _set_tools_on_span(span, tools) - input = args[0].get("input") if len(args) >= 1 else None - if ( - input is not None - and should_send_default_pii() - and integration.include_prompts - ): - normalized_messages = normalize_message_roles([input]) - scope = sentry_sdk.get_current_scope() - messages_data = truncate_and_annotate_messages( - normalized_messages, span, scope - ) - if messages_data is not None: - set_data_normalized( - span, - SPANDATA.GEN_AI_REQUEST_MESSAGES, - messages_data, - unpack=False, + input = args[0].get("input") if len(args) >= 1 else None + if ( + input is not None + and should_send_default_pii() + and integration.include_prompts + ): + normalized_messages = normalize_message_roles([input]) + scope = sentry_sdk.get_current_scope() + messages_data = truncate_and_annotate_messages( + normalized_messages, span, scope ) + if messages_data is not None: + set_data_normalized( + span, + SPANDATA.GEN_AI_REQUEST_MESSAGES, + messages_data, + unpack=False, + ) - # Run the agent - result = f(self, *args, **kwargs) + # Run the agent + result = f(self, *args, **kwargs) + except Exception: + span.__exit__(None, None, None) + CURRENT_LANGCHAIN_AGENT_NAME.reset(token) + raise old_iterator = result From d0299c8e7f3771cd2f72fdf69694a5b51e8947d1 Mon Sep 17 00:00:00 2001 From: harryautomazione Date: Sun, 22 Mar 2026 17:10:47 +0100 Subject: [PATCH 5/6] fix(ai): normalize messages before tracking truncation size in OpenAI (#5350) --- sentry_sdk/ai/utils.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/sentry_sdk/ai/utils.py b/sentry_sdk/ai/utils.py index 3cfae61546..bcd76f884f 100644 --- a/sentry_sdk/ai/utils.py +++ b/sentry_sdk/ai/utils.py @@ -682,18 +682,19 @@ def truncate_messages_by_size( In the single message case, the serialized message size may exceed `max_bytes`, because truncation is based only on character count in that case. """ - serialized_json = json.dumps(messages, separators=(",", ":")) + normalized_messages = _normalize_data(messages, unpack=False) + serialized_json = json.dumps(normalized_messages, separators=(",", ":")) current_size = len(serialized_json.encode("utf-8")) if current_size <= max_bytes: - return messages, 0 + return normalized_messages, 0 - truncation_index = _find_truncation_index(messages, max_bytes) - if truncation_index < len(messages): - truncated_messages = messages[truncation_index:] + truncation_index = _find_truncation_index(normalized_messages, max_bytes) + if truncation_index < len(normalized_messages): + truncated_messages = normalized_messages[truncation_index:] else: - truncation_index = len(messages) - 1 - truncated_messages = messages[-1:] + truncation_index = len(normalized_messages) - 1 + truncated_messages = normalized_messages[-1:] if len(truncated_messages) == 1: truncated_messages[0] = _truncate_single_message_content_if_present( From dbb209ef9aacd1efd3e78c601f20bea9f6b36b80 Mon Sep 17 00:00:00 2001 From: harryautomazione Date: Sun, 22 Mar 2026 17:21:15 +0100 Subject: [PATCH 6/6] chore: remove accidental changes from this PR --- sentry_sdk/integrations/langchain.py | 125 +++++++++++------- .../integrations/pydantic_ai/__init__.py | 34 ----- .../integrations/langchain/test_langchain.py | 40 ------ 3 files changed, 79 insertions(+), 120 deletions(-) diff --git a/sentry_sdk/integrations/langchain.py b/sentry_sdk/integrations/langchain.py index eaaad0a99e..d19d9bbdd5 100644 --- a/sentry_sdk/integrations/langchain.py +++ b/sentry_sdk/integrations/langchain.py @@ -23,13 +23,6 @@ from sentry_sdk.tracing_utils import _get_value, set_span_errored from sentry_sdk.utils import capture_internal_exceptions, logger -CURRENT_LANGCHAIN_AGENT_NAME = contextvars.ContextVar("CURRENT_LANGCHAIN_AGENT_NAME", default=None) - - -def _get_current_langchain_agent_name() -> "Optional[str]": - return CURRENT_LANGCHAIN_AGENT_NAME.get(None) - - if TYPE_CHECKING: from typing import ( Any, @@ -161,6 +154,43 @@ def _transform_langchain_message_content(content: "Any") -> "Any": # Contextvar to track agent names in a stack for re-entrant agent support +_agent_stack: "contextvars.ContextVar[Optional[List[Optional[str]]]]" = ( + contextvars.ContextVar("langchain_agent_stack", default=None) +) + + +def _push_agent(agent_name: "Optional[str]") -> None: + """Push an agent name onto the stack.""" + stack = _agent_stack.get() + if stack is None: + stack = [] + else: + # Copy the list to maintain contextvar isolation across async contexts + stack = stack.copy() + stack.append(agent_name) + _agent_stack.set(stack) + + +def _pop_agent() -> "Optional[str]": + """Pop an agent name from the stack and return it.""" + stack = _agent_stack.get() + if stack: + # Copy the list to maintain contextvar isolation across async contexts + stack = stack.copy() + agent_name = stack.pop() + _agent_stack.set(stack) + return agent_name + return None + + +def _get_current_agent() -> "Optional[str]": + """Get the current agent name (top of stack) without removing it.""" + stack = _agent_stack.get() + if stack: + return stack[-1] + return None + + def _get_system_instructions(messages: "List[List[BaseMessage]]") -> "List[str]": system_instructions = [] @@ -297,11 +327,6 @@ def _create_span( watched_span = WatchedSpan(sentry_sdk.start_span(**kwargs)) watched_span.span.__enter__() - - agent_name = _get_current_langchain_agent_name() - if agent_name: - watched_span.span.set_data(SPANDATA.GEN_AI_AGENT_NAME, agent_name) - self.span_map[run_id] = watched_span self.gc_span_map() return watched_span @@ -430,6 +455,10 @@ def on_chat_model_start( elif "openai" in ai_type: span.set_data(SPANDATA.GEN_AI_SYSTEM, "openai") + agent_name = _get_current_agent() + if agent_name: + span.set_data(SPANDATA.GEN_AI_AGENT_NAME, agent_name) + for key, attribute in DATA_FIELDS.items(): if key in all_params and all_params[key] is not None: set_data_normalized(span, attribute, all_params[key], unpack=False) @@ -626,6 +655,10 @@ def on_tool_start( if tool_description is not None: span.set_data(SPANDATA.GEN_AI_TOOL_DESCRIPTION, tool_description) + agent_name = _get_current_agent() + if agent_name: + span.set_data(SPANDATA.GEN_AI_AGENT_NAME, agent_name) + if should_send_default_pii() and self.include_prompts: set_data_normalized( span, @@ -945,15 +978,17 @@ def new_invoke(self: "Any", *args: "Any", **kwargs: "Any") -> "Any": return f(self, *args, **kwargs) agent_name, tools = _get_request_data(self, args, kwargs) - token = CURRENT_LANGCHAIN_AGENT_NAME.set(agent_name) start_span_function = get_start_span_function() - try: + with start_span_function( op=OP.GEN_AI_INVOKE_AGENT, name=f"invoke_agent {agent_name}" if agent_name else "invoke_agent", origin=LangchainIntegration.origin, ) as span: + _push_agent(agent_name) try: + if agent_name: + span.set_data(SPANDATA.GEN_AI_AGENT_NAME, agent_name) span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "invoke_agent") span.set_data(SPANDATA.GEN_AI_RESPONSE_STREAMING, False) @@ -993,8 +1028,7 @@ def new_invoke(self: "Any", *args: "Any", **kwargs: "Any") -> "Any": return result finally: # Ensure agent is popped even if an exception occurs - finally: - CURRENT_LANGCHAIN_AGENT_NAME.reset(token) + _pop_agent() return new_invoke @@ -1007,7 +1041,6 @@ def new_stream(self: "Any", *args: "Any", **kwargs: "Any") -> "Any": return f(self, *args, **kwargs) agent_name, tools = _get_request_data(self, args, kwargs) - token = CURRENT_LANGCHAIN_AGENT_NAME.set(agent_name) start_span_function = get_start_span_function() span = start_span_function( @@ -1017,37 +1050,37 @@ def new_stream(self: "Any", *args: "Any", **kwargs: "Any") -> "Any": ) span.__enter__() - try: - span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "invoke_agent") - span.set_data(SPANDATA.GEN_AI_RESPONSE_STREAMING, True) + _push_agent(agent_name) + + if agent_name: + span.set_data(SPANDATA.GEN_AI_AGENT_NAME, agent_name) - _set_tools_on_span(span, tools) + span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "invoke_agent") + span.set_data(SPANDATA.GEN_AI_RESPONSE_STREAMING, True) - input = args[0].get("input") if len(args) >= 1 else None - if ( - input is not None - and should_send_default_pii() - and integration.include_prompts - ): - normalized_messages = normalize_message_roles([input]) - scope = sentry_sdk.get_current_scope() - messages_data = truncate_and_annotate_messages( - normalized_messages, span, scope + _set_tools_on_span(span, tools) + + input = args[0].get("input") if len(args) >= 1 else None + if ( + input is not None + and should_send_default_pii() + and integration.include_prompts + ): + normalized_messages = normalize_message_roles([input]) + scope = sentry_sdk.get_current_scope() + messages_data = truncate_and_annotate_messages( + normalized_messages, span, scope + ) + if messages_data is not None: + set_data_normalized( + span, + SPANDATA.GEN_AI_REQUEST_MESSAGES, + messages_data, + unpack=False, ) - if messages_data is not None: - set_data_normalized( - span, - SPANDATA.GEN_AI_REQUEST_MESSAGES, - messages_data, - unpack=False, - ) - # Run the agent - result = f(self, *args, **kwargs) - except Exception: - span.__exit__(None, None, None) - CURRENT_LANGCHAIN_AGENT_NAME.reset(token) - raise + # Run the agent + result = f(self, *args, **kwargs) old_iterator = result @@ -1074,8 +1107,8 @@ def new_iterator() -> "Iterator[Any]": raise finally: # Ensure cleanup happens even if iterator is abandoned or fails + _pop_agent() span.__exit__(*exc_info) - CURRENT_LANGCHAIN_AGENT_NAME.reset(token) async def new_iterator_async() -> "AsyncIterator[Any]": exc_info: "tuple[Any, Any, Any]" = (None, None, None) @@ -1100,8 +1133,8 @@ async def new_iterator_async() -> "AsyncIterator[Any]": raise finally: # Ensure cleanup happens even if iterator is abandoned or fails + _pop_agent() span.__exit__(*exc_info) - CURRENT_LANGCHAIN_AGENT_NAME.reset(token) if str(type(result)) == "": result = new_iterator_async() diff --git a/sentry_sdk/integrations/pydantic_ai/__init__.py b/sentry_sdk/integrations/pydantic_ai/__init__.py index 9a9b9ab671..0f0de53fa5 100644 --- a/sentry_sdk/integrations/pydantic_ai/__init__.py +++ b/sentry_sdk/integrations/pydantic_ai/__init__.py @@ -16,40 +16,6 @@ class PydanticAIIntegration(Integration): - """ - Integration for Pydantic AI. - - This integration instruments Pydantic AI agents to capture traces and errors. - - Example: - Install the integration: - - .. code-block:: bash - - pip install sentry-sdk[pydantic_ai] - - Configure the integration: - - .. code-block:: python - - import sentry_sdk - from sentry_sdk.integrations.pydantic_ai import PydanticAIIntegration - - sentry_sdk.init( - dsn="your-dsn", - integrations=[PydanticAIIntegration()], - ) - - Use Pydantic AI: - - .. code-block:: python - - from pydantic_ai import Agent - - agent = Agent("test", output_type=SupportResponse) - result = await agent.run("Hello") - print(result.output) - """ identifier = "pydantic_ai" origin = f"auto.ai.{identifier}" diff --git a/tests/integrations/langchain/test_langchain.py b/tests/integrations/langchain/test_langchain.py index 1e73ef9634..132da0a9a0 100644 --- a/tests/integrations/langchain/test_langchain.py +++ b/tests/integrations/langchain/test_langchain.py @@ -313,46 +313,6 @@ def test_langchain_agent( ) -def test_langchain_agent_name_propagation(sentry_init, capture_events, monkeypatch): - sentry_init( - integrations=[LangchainIntegration(include_prompts=True)], - traces_sample_rate=1.0, - send_default_pii=True, - ) - events = capture_events() - - prompt = ChatPromptTemplate.from_messages( - [ - ( - "system", - "You are very powerful assistant, but don't know current events", - ), - ("user", "{input}"), - MessagesPlaceholder(variable_name="agent_scratchpad"), - ] - ) - - llm = MockOpenAI(model_name="gpt-3.5-turbo", temperature=0, openai_api_key="badkey") - agent = create_openai_tools_agent(llm, [get_word_length], prompt) - agent_executor = AgentExecutor(agent=agent, tools=[get_word_length], verbose=True) - - # Mock _get_request_data to return a test agent name - def mock_get_request_data(self, args, kwargs): - return "test_agent_name", [get_word_length] - - monkeypatch.setattr( - "sentry_sdk.integrations.langchain._get_request_data", mock_get_request_data - ) - - with start_transaction(): - list(agent_executor.stream({"input": "How many letters in the word eudca"})) - - tx = events[0] - assert tx["type"] == "transaction" - for span in tx["spans"]: - assert span["data"].get(SPANDATA.GEN_AI_AGENT_NAME) == "test_agent_name" - - def test_langchain_error(sentry_init, capture_events): sentry_init( integrations=[LangchainIntegration(include_prompts=True)],