Skip to content

Commit ea0a549

Browse files
committed
fix: using contextvar to store agent name in a re-entrant way
1 parent 5043e91 commit ea0a549

File tree

1 file changed

+42
-19
lines changed

1 file changed

+42
-19
lines changed

sentry_sdk/integrations/langchain.py

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import contextvars
12
import itertools
23
from collections import OrderedDict
34
from functools import wraps
@@ -72,6 +73,40 @@
7273
}
7374

7475

76+
# Contextvar to track agent names in a stack for re-entrant agent support
77+
_agent_stack = contextvars.ContextVar("langchain_agent_stack", default=None)
78+
79+
80+
def _push_agent(agent_name):
81+
# type: (Optional[str]) -> None
82+
"""Push an agent name onto the stack."""
83+
stack = _agent_stack.get()
84+
if stack is None:
85+
stack = []
86+
stack.append(agent_name)
87+
_agent_stack.set(stack)
88+
89+
90+
def _pop_agent():
91+
# type: () -> Optional[str]
92+
"""Pop an agent name from the stack and return it."""
93+
stack = _agent_stack.get()
94+
if stack and len(stack) > 0:
95+
agent_name = stack.pop()
96+
_agent_stack.set(stack)
97+
return agent_name
98+
return None
99+
100+
101+
def _get_current_agent():
102+
# type: () -> Optional[str]
103+
"""Get the current agent name (top of stack) without removing it."""
104+
stack = _agent_stack.get()
105+
if stack and len(stack) > 0:
106+
return stack[-1]
107+
return None
108+
109+
75110
class LangchainIntegration(Integration):
76111
identifier = "langchain"
77112
origin = f"auto.ai.{identifier}"
@@ -276,11 +311,7 @@ def on_chat_model_start(self, serialized, messages, *, run_id, **kwargs):
276311
elif "openai" in ai_type:
277312
span.set_data(SPANDATA.GEN_AI_SYSTEM, "openai")
278313

279-
agent_name = (
280-
sentry_sdk.get_current_scope()
281-
._contexts.get("langchain_agent", {})
282-
.get("agent_name")
283-
)
314+
agent_name = _get_current_agent()
284315
if agent_name:
285316
span.set_data(SPANDATA.GEN_AI_AGENT_NAME, agent_name)
286317

@@ -436,11 +467,7 @@ def on_tool_start(self, serialized, input_str, *, run_id, **kwargs):
436467
if tool_description is not None:
437468
span.set_data(SPANDATA.GEN_AI_TOOL_DESCRIPTION, tool_description)
438469

439-
agent_name = (
440-
sentry_sdk.get_current_scope()
441-
._contexts.get("langchain_agent", {})
442-
.get("agent_name")
443-
)
470+
agent_name = _get_current_agent()
444471
if agent_name:
445472
span.set_data(SPANDATA.GEN_AI_AGENT_NAME, agent_name)
446473

@@ -772,9 +799,7 @@ def new_invoke(self, *args, **kwargs):
772799
name=f"invoke_agent {agent_name}" if agent_name else "invoke_agent",
773800
origin=LangchainIntegration.origin,
774801
) as span:
775-
sentry_sdk.get_current_scope().set_context(
776-
"langchain_agent", {"agent_name": agent_name, "tools": tools}
777-
)
802+
_push_agent(agent_name)
778803
if agent_name:
779804
span.set_data(SPANDATA.GEN_AI_AGENT_NAME, agent_name)
780805

@@ -813,7 +838,7 @@ def new_invoke(self, *args, **kwargs):
813838
):
814839
set_data_normalized(span, SPANDATA.GEN_AI_RESPONSE_TEXT, output)
815840

816-
sentry_sdk.get_current_scope().remove_context("langchain_agent")
841+
_pop_agent()
817842

818843
return result
819844

@@ -840,9 +865,7 @@ def new_stream(self, *args, **kwargs):
840865
)
841866
span.__enter__()
842867

843-
sentry_sdk.get_current_scope().set_context(
844-
"langchain_agent", {"agent_name": agent_name, "tools": tools}
845-
)
868+
_push_agent(agent_name)
846869

847870
if agent_name:
848871
span.set_data(SPANDATA.GEN_AI_AGENT_NAME, agent_name)
@@ -893,7 +916,7 @@ def new_iterator():
893916
):
894917
set_data_normalized(span, SPANDATA.GEN_AI_RESPONSE_TEXT, output)
895918

896-
sentry_sdk.get_current_scope().remove_context("langchain_agent")
919+
_pop_agent()
897920

898921
span.__exit__(None, None, None)
899922

@@ -914,7 +937,7 @@ async def new_iterator_async():
914937
):
915938
set_data_normalized(span, SPANDATA.GEN_AI_RESPONSE_TEXT, output)
916939

917-
sentry_sdk.get_current_scope().remove_context("langchain_agent")
940+
_pop_agent()
918941

919942
span.__exit__(None, None, None)
920943

0 commit comments

Comments
 (0)