Files
langchain/libs/core/tests/unit_tests
Jacob Lee a6eb829701 fix(core): Use reference counting for storing inherited run trees to support garbage collection (#36660)
When a langsmith `@traceable` function invokes a LangChain Runnable or
LangGraph subgraph, the callback manager's `_configure` function injects
the `@traceable` RunTree into the `LangChainTracer`'s `run_map` so that
child runs can resolve their parent for trace nesting. However, since
the RunTree was created outside the tracer's callback lifecycle,
`_end_trace` never removes it. The entry persists in `run_map`
indefinitely, retaining the full RunTree and its entire child tree.

In applications with nested subgraph invocations (e.g. an outer
investigation graph delegating to skill agent subgraphs, each compiled
as their own `StateGraph`), this causes RunTree objects to accumulate
linearly with every call.

**Fix:** Track which `run_map` entries were injected externally via a
shared `_external_run_ids` refcount dict on `_TracerCore`. When
`_start_trace` adds a child under an external parent, it increments the
count. When `_end_trace` finishes a child, it decrements — and evicts
the external parent from `run_map` once the last child completes.

The refcount (rather than a simple set) is necessary because a single
external parent may have multiple sibling children in the callback chain
(e.g. a `prompt | llm` `RunnableSequence`). Only truly external runs are
tracked — the `_configure` guard `if run_id_str not in handler.run_map`
prevents tracer-managed runs from being misclassified.
2026-04-13 09:50:37 -04:00
..
2025-10-02 18:46:26 -04:00