Skip to main content
When you have the environment variable LANGSMITH_TRACING=true set globally, traces are automatically sent to LangSmith. This guide shows you how to disable or customize tracing selectively for specific requests. The tracing_context context manager (Python) and tracingEnabled option (TypeScript) allow you to override global tracing settings at runtime, without restructuring your code or changing environment variables. Use conditional tracing when you need to:
  • Comply with data retention policies: Some clients may require zero data retention for compliance or privacy reasons.
  • Handle sensitive operations: Disable tracing for operations involving PII, credentials, or confidential data.
  • Implement per-tenant configurations: Route traces to different projects or apply different settings based on the customer.
  • Control costs: Disable tracing for low-value requests while maintaining visibility into critical operations.
  • Support feature flags: Enable tracing only when specific features or experimental code paths are active.
The following sections provide language-specific examples that you can adapt to your application logic and business requirements.

How tracing context works

When you use the tracing_context context manager, it overrides the global tracing configuration for code executed within its scope. This means you can keep automatic tracing enabled globally while selectively controlling tracing behavior for specific function calls.There are three priority levels of control:
  1. tracing_context(enabled=...): highest priority (context manager for scoped tracing control).
  2. ls.configure(enabled=...): global configuration (sets global tracing behavior).
  3. Environment variables: lowest priority (LANGSMITH_TRACING).

Disable tracing for specific invocations

To disable tracing for a specific operation, wrap it in a tracing_context with enabled=False:
import langsmith as ls
from langsmith import traceable

# LANGSMITH_TRACING=true is set globally

@traceable
def my_function(input_text: str):
    return process(input_text)

# Default invocation - is traced
result = my_function("regular data")

# Disable tracing for sensitive data
with ls.tracing_context(enabled=False):
    result = my_function("sensitive data")  # not traced
This pattern is useful for one-off cases where you know specific data should not be logged.

Enable conditional tracing based on business logic

You can dynamically enable or disable tracing based on runtime conditions, such as client settings or request properties.
import langsmith as ls
from langsmith import traceable

@traceable
def my_function(input_text: str):
    return process(input_text)

def client_requires_zero_retention(client_id: str) -> bool:
    """
    Check if a client has a zero-retention policy.

    In production, this would query a database, configuration service,
    or feature flag system. Consider caching results for performance.
    """
    # Example: Query from database or config
    zero_retention_clients = get_zero_retention_clients()  # Your implementation
    return client_id in zero_retention_clients

def handle_request(client_id: str, user_input: str):
    """
    Process a request with conditional tracing based on client requirements.
    """
    should_disable = client_requires_zero_retention(client_id)

    with ls.tracing_context(enabled=not should_disable):
        return my_function(user_input)

# Example usage
handle_request("client-a", "some input")  # Traced or not based on client settings

Customize tracing configuration per request

You can also customize tracing settings dynamically, such as routing traces to different projects or adding request-specific metadata.
import langsmith as ls
from langsmith import traceable

@traceable
def my_function(input_text: str):
    return process(input_text)

def handle_request(client_id: str, user_input: str, region: str):
    """
    Route traces to client-specific projects with custom metadata.
    """
    client_tier = get_client_tier(client_id)  # e.g., "enterprise", "standard"

    with ls.tracing_context(
        enabled=True,
        project_name=f"client-{client_id}",
        tags=["production", f"tier-{client_tier}", f"region-{region}"],
        metadata={
            "client_id": client_id,
            "region": region,
            "tier": client_tier
        }
    ):
        return my_function(user_input)

# Traces go to "client-abc" project with custom tags and metadata
handle_request("abc", "some input", "us-west")
This pattern is useful for:
  • Multi-tenant applications: Isolate traces by customer in separate projects
  • Regional deployments: Track performance and behavior by geographic region
  • Feature branches: Route experimental feature traces to dedicated projects
  • User segmentation: Analyze behavior by user tier, cohort, or A/B test group

Work with automatic tracing

The tracing_context context manager works with automatic tracing. You can keep LANGSMITH_TRACING=true set globally and use tracing_context to override settings for specific requests:
import os
import langsmith as ls
from langsmith import traceable

# Global environment variable set
os.environ["LANGSMITH_TRACING"] = "true"

@traceable
def process_data(data: str):
    return data.upper()

# Automatically traced (respects LANGSMITH_TRACING)
process_data("hello")

# Override global setting - disable for this call
with ls.tracing_context(enabled=False):
    process_data("sensitive")  # not traced

# Override global setting - enable with custom config
with ls.tracing_context(
    enabled=True,
    project_name="special-project"
):
    process_data("important")  # Traced to "special-project"

Nest tracing contexts

When you nest tracing_context blocks, the innermost context takes precedence.
Python
import langsmith as ls
from langsmith import traceable

@traceable
def inner_function(data: str):
    return data

@traceable
def outer_function(data: str):
    # This call respects the inner context
    return inner_function(data)

# Outer context disables tracing
with ls.tracing_context(enabled=False):
    # But inner context re-enables it
    with ls.tracing_context(enabled=True):
        outer_function("data")  # is traced
This can be useful when you want to temporarily enable tracing for debugging within a normally non-traced section.

Reusable tracing wrapper

Create a decorator to automatically apply conditional tracing logic.
Python
import functools
import langsmith as ls
from langsmith import traceable

def conditional_trace(check_function):
    """
    Decorator that conditionally traces based on a check function.

    Args:
        check_function: Function that returns True if tracing should be enabled
    """
    def decorator(func):
        traced_func = traceable(func)

        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            should_trace = check_function(*args, **kwargs)
            with ls.tracing_context(enabled=should_trace):
                return traced_func(*args, **kwargs)
        return wrapper
    return decorator

# Usage
def should_trace_client(client_id: str, *args, **kwargs) -> bool:
    return not client_requires_zero_retention(client_id)

@conditional_trace(should_trace_client)
def process_request(client_id: str, data: str):
    return data.upper()

# Automatically applies conditional tracing based on client_id
process_request("client-a", "some data")

Comparison with sampling

Conditional tracing and sampling serve different purposes:
FeatureConditional tracingSampling
ControlDeterministic (explicit enable/disable)Probabilistic (random sampling)
Use caseBusiness logic, compliance, per-request decisionsCost optimization, high-volume observability
PredictabilityGuaranteed behavior for specific requestsStatistical representation of traffic
ConfigurationRuntime code logicEnvironment variable or client config
You can combine both approaches for fine-grained control.
Connect these docs to Claude, VSCode, and more via MCP for real-time answers.