2323from sentry_sdk .tracing_utils import _get_value , set_span_errored
2424from sentry_sdk .utils import capture_internal_exceptions , logger
2525
26+ CURRENT_LANGCHAIN_AGENT_NAME = contextvars .ContextVar ("CURRENT_LANGCHAIN_AGENT_NAME" , default = None )
27+
28+
29+ def _get_current_langchain_agent_name () -> "Optional[str]" :
30+ return CURRENT_LANGCHAIN_AGENT_NAME .get (None )
31+
32+
2633if TYPE_CHECKING :
2734 from typing import (
2835 Any ,
@@ -290,6 +297,11 @@ def _create_span(
290297 watched_span = WatchedSpan (sentry_sdk .start_span (** kwargs ))
291298
292299 watched_span .span .__enter__ ()
300+
301+ agent_name = _get_current_langchain_agent_name ()
302+ if agent_name :
303+ watched_span .span .set_data (SPANDATA .GEN_AI_AGENT_NAME , agent_name )
304+
293305 self .span_map [run_id ] = watched_span
294306 self .gc_span_map ()
295307 return watched_span
@@ -933,53 +945,60 @@ def new_invoke(self: "Any", *args: "Any", **kwargs: "Any") -> "Any":
933945 return f (self , * args , ** kwargs )
934946
935947 agent_name , tools = _get_request_data (self , args , kwargs )
948+ token = CURRENT_LANGCHAIN_AGENT_NAME .set (agent_name )
936949 start_span_function = get_start_span_function ()
937950
938- with start_span_function (
939- op = OP .GEN_AI_INVOKE_AGENT ,
940- name = f"invoke_agent { agent_name } " if agent_name else "invoke_agent" ,
941- origin = LangchainIntegration .origin ,
942- ) as span :
943- try :
944-
945- span .set_data (SPANDATA .GEN_AI_OPERATION_NAME , "invoke_agent" )
946- span .set_data (SPANDATA .GEN_AI_RESPONSE_STREAMING , False )
947-
948- _set_tools_on_span (span , tools )
949-
950- # Run the agent
951- result = f (self , * args , ** kwargs )
952-
953- input = result .get ("input" )
954- if (
955- input is not None
956- and should_send_default_pii ()
957- and integration .include_prompts
958- ):
959- normalized_messages = normalize_message_roles ([input ])
960- scope = sentry_sdk .get_current_scope ()
961- messages_data = truncate_and_annotate_messages (
962- normalized_messages , span , scope
963- )
964- if messages_data is not None :
965- set_data_normalized (
966- span ,
967- SPANDATA .GEN_AI_REQUEST_MESSAGES ,
968- messages_data ,
969- unpack = False ,
951+ try :
952+ with start_span_function (
953+ op = OP .GEN_AI_INVOKE_AGENT ,
954+ name = f"invoke_agent { agent_name } " if agent_name else "invoke_agent" ,
955+ origin = LangchainIntegration .origin ,
956+ ) as span :
957+ try :
958+ if agent_name :
959+ span .set_data (SPANDATA .GEN_AI_AGENT_NAME , agent_name )
960+
961+ span .set_data (SPANDATA .GEN_AI_OPERATION_NAME , "invoke_agent" )
962+ span .set_data (SPANDATA .GEN_AI_RESPONSE_STREAMING , False )
963+
964+ _set_tools_on_span (span , tools )
965+
966+ # Run the agent
967+ result = f (self , * args , ** kwargs )
968+
969+ input = result .get ("input" )
970+ if (
971+ input is not None
972+ and should_send_default_pii ()
973+ and integration .include_prompts
974+ ):
975+ normalized_messages = normalize_message_roles ([input ])
976+ scope = sentry_sdk .get_current_scope ()
977+ messages_data = truncate_and_annotate_messages (
978+ normalized_messages , span , scope
970979 )
980+ if messages_data is not None :
981+ set_data_normalized (
982+ span ,
983+ SPANDATA .GEN_AI_REQUEST_MESSAGES ,
984+ messages_data ,
985+ unpack = False ,
986+ )
971987
972- output = result .get ("output" )
973- if (
974- output is not None
975- and should_send_default_pii ()
976- and integration .include_prompts
977- ):
978- set_data_normalized (span , SPANDATA .GEN_AI_RESPONSE_TEXT , output )
979-
980- return result
981- finally :
982- # Ensure agent is popped even if an exception occurs
988+ output = result .get ("output" )
989+ if (
990+ output is not None
991+ and should_send_default_pii ()
992+ and integration .include_prompts
993+ ):
994+ set_data_normalized (span , SPANDATA .GEN_AI_RESPONSE_TEXT , output )
995+
996+ return result
997+ finally :
998+ # Ensure agent is popped even if an exception occurs
999+ pass
1000+ finally :
1001+ CURRENT_LANGCHAIN_AGENT_NAME .reset (token )
9831002
9841003 return new_invoke
9851004
@@ -992,6 +1011,7 @@ def new_stream(self: "Any", *args: "Any", **kwargs: "Any") -> "Any":
9921011 return f (self , * args , ** kwargs )
9931012
9941013 agent_name , tools = _get_request_data (self , args , kwargs )
1014+ token = CURRENT_LANGCHAIN_AGENT_NAME .set (agent_name )
9951015 start_span_function = get_start_span_function ()
9961016
9971017 span = start_span_function (
@@ -1001,6 +1021,8 @@ def new_stream(self: "Any", *args: "Any", **kwargs: "Any") -> "Any":
10011021 )
10021022 span .__enter__ ()
10031023
1024+ if agent_name :
1025+ span .set_data (SPANDATA .GEN_AI_AGENT_NAME , agent_name )
10041026
10051027 span .set_data (SPANDATA .GEN_AI_OPERATION_NAME , "invoke_agent" )
10061028 span .set_data (SPANDATA .GEN_AI_RESPONSE_STREAMING , True )
@@ -1055,6 +1077,7 @@ def new_iterator() -> "Iterator[Any]":
10551077 finally :
10561078 # Ensure cleanup happens even if iterator is abandoned or fails
10571079 span .__exit__ (* exc_info )
1080+ CURRENT_LANGCHAIN_AGENT_NAME .reset (token )
10581081
10591082 async def new_iterator_async () -> "AsyncIterator[Any]" :
10601083 exc_info : "tuple[Any, Any, Any]" = (None , None , None )
@@ -1080,6 +1103,7 @@ async def new_iterator_async() -> "AsyncIterator[Any]":
10801103 finally :
10811104 # Ensure cleanup happens even if iterator is abandoned or fails
10821105 span .__exit__ (* exc_info )
1106+ CURRENT_LANGCHAIN_AGENT_NAME .reset (token )
10831107
10841108 if str (type (result )) == "<class 'async_generator'>" :
10851109 result = new_iterator_async ()
0 commit comments