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).

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.

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.

Configure for the Messages view

If you’re sending traces to LangSmith via OpenTelemetry, configure your spans so the Messages view can render your traces correctly. Two things are required:
  • Set ls_message_format in span metadata so LangSmith knows how to parse the message format.
  • Structure tool spans so LangSmith can associate them with the LLM call that triggered them.

Inputs and outputs

Span attribute conventions differ by span type:
  • Chain spans: use gen_ai.prompt for inputs and gen_ai.completion for outputs.
  • Tool spans: use gen_ai.tool.call.arguments for inputs and gen_ai.tool.call.result for outputs.
  • LLM spans: captured automatically by your instrumentation library (for example, traceanthropic); no manual attribute setting is needed.

Tool call association

LangSmith uses one of two strategies to associate tool runs with the LLM call that triggered them.
  • Tool call ID matching is the default for OpenAI APIs. The LLM run’s output must contain tool_calls entries with IDs, and each corresponding tool run’s output must reference the matching tool call ID. This happens automatically when you log the raw OpenAI API response as the LLM run output.
  • Adjacency matching by tool name is the default for Anthropic. LangSmith matches tool runs to the preceding LLM run by name and position in the trace. The only requirement is that tool spans are flushed after the LLM span ends.

Example: Go SDK with Anthropic

The following example uses the LangSmith Go SDK’s OTel tracer with traceanthropic auto-instrumentation, which automatically captures each messages.New call as an LLM span. Tool spans are created manually after the LLM call, satisfying the adjacency requirement. Root span:
langsmith.span.kind = "chain" marks this as an agent run, which becomes the outer container in the Messages view that groups all messages for the turn. ls_message_format = "anthropic" is required. Without it, LangSmith won’t parse the Anthropic message format and the Messages view won’t render. The three session ID attributes link turns together as a single conversation thread. Tool-use loop: tool spans are created after messages.New returns:
Because runToolCalls runs after messages.New returns, tool spans are created after the LLM span ends. This is what enables adjacency matching: LangSmith sees the tool spans following the LLM span in the trace timeline and nests them under the assistant message that triggered them in the Messages view. Tool span:
The span name (toolUse.Name) appears as the tool name in the tool call card in the Messages view. gen_ai.tool.call.result populates the result shown in the card. Call toolSpan.End() explicitly rather than deferring it so each tool span closes before the next LLM call begins, keeping the trace timeline correct for adjacency matching. For a complete working example, see the langsmith-go-messages-view-demo repository.

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

Set up distributed tracing with LangChain

To enable distributed tracing across multiple services: