mirror of
https://github.com/langchain-ai/deepagents.git
synced 2026-07-22 01:35:28 -04:00
fix(cli): suppress LangSmith trace for _context_tokens state writes (#3317)
`_context_tokens` is declared with `PrivateStateAttr`, which keeps it out of the graph's input/output schemas, but `Pregel.aupdate_state` still emits its own top-level `UpdateState` run on every turn — so the count surfaces as a noisy standalone trace in LangSmith on each LLM response and offload. Wrap the `aupdate_state` call in `_persist_context_tokens` with `langsmith.tracing_context(enabled=False)` so the internal bookkeeping write is fully suppressed from the active LangSmith project while still being checkpointed for thread resume. _Opened collaboratively by Mason Daugherty and open-swe._ Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com> Co-authored-by: Mason Daugherty <61371264+mdrxy@users.noreply.github.com> Co-authored-by: Mason Daugherty <mason@langchain.dev>
This commit is contained in:
@@ -1432,13 +1432,22 @@ async def _persist_context_tokens(
|
||||
) -> None:
|
||||
"""Best-effort persist of the context token count into graph state.
|
||||
|
||||
The `aupdate_state` call is wrapped in `tracing_context(enabled=False)` so
|
||||
this purely-internal bookkeeping write does not surface as a separate
|
||||
`UpdateState` run in LangSmith. `_context_tokens` is already marked
|
||||
`PrivateStateAttr`, but `aupdate_state` itself creates its own traced run
|
||||
that would otherwise clutter the project's traces.
|
||||
|
||||
Args:
|
||||
agent: The LangGraph agent (must support `aupdate_state`).
|
||||
config: Runnable config with `thread_id`.
|
||||
tokens: Total context tokens to persist.
|
||||
"""
|
||||
from langsmith import tracing_context
|
||||
|
||||
try:
|
||||
await agent.aupdate_state(config, {"_context_tokens": tokens})
|
||||
with tracing_context(enabled=False):
|
||||
await agent.aupdate_state(config, {"_context_tokens": tokens})
|
||||
except (httpx.TransportError, httpx.TimeoutException) as e:
|
||||
logger.warning(
|
||||
"Could not persist _context_tokens=%d (network): %s; "
|
||||
|
||||
@@ -123,3 +123,28 @@ class TestPersistContextTokens:
|
||||
|
||||
# Should not raise
|
||||
await _persist_context_tokens(agent, config, 1000) # type: ignore[arg-type]
|
||||
|
||||
async def test_disables_tracing_during_update(self):
|
||||
"""`aupdate_state` should run with LangSmith tracing disabled.
|
||||
|
||||
The token-count write is a private bookkeeping update; surfacing it as a
|
||||
standalone `UpdateState` run in LangSmith clutters traces.
|
||||
"""
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
from langsmith import get_tracing_context
|
||||
|
||||
from deepagents_cli.textual_adapter import _persist_context_tokens
|
||||
|
||||
captured: dict[str, object] = {}
|
||||
|
||||
async def _capture(*_args: object, **_kwargs: object) -> None: # noqa: RUF029 # AsyncMock side_effect must be a coroutine function
|
||||
captured["enabled"] = get_tracing_context().get("enabled")
|
||||
|
||||
agent = AsyncMock()
|
||||
agent.aupdate_state.side_effect = _capture
|
||||
config = {"configurable": {"thread_id": "t-1"}}
|
||||
|
||||
await _persist_context_tokens(agent, config, 4200) # type: ignore[arg-type]
|
||||
|
||||
assert captured["enabled"] is False
|
||||
|
||||
Reference in New Issue
Block a user