Skip to content

AI-183: Respect LANGSMITH_TRACING env var in LangSmith plugin#1509

Open
xumaple wants to merge 4 commits intomainfrom
maplexu/AI-183-respect-langsmith-tracing-env
Open

AI-183: Respect LANGSMITH_TRACING env var in LangSmith plugin#1509
xumaple wants to merge 4 commits intomainfrom
maplexu/AI-183-respect-langsmith-tracing-env

Conversation

@xumaple
Copy link
Copy Markdown
Contributor

@xumaple xumaple commented May 8, 2026

Summary

Fix AI-183: LangSmithPlugin was force-enabling LangSmith tracing inside every workflow execution, overriding the user's LANGSMITH_TRACING=false env var.

Two bug surfaces in temporalio/contrib/langsmith/_interceptor.py:

  • All four tracing_context(...) call sites (workflow, activity, nexus start, nexus cancel) hard-coded enabled=True, short-circuiting tracing_is_enabled() because the langsmith library checks the context dict before env vars.
  • _maybe_run gated Temporal-level runs only on add_temporal_runs. When add_temporal_runs=True, runs were created regardless of any disable mechanism.

The fix defers to langsmith's native polarity: drop the enabled kwarg entirely so langsmith's own resolution takes over, and gate _maybe_run on langsmith.utils.tracing_is_enabled().

⚠️ Behavior change

The plugin no longer treats "installed = on by default." Users must now opt in via LANGSMITH_TRACING=true (or set the context appropriately), matching langsmith's standard mechanism. Users who previously relied on installing the plugin without setting any env var will need to set LANGSMITH_TRACING=true to keep getting traces.

Cross-process trace continuation

tracing_is_enabled() checks for an active parent run tree before consulting the env var. So a worker with LANGSMITH_TRACING=false will still continue an inbound parent trace propagated via headers from an upstream worker that had tracing enabled. This matches langsmith's "continue mid-trace" model — LANGSMITH_TRACING=false suppresses new traces locally but doesn't break a parent trace flowing through. Documented in _maybe_run's docstring.

Tests

5 new tests in tests/contrib/langsmith/test_tracing_env_override.py:

  • add_temporal_runs=True + LANGSMITH_TRACING=false → no runs
  • add_temporal_runs=False + LANGSMITH_TRACING=false → no runs
  • Legacy LANGCHAIN_TRACING_V2=false → no runs
  • Nexus start handler + LANGSMITH_TRACING=false → no runs
  • Positive control: LANGSMITH_TRACING=true → runs ARE emitted

Two new autouse fixtures in tests/contrib/langsmith/conftest.py:

  • _clear_langsmith_env_cache — clears langsmith's get_env_var lru_cache between tests so env-var changes don't leak across tests.
  • _enable_langsmith_tracing — sets LANGSMITH_TRACING=true by default for all langsmith tests, preserving the prior "tracing on" assumption that 87 existing tests rely on. Individual tests override with monkeypatch.setenv(..., "false") as needed.

The Nexus cancel path is not directly tested — it would require ~50+ lines of new scaffolding for in-flight cancel orchestration. Code path is identical to Nexus start; worth a follow-up ticket.

Test plan

  • uv run pytest tests/contrib/langsmith/test_tracing_env_override.py -v — 5/5 pass
  • uv run pytest tests/contrib/langsmith/ -v — full suite, 87/87 pass
  • uv run pytest tests/contrib/ -v — broader contrib, 306 pass / 16 skip / 0 fail (3 unrelated collection errors from missing optional deps)
  • All 6 SDK linters clean on changed files (ruff, ruff format, pyright, mypy, basedpyright, pydocstyle)
  • Bug-detection regression check: revert the fix, run the 4 negative tests, confirm they fail correctly, restore.

LangSmithInterceptor previously hard-coded `enabled=True` in every
`tracing_context(...)` call (4 sites: workflow, activity, nexus start,
nexus cancel) and `_maybe_run` gated only on `add_temporal_runs`. This
meant `LANGSMITH_TRACING=false` was a no-op when the plugin was
installed.

Defer to langsmith's native polarity: drop `enabled` from all four
`tracing_context(...)` calls so langsmith's own `tracing_is_enabled()`
resolution takes over, and short-circuit `_maybe_run` on
`tracing_is_enabled()` in addition to the existing `add_temporal_runs`
gate.

Behavior change: the plugin is no longer "on by default" once installed.
Users must now explicitly opt in via `LANGSMITH_TRACING=true`, matching
langsmith's standard mechanism.

Cross-process: `tracing_is_enabled()` checks for an active parent run
tree before consulting env vars, so an inbound parent trace propagated
via headers will continue locally even when `LANGSMITH_TRACING=false`
(documented in `_maybe_run`'s docstring).

Adds 5 tests in tests/contrib/langsmith/test_tracing_env_override.py
covering both `add_temporal_runs` modes, the legacy `LANGCHAIN_TRACING_V2`
env var, the Nexus start path, and a positive control. Adds two autouse
fixtures in tests/contrib/langsmith/conftest.py: one to clear langsmith's
env-var lru_cache between tests, and one to set `LANGSMITH_TRACING=true`
by default for the suite (preserving the prior "tracing on" assumption
that the existing 87 tests rely on; individual tests override).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@xumaple xumaple requested review from a team as code owners May 8, 2026 18:27
xumaple and others added 2 commits May 8, 2026 15:00
The Note paragraph was sandwiched between two bullets, breaking RST
definition list parsing. Pydoctor reported "Definition list ends without
a blank line; unexpected unindent."

Move the Note after all bullets, as a standalone paragraph before
``Args:``. No content change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants