Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

OpenTelemetry LangChain Instrumentation

pypi

This library traces LangChain and LangGraph applications. It hooks into LangChain’s callback manager to emit spans that mirror the structure of your application:

  • Workflow spans for a graph or chain run — for example an invocation of a LangGraph StateGraph — capturing the overall input and output of the run.

  • Agent spans for agent invocations nested inside a workflow, including the agent name, id, description, and conversation/session id when available.

  • Tool spans for tool calls made during a run.

  • Retrieval spans for retriever invocations, capturing the query and retrieved document IDs and relevance scores when available.

The spans nest to reflect the graph, so a single graph invocation produces a workflow span with the agent, tool, and model calls it triggered as children.

Installation

pip install opentelemetry-instrumentation-genai-langchain

See the examples directory for runnable workflow, agent, tools, and zero-code scenarios.

Usage

Call LangChainInstrumentor().instrument() once during startup, then build and invoke your graph as usual. The example below traces a simple two-node LangGraph StateGraph (START → researcher → summariser → END); the graph.invoke(...) call is recorded as a workflow span with the node model calls nested underneath.

from typing import Annotated, TypedDict

from langchain_core.messages import HumanMessage, SystemMessage
from langchain_openai import ChatOpenAI
from langgraph.graph import END, START, StateGraph
from langgraph.graph.message import add_messages

from opentelemetry.instrumentation.genai.langchain import LangChainInstrumentor

LangChainInstrumentor().instrument()

llm = ChatOpenAI(model="<your-model>", temperature=0)


class State(TypedDict):
    messages: Annotated[list, add_messages]
    research: str


def researcher(state: State) -> dict:
    response = llm.invoke(
        [
            SystemMessage(content="Provide 2-3 factual sentences."),
            HumanMessage(content=state["messages"][-1].content),
        ]
    )
    return {"research": response.content, "messages": [response]}


def summariser(state: State) -> dict:
    response = llm.invoke(
        [
            SystemMessage(content="Condense the text into one sentence."),
            HumanMessage(content=state["research"]),
        ]
    )
    return {"messages": [response]}


builder = StateGraph(State)
builder.add_node("researcher", researcher)
builder.add_node("summariser", summariser)
builder.add_edge(START, "researcher")
builder.add_edge("researcher", "summariser")
builder.add_edge("summariser", END)
graph = builder.compile()

# Recorded as a workflow span with the two node LLM calls nested underneath.
graph.invoke(
    {
        "messages": [HumanMessage(content="What is the capital of France?")],
        "research": "",
    }
)

Retrieval Spans and Document Scores

When invoking LangChain retrievers (e.g., vectorstores, knowledge bases, or contextual compression retrievers), retrieval spans are recorded with the query and retrieved document IDs and scores.

When message content capture is enabled (OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=SPAN_ONLY or SPAN_AND_EVENT), the retrieved documents are serialized into the gen_ai.retrieval.documents span attribute using the shared RetrievalDocument model, as a JSON array of objects with only id and score. Document text (previously recorded as content) and metadata are not captured. Query text capture is unchanged.

When available, relevance and similarity scores are captured in each document object under score:

  • Direct retrieval scores: extracted from metadata["score"] (populated by retrievers such as AmazonKnowledgeBasesRetriever, TavilySearchAPIRetriever, and vectorstore score-threshold searches).

  • Reranking scores: extracted from metadata["relevance_score"] (populated when retrievers are wrapped with rerankers via ContextualCompressionRetriever, such as CohereRerank).

  • Duck-typed / custom documents: extracted from a top-level score attribute or mapping key.

If a document has no score, or if the score is non-numeric or non-finite (NaN, Infinity), score is recorded as JSON null to ensure RFC 8259 JSON compliance. Missing document IDs are also recorded as null.

Configuration

By default, prompts and completions are not captured. To capture message content, set the environment variable OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT to one of NO_CONTENT, SPAN_ONLY, EVENT_ONLY, or SPAN_AND_EVENT.

Prompts and completions can instead be uploaded to external storage via a completion hook: set OTEL_INSTRUMENTATION_GENAI_COMPLETION_HOOK=upload with OTEL_INSTRUMENTATION_GENAI_UPLOAD_BASE_PATH (install the upload extra: pip install opentelemetry-util-genai[upload]), or pass a custom CompletionHook programmatically, which takes precedence over the environment variable:

LangChainInstrumentor().instrument(completion_hook=my_hook)

Known Limitations

Context propagation to nested calls (such as auto-instrumented HTTP clients or database queries within tools) is not supported when using LangChain async API.

References

Release files for opentelemetry-instrumentation-genai-langchain 1.2b0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for opentelemetry-instrumentation-genai-langchain 1.2b0
File Size Uploaded
opentelemetry_instrumentation_genai_langchain-1.2b0.tar.gz 94.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for opentelemetry-instrumentation-genai-langchain 1.2b0
File Interpreter ABI Platform
opentelemetry_instrumentation_genai_langchain-1.2b0-py3-none-any.whl Python 3 none any Details

Total release size: 126.3 kB

Release files / opentelemetry_instrumentation_genai_langchain-1.2b0.tar.gz

Download URL opentelemetry_instrumentation_genai_langchain-1.2b0.tar.gz
Size 94.7 kB
Tags Source
SHA-256 checksum
How to use checksums
ee9ef08066a57f8cb1130932faab4d857154da28dc90286fc054e635bf7f7348
BLAKE2b-256 checksum
How to use checksums
cebf45a30d515effc8e4fdb95a1c6ffeababdf0292ff14819fd29a5d74a9c151
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log

Release files / opentelemetry_instrumentation_genai_langchain-1.2b0-py3-none-any.whl

Download URL opentelemetry_instrumentation_genai_langchain-1.2b0-py3-none-any.whl
Size 31.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ddb3cbbaa3304798a53385defc6414ae6a3ea706b3163363cd829f5bfdfbdead
BLAKE2b-256 checksum
How to use checksums
cb62ac0acbd8442d74d1778cc0b91b3adfb92b7a9834a29d363b44d4ce4ddd9a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page