Skip to main content
LangSmith supports OpenTelemetry-based tracing, allowing you to send traces from any OpenTelemetry-compatible application. This guide covers both automatic instrumentation for LangChain applications and manual instrumentation for other frameworks. Learn how to trace your LLM applications using OpenTelemetry with LangSmith.
Update the LangSmith URL appropriately for self-hosted installations or regional SaaS in the requests below: GCP EU uses eu.api.smith.langchain.com; GCP APAC uses apac.api.smith.langchain.com; AWS US uses aws.api.smith.langchain.com.

Trace a LangChain application

If you’re using LangChain or LangGraph, use the built-in integration to trace your application:
  1. Install the LangSmith package with OpenTelemetry support:
    Requires Python SDK version langsmith>=0.3.18. We recommend langsmith>=0.4.25 to benefit from important OpenTelemetry fixes.
  2. In your LangChain/LangGraph App, enable the OpenTelemetry integration by setting the LANGSMITH_OTEL_ENABLED environment variable:
  3. Create a LangChain application with tracing. For example:
  4. View the traces in your LangSmith dashboard (example) once your application runs.

Trace a non-LangChain application

For non-LangChain applications or custom instrumentation, you can trace your application in LangSmith with a standard OpenTelemetry client. (We recommend langsmith ≥ 0.4.25.)
  1. Install the OpenTelemetry SDK, OpenTelemetry exporter packages, as well as the OpenAI package:
  2. Setup environment variables for the endpoint, substitute your specific values:
    Depending on how your otel exporter is configured, you may need to append /v1/traces to the endpoint if you are only sending traces.
    If you’re self-hosting LangSmith, replace the base endpoint with your LangSmith api endpoint and append /api/v1. For example: OTEL_EXPORTER_OTLP_ENDPOINT=https://ai-company.com/api/v1/otel
    Optional: Specify a custom project name other than “default”:
  3. Log a trace. This code sets up an OTEL tracer and exporter that will send traces to LangSmith. It then calls OpenAI and sends the required OpenTelemetry attributes.
  4. View the trace in your LangSmith dashboard (example).
If your spans reference a parent from another service or process, see Context propagation in distributed tracing for how parent–child linking works and when a span can be dropped.

Send traces to an alternate provider

While LangSmith is the default destination for OpenTelemetry traces, you can also configure OpenTelemetry to send traces to other observability platforms.
Available in LangSmith Python SDK ≥ 0.4.1. We recommend ≥ 0.4.25 for fixes that improve OTEL export and hybrid fan-out stability.

Use environment variables for global configuration

By default, the LangSmith OpenTelemetry exporter will send data to the LangSmith API OTEL endpoint, but this can be customized by setting standard OTEL environment variables:
LangSmith uses the HTTP trace exporter by default. If you’d like to use your own tracing provider, you can either:
  1. Set the OTEL environment variables as shown above, or
  2. Set a global trace provider before initializing LangChain components, which LangSmith will detect and use instead of creating its own.

Configure alternate OTLP endpoints

To send traces to a different provider, configure the OTLP exporter with your provider’s endpoint:
Hybrid tracing is available in version ≥ 0.4.1. To send traces only to your OTEL endpoint, set:LANGSMITH_OTEL_ONLY="true" (Recommendation: use langsmith ≥ 0.4.25.)

Supported OpenTelemetry attribute and event mapping

When sending traces to LangSmith via OpenTelemetry, the following attributes are mapped to LangSmith fields:

Core LangSmith attributes

GenAI standard attributes

GenAI request parameters

GenAI usage metrics

TraceLoop attributes

OpenInference attributes

LLM attributes

Prompt template attributes

Retriever attributes

Tool attributes

Logfire attributes

OpenTelemetry event mapping

Event attribute extraction

For message events, the following attributes are extracted:
  • content → message content
  • role → message role
  • id → tool_call_id (for tool messages)
  • gen_ai.event.content → full message JSON
For choice events:
  • finish_reason → choice finish reason
  • message.content → choice message content
  • message.role → choice message role
  • tool_calls.{n}.id → tool call ID
  • tool_calls.{n}.function.name → tool function name
  • tool_calls.{n}.function.arguments → tool function arguments
  • tool_calls.{n}.type → tool call type
For exception events:
  • exception.message → error message
  • exception.stacktrace → error stacktrace (appended to message)

Implementation examples

Trace using the LangSmith SDK

Use the LangSmith SDK’s OpenTelemetry helper to configure export. The following example traces a Google ADK agent:
You do not need to set OTEL environment variables or exporters. configure() wires them for LangSmith automatically; instrumentors (like GoogleADKInstrumentor) create the spans.
Here is an example of what the resulting trace looks like in LangSmith. Native OTLP parentSpanId can’t reference an existing LangSmith run: an OTLP span ID is 8 bytes, while LangSmith run IDs are full UUIDs. To attach an OpenTelemetry span to a run created elsewhere (for example, a LangChain-SDK run), set the langsmith.* attributes with the parent’s full UUIDs. They override the IDs derived from the native OTLP span, so the span nests under the existing run in the same trace.
langsmith.span.dotted_order encodes the span’s position in the trace tree. Build it from the parent’s dotted_order, a dot, then this span’s timestamp followed by its langsmith.span.id.

Add an attachment to a trace

LangSmith supports attaching files to traces. This is useful when building an agent with multimodal inputs or outputs. Attachments are also supported when tracing with OpenTelemetry. The example below traces a Google ADK agent and adds an attachment to the trace. It uses a combination of LangSmith’s OtelSpanProcessor and a custom AttachmentSpanProcessor that uses on_end() to add an image attachment to the parent span.
Here is an example of what the resulting trace looks like in LangSmith.

Advanced configuration

Use OpenTelemetry collector for fan-out

Use LANGSMITH_OTEL_ENABLED=true when you need OTEL fanout. Configure your application to emit OTEL spans once, then use an OpenTelemetry Collector to route them to LangSmith and any additional observability backends. Use this approach when you are tracing applications and want multi-destination routing. If you are operating LangSmith platform infrastructure telemetry (logs, metrics, traces from self-hosted LangSmith services on Kubernetes), use the Configure your collector for LangSmith telemetry guide instead. For more advanced scenarios, you can use the OpenTelemetry Collector to fan out your telemetry data to multiple destinations. This is a more scalable approach than configuring multiple exporters in your application code.
  1. Install the OpenTelemetry Collector for your environment.
  2. Create a configuration file (e.g., otel-collector-config.yaml) that exports to multiple destinations:
  3. Configure your application to send to the collector:
This approach offers several advantages:
  • Centralized configuration for all your telemetry destinations
  • Reduced overhead in your application code
  • Better scalability and resilience
  • Ability to add or remove destinations without changing application code

Distributed tracing with LangChain and OpenTelemetry

Distributed tracing is essential when your LLM application spans multiple services or processes. OpenTelemetry’s context propagation capabilities ensure that traces remain connected across service boundaries.

Context propagation in distributed tracing

In distributed systems, context propagation passes trace metadata between services so that related spans are linked to the same trace:
  • Trace ID: A unique identifier for the entire trace
  • Span ID: A unique identifier for the current span
  • Sampling Decision: Indicates whether this trace should be sampled
A span whose parent is never sent to LangSmith is dropped.The OTel endpoint is asynchronous: it accepts a batch, returns 200, and materializes runs in the background. When a span’s parentSpanId references a parent that LangSmith hasn’t received yet, the child is buffered and linked once the parent arrives. This works regardless of order; a child can arrive before its parent, in a separate request, and still link correctly.However, if the parent span is never exported to LangSmith, the buffered child expires and never appears as a run. LangSmith will not return an error, because the 200 was sent before processing. This commonly happens when only part of a distributed trace reaches LangSmith: the parent is emitted by a service that exports to a different backend, or it’s removed by a sampling decision.To avoid silent loss, make sure every span you want in LangSmith also has its ancestors exported to LangSmith within the buffering window. On self-hosted deployments, this window is controlled by REDIS_RUNS_EXPIRY_SECONDS (default 12 hours).

Set up distributed tracing with LangChain

To enable distributed tracing across multiple services: