Langflow Tracing and Observability Integrations: Complete Guide to LangSmith, LangFuse, and More

Langflow natively supports seven observability platforms—including LangSmith, LangFuse, LangWatch, Opik, Arize Phoenix, and Traceloop—through a modular tracing service that automatically activates when specific environment variables are present.

The langflow-ai/langflow repository implements a comprehensive tracing and observability system in src/backend/base/langflow/services/tracing/ that forwards execution data from flow runs to third-party monitoring backends. This architecture requires no application code changes; integrations activate automatically based on environment configuration, using an abstract BaseTracer contract to standardize telemetry collection across diverse platforms.

Supported Observability Integrations

Langflow's TracingService detects and initializes tracer implementations based on the presence of vendor-specific environment variables. Each integration implements the BaseTracer interface defined in src/backend/base/langflow/services/tracing/base.py.

LangSmith

Activation: Set LANGCHAIN_API_KEY. Langflow automatically injects LANGCHAIN_TRACING_V2="true".

Implementation: The LangSmithTracer class in src/backend/base/langflow/services/tracing/langsmith.py constructs run trees and component spans using the LangSmith client. It converts internal Langflow Message and Data objects to LangChain-compatible types via _convert_to_langchain_types.

LangFuse

Activation: Define LANGFUSE_SECRET_KEY, LANGFUSE_PUBLIC_KEY, and LANGFUSE_HOST.

Implementation: LangFuseTracer (located in src/backend/base/langflow/services/tracing/langfuse.py) creates hierarchical spans with inputs, outputs, metadata, and error information using self.trace.span() calls.

LangWatch

Activation: Set LANGWATCH_API_KEY and optionally LANGWATCH_ENDPOINT.

Implementation: The LangWatchTracer in src/backend/base/langflow/services/tracing/langwatch.py exports OpenTelemetry spans to LangWatch’s OTLP endpoint, converting data via _convert_to_langwatch_types.

Opik

Activation: Configure OPIK_PROJECT_NAME and ensure valid Opik client configuration is present.

Implementation: OpikTracer (src/backend/base/langflow/services/tracing/opik.py) manages trace and span objects with distributed-header propagation support.

Arize Phoenix

Activation: Provide ARIZE_PHOENIX_API_KEY and ARIZE_PHOENIX_ENDPOINT.

Implementation: The ArizePhoenixTracer in src/backend/base/langflow/services/tracing/arize_phoenix.py implements a span processor that forwards telemetry to Arize Phoenix endpoints.

Traceloop

Activation: Set TRACEELOOP_API_KEY.

Implementation: TraceloopTracer (src/backend/base/langflow/services/tracing/traceloop.py) provides automatic LangChain-compatible instrumentation via the Traceloop SDK.

Minimal LFX Tracing

Fallback behavior: When deactivate_tracing is disabled and no external variables are set, the system uses a minimal in-process tracer defined in src/lfx/src/lfx/services/tracing/service.py for local log entries.

Internal Architecture and Data Flow

The BaseTracer Contract

All integrations inherit from BaseTracer in src/backend/base/langflow/services/tracing/base.py, which defines the interface for add_trace, set_outputs, end_trace, and get_langchain_callbacks. This abstraction allows TracingService to remain agnostic to specific vendor implementations.

TraceContext and Async Processing

When a graph run starts, TracingService.create_trace_context() instantiates a TraceContext object containing:

  • run_id, run_name, user_id, session_id
  • A per-run async queue (traces_queue)
  • A dictionary of active tracers

The service spawns a background _trace_worker that drains the queue sequentially, ensuring network I/O does not block graph execution. All tracer method calls are enqueued via TraceContext.traces_queue.put_nowait().

Lazy Initialization Pattern

The TracingService._start() method in src/backend/base/langflow/services/tracing/service.py lazily instantiates tracers through helper methods like _initialize_langsmith_tracer() and _initialize_langfuse_tracer(). Each helper checks for required environment variables and SDK availability:

def _initialize_langsmith_tracer(self, ctx):
    if not os.getenv("LANGCHAIN_API_KEY"):
        return
    ctx.tracers["langsmith"] = _get_langsmith_tracer()(
        trace_name=ctx.run_name,
        trace_type="chain",
        project_name=ctx.project_name,
        trace_id=ctx.run_id,
    )

If import or authentication fails, the tracer sets _ready = False and is silently omitted from the active tracer list.

Metadata Conversion

Concrete tracers implement conversion helpers to transform Langflow internal types:

  • _convert_to_langchain_types() for LangSmith compatibility
  • _convert_to_opik_types() for Opik traces
  • _convert_to_langwatch_types() for LangWatch spans

These methods recursively process Message, Data, and arbitrary Python objects into JSON-serializable dictionaries or vendor-specific message formats.

Configuring Tracing Integrations

Enable observability by setting environment variables before starting Langflow. No code changes are required.

Enabling LangSmith

export LANGCHAIN_API_KEY="sk-your-key"

# LANGCHAIN_TRACING_V2 is automatically set by Langflow

Enabling LangFuse

export LANGFUSE_PUBLIC_KEY="public-key"
export LANGFUSE_SECRET_KEY="secret-key"
export LANGFUSE_HOST="https://cloud.langfuse.com"

Enabling LangWatch

export LANGWATCH_API_KEY="your-api-key"
export LANGWATCH_ENDPOINT="https://api.langwatch.com"  # Optional

Programmatic Tracing API

For custom instrumentation within components, use the TracingService directly.

Manual Trace Context Management

from langflow.services.tracing.service import TracingService
from uuid import uuid4

# Initialize service with settings that do not deactivate tracing

tracing = TracingService(settings_service=my_settings)

# Start a run session

run_id = uuid4()
await tracing.start_tracers(
    run_id=run_id,
    run_name="example-run",
    user_id="user-123",
    session_id="sess-abc",
    project_name="demo-proj",
)

# Trace component execution

async with tracing.trace_component(
    component=my_component,
    trace_name="my-component",
    inputs={"query": "user input"},
) as ctx:
    result = await my_component.run()
    tracing.set_outputs("my-component", {"result": result})

Adding Custom Logs

import time

tracing.add_log("my-component", {
    "event": "processing_started",
    "timestamp": time.time(),
    "metadata": {"batch_size": 10}
})

Error Handling

Errors are automatically captured via _error_to_string() methods that serialize stack traces into the trace metadata before end_trace() finalizes the span.

Summary

  • Langflow provides seven production-ready observability integrations through a unified tracing architecture in src/backend/base/langflow/services/tracing/.
  • The modular design uses BaseTracer abstractions and lazy initialization based on environment variable detection.
  • Zero-code configuration activates tracers like LangSmith (LANGCHAIN_API_KEY) and LangFuse (LANGFUSE_SECRET_KEY) automatically.
  • Async queue processing ensures telemetry export does not block flow execution, managed by TraceContext and _trace_worker.
  • Metadata conversion helpers normalize Langflow's internal Message and Data types to vendor-specific formats.
  • Programmatic access via trace_component() context managers allows custom instrumentation within component logic.

Frequently Asked Questions

How do I enable LangSmith tracing in Langflow?

Set the LANGCHAIN_API_KEY environment variable. Langflow automatically detects this in TracingService._initialize_langsmith_tracer() and instantiates the LangSmithTracer class. The system also injects LANGCHAIN_TRACING_V2="true" automatically. No code changes are required within your flows.

What is the difference between LangSmith and LangFuse integrations?

LangSmith focuses on LangChain-compatible run trees and uses _convert_to_langchain_types() for data serialization, requiring only LANGCHAIN_API_KEY. LangFuse provides hierarchical span management with explicit input/output tracking via self.trace.span() calls, requiring three variables: LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY, and LANGFUSE_HOST. LangFuse also captures more granular metadata by default.

Can I use multiple tracing providers simultaneously?

Yes. TracingService maintains a dictionary of active tracers in TraceContext.tracers. If you set environment variables for multiple providers (e.g., both LangSmith and LangFuse), both tracers initialize and receive identical trace data through the async queue. Each tracer processes the data independently according to its vendor-specific conversion logic.

Where are the tracer implementations located in the codebase?

Concrete implementations reside in src/backend/base/langflow/services/tracing/:

The abstract contract is defined in base.py, while the central orchestration logic lives in service.py.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →