> ## Documentation Index
> Fetch the complete documentation index at: https://docs.agnost.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# LangChain (Python)

> Capture traces from LangChain / LangGraph via LangSmith's OTel mode

LangChain Python ships OTel via LangSmith. Register a `TracerProvider` pointing at Agnost **before** importing LangChain, enable LangSmith's OTel mode, then pass `session_id` / `user_id` per call.

## 1. Install

**Already have LangSmith with the OTel extra and an OTLP exporter installed?** Skip.

**No setup yet?**

```bash theme={null}
pip install "langsmith[otel]" langchain \
            opentelemetry-sdk opentelemetry-exporter-otlp-proto-http
```

## 2. Wire OTel + LangSmith pointing at Agnost

The TracerProvider must be registered **before** importing LangChain: LangSmith detects an existing provider on import and uses it.

**Already have an OTel TracerProvider?** Append Agnost as an additional span processor and switch LangSmith into OTel mode:

```python theme={null}
import os
from opentelemetry import trace
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter

trace.get_tracer_provider().add_span_processor(
    BatchSpanProcessor(
        OTLPSpanExporter(
            endpoint="https://otel.agnost.ai/v1/traces",
            headers={"X-Agnost-Org-ID": os.environ["AGNOST_ORG_ID"]},
        )
    )
)

os.environ["LANGSMITH_OTEL_ENABLED"] = "true"
os.environ["LANGSMITH_TRACING"] = "true"
os.environ["LANGSMITH_OTEL_ONLY"] = "true"  # don't ship to LangSmith's hosted backend
```

**No OTel yet?** Full setup:

```python theme={null}
import os
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter

provider = TracerProvider()
provider.add_span_processor(
    BatchSpanProcessor(
        OTLPSpanExporter(
            endpoint="https://otel.agnost.ai/v1/traces",
            headers={"X-Agnost-Org-ID": os.environ["AGNOST_ORG_ID"]},
        )
    )
)
trace.set_tracer_provider(provider)

os.environ["LANGSMITH_OTEL_ENABLED"] = "true"
os.environ["LANGSMITH_TRACING"] = "true"
os.environ["LANGSMITH_OTEL_ONLY"] = "true"

# Import LangChain AFTER the provider is registered
from langchain_openai import ChatOpenAI
```

`LANGSMITH_OTEL_ONLY=true` stops LangSmith from also shipping to its hosted dashboard: no LangSmith API key needed.

## 3. Pass user\_id / session\_id per call

```python theme={null}
result = agent.invoke(
    {"messages": [{"role": "user", "content": "Hello"}]},
    config={
        "metadata": {
            "session_id": "conv-abc123",
            "user_id": "user-42",
        },
    },
)
```

LangChain prefixes any key in `config.metadata` with `langsmith.metadata.*`: Agnost reads `langsmith.metadata.session_id` and `langsmith.metadata.user_id` natively for user / session grouping.

## References

* [Enable OpenTelemetry export](https://docs.langchain.com/langsmith/trace-with-opentelemetry)
* [Add custom metadata](https://docs.langchain.com/langsmith/add-metadata-tags)
