Skip to main content

LangChain & LangGraph OpenTelemetry Integration

Overview

This integration provides comprehensive OpenTelemetry instrumentation for both LangChain and LangGraph frameworks. It enables detailed tracing and monitoring of applications built with these frameworks.

Installation

Install traceAI LangChain

pip install traceAI-langchain

For LangGraph support (optional)

pip install traceAI-langchain[langgraph]

Install LangChain OpenAI

pip install langchain-openai

Environment Variables

Set up your environment variables to authenticate with FutureAGI.

import os

os.environ["FI_API_KEY"] = FI_API_KEY
os.environ["FI_SECRET_KEY"] = FI_SECRET_KEY
os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY

LangChain Quickstart

Register Tracer Provider

Set up the trace provider to establish the observability pipeline:

from fi_instrumentation import register
from fi_instrumentation.fi_types import ProjectType

trace_provider = register(
    project_type=ProjectType.OBSERVE,
    project_name="langchain_app",
    session_name="chat-bot"
)

Configure LangChain Instrumentation

Instrument the LangChain client to enable telemetry collection:

from traceai_langchain import LangChainInstrumentor

LangChainInstrumentor().instrument(tracer_provider=trace_provider)

Create LangChain Components

Set up your LangChain client with built-in observability:

from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate

prompt = ChatPromptTemplate.from_template("{x} {y} {z}?").partial(x="why is", z="blue")
chain = prompt | ChatOpenAI(model_name="gpt-3.5-turbo")

def run_chain():
    try:
        result = chain.invoke({"y": "sky"})
        print(f"Response: {result}")
    except Exception as e:
        print(f"Error executing chain: {e}")

if __name__ == "__main__":
    run_chain()

LangGraph Instrumentation

LangGraph tracing is automatic: LangGraph runs each node, tool and LLM through LangChain's callback system, so LangChainInstrumentor captures them with no LangGraph-specific setup. You get:

  • Per-node spans named after the graph node (agent, tools, ask_human, …)
  • Tool and LLM spans nested under their node
  • Graph-node enrichment — the node's own span carries gen_ai.agent.graph.node_name and gen_ai.agent.graph.node_id
  • Session grouping — LangGraph's configurable.thread_id becomes session.id on every span (an explicit using_session(...) or metadata={"session_id": ...} wins). New in 0.2.1; with 0.2.0 or earlier, wrap the call in using_session(thread_id).
  • HITL interrupts traced correctly — an interrupted node/tool span stays OK (not ERROR) and is marked with langgraph.interrupt

LangGraphInstrumentor is a deprecated no-op kept for backwards compatibility. You can remove any LangGraphInstrumentor().instrument() call — tracing happens through LangChainInstrumentor.

LangGraph Quickstart

from typing import Annotated, TypedDict
from fi_instrumentation import register
from fi_instrumentation.fi_types import ProjectType
from fi_instrumentation.instrumentation.context_attributes import using_session
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
from traceai_langchain import LangChainInstrumentor

class MyState(TypedDict):
    messages: Annotated[list, add_messages]

trace_provider = register(
    project_type=ProjectType.OBSERVE,
    project_name="langgraph_app",
)

# Instrument LangChain — LangGraph is traced through it automatically.
LangChainInstrumentor().instrument(tracer_provider=trace_provider)

workflow = StateGraph(MyState)
workflow.add_node("agent", agent_node)   # sync or async nodes both work
workflow.add_edge(START, "agent")
workflow.add_edge("agent", END)
app = workflow.compile()

# Group every span of a conversation under one session:
with using_session("thread-123"):
    result = app.invoke(
        {"messages": []}, {"configurable": {"thread_id": "thread-123"}}
    )

LangGraph Span Attributes

Node, tool and LLM runs are standard LangChain spans (gen_ai.span.kind = CHAIN / TOOL / LLM / AGENT) with these LangGraph additions:

  • gen_ai.agent.graph.node_name, gen_ai.agent.graph.node_id — the graph node (on the node's own span)
  • langgraph_node, langgraph_step, langgraph_triggers, langgraph_path, langgraph_checkpoint_ns — LangGraph's raw callback metadata
  • session.id — from config={"metadata": {"session_id": ...}}, else using_session(...), else LangGraph's configurable.thread_id (0.2.1 and later; a blank thread_id sets nothing). The choice is made per run: set an explicit session around the whole invoke/stream, because a session set for only part of a run (inside a node, or in an inner with_config) covers only the runs inside it, and the outer spans fall back to thread_id.
  • langgraph.interrupt (attribute + event) on a HITL pause; a langgraph.resume event on resume

Deep Agents

Deep Agents builds a LangGraph graph with create_deep_agent. There is no Deep Agents instrumentor and no separate package: LangChainInstrumentor traces the graph, its model calls, its built-in tools and its task subagents. The cookbook is examples/deep_agents.py; the compatibility test (tests/test_deepagents_compat.py) runs that same script offline against a scripted fake model and a loopback collector.

Tested versions, as printed by the compatibility test:

Package Version
deepagents 0.7.21 (PyPI wheel); 0.7.23 and 0.7.28 (latest on 2026-10-16) also pass
langchain 1.4.3; 1.4.4 with deepagents 0.7.23
langchain-core 1.6.6 (the floor deepagents 0.7.21 requires); 1.6.9 and 1.6.12 (latest) also pass
langgraph 1.2.12; 1.2.14 and 1.2.16 (latest) also pass
langgraph-prebuilt as resolved with langgraph 1.2.12 (printed by the test), and 1.1.0 with langgraph 1.2.14; its ToolNode re-raises tool errors
traceAI-langchain 0.2.1 (tested from this repository before release): the thread_id → session.id change is not in 0.2.0
Python 3.11.12 and 3.13.7; 3.13.15 with deepagents 0.7.28; 3.12 with deepagents 0.7.23

traceAI-langchain's own lower bound (langchain-core>=0.2.43) is unchanged. Deep Agents itself needs langchain-core>=1.6.6 and langgraph.

pip install "traceAI-langchain>=0.2.1" "deepagents==0.7.21" langgraph

With traceAI-langchain 0.2.0 or earlier, thread_id is not copied to session.id: upgrade, or wrap the call in using_session(thread_id).

from deepagents import create_deep_agent
from deepagents.backends import StateBackend
from fi_instrumentation import TraceConfig, register
from fi_instrumentation.fi_types import ProjectType
from traceai_langchain import LangChainInstrumentor

# 1. register(), 2. instrument(), 3. build the agent.
trace_provider = register(project_type=ProjectType.OBSERVE, project_name="deep-agents-app")
LangChainInstrumentor().instrument(
    tracer_provider=trace_provider,
    # Filesystem tool arguments and results can contain file contents.
    config=TraceConfig(hide_inputs=True, hide_outputs=True),
)

# Pass a model explicitly: model=None selects the deprecated claude-sonnet-4-6 default.
agent = create_deep_agent(model=model, tools=[my_tool], backend=StateBackend())
result = agent.invoke(
    {"messages": [{"role": "user", "content": "..."}]},
    config={"configurable": {"thread_id": "t-1"}},  # becomes session.id (0.2.1+; with 0.2.0 use using_session)
)
trace_provider.force_flush()

What you get (all from traceAI-langchain; Deep Agents adds no keys):

  • LLM spans with gen_ai.request.model and gen_ai.usage.* from the model's usage_metadata. Token counts are only on LLM spans, so a trace's token total is the sum of its model calls.
  • TOOL spans named after the tool that ran. With the default StateBackend, 0.7.21 binds ls, read_file, write_file, edit_file, delete, glob, grep and task, plus your tools. execute is bound only for a sandbox backend. write_todos is not a default tool at this version; harness profiles can add tools (the OpenAI Codex profile adds write_todos for openai:gpt-5.x-codex models).
  • Subagents: the task TOOL span is the parent of the subagent's span (named after the subagent, e.g. general-purpose, kind CHAIN) and of its model and tool spans, all in one trace. Subagent spans also carry lc_agent_name.
  • Graph nodes (model, tools, middleware nodes) are CHAIN spans; a node whose name contains "agent" (e.g. PatchToolCallsMiddleware.before_agent) is reported as AGENT by the existing name heuristic.
  • Session: configurable.thread_id → session.id on every span, subagents included (0.2.1 and later; see the session note above).
  • Errors: a tool that raises ends its TOOL span ERROR with an exception event (LangGraph's default tool error handler re-raises, so invoke raises too). The status description is the exception message, without a traceback. Stacktraces remain in exception events only when error details are visible. With core 1.2.0+, TraceConfig.hide_error_details controls this: content-hide flags derive it by default, and an explicit False keeps error details. With older core versions, hide_inputs=True or hide_outputs=True also hides error details. Hidden failures keep their exception type, but no status description, message, stacktrace or provider-error output (body, response headers or request ids). Cancelling an astream early closes every span; the root span ends ERROR with a GeneratorExit exception event (asserted by the compatibility test).
  • CI: the Deep Agents job installs the real deepagents==0.7.21 wheel and runs the compatibility, session and error-policy tests with the current core. It also checks input/output privacy and sessions against published core 1.1.0.

Not emitted: cost, user id (set using_attributes(user_id=...) yourself), retrieval (Deep Agents has no retriever tool), and a gen_ai.provider.name (LangChain's raw ls_provider metadata is passed through as-is).


Examples

LangChain Examples

  • examples/chat_prompt_template.py - Basic chat prompt usage
  • examples/rag.py - Retrieval-augmented generation
  • examples/tool_calling_agent.py - Agent with tools
  • examples/openai_chat_stream.py - Streaming responses

LangGraph Examples

  • examples/langgraph_simple_workflow.py - Simple state machine workflow
  • examples/langgraph_agent_supervisor.py - Multi-agent supervisor pattern
  • examples/langgraph_human_in_the_loop.py - Human-in-the-loop interrupt workflow

Deep Agents Example

  • examples/deep_agents.py - create_deep_agent with a custom tool, built-in file tools and a task subagent (runs offline)

API Reference

LangChainInstrumentor

from traceai_langchain import LangChainInstrumentor

# Initialize and instrument
instrumentor = LangChainInstrumentor()
instrumentor.instrument(tracer_provider=trace_provider)

# Get current span
span = instrumentor.get_span(run_id)

# Get ancestor spans
ancestors = instrumentor.get_ancestors(run_id)

LangGraphInstrumentor

from traceai_langchain import LangGraphInstrumentor

# Deprecated no-op — LangGraph is traced automatically by LangChainInstrumentor.
# instrument() only logs a one-time deprecation notice; you can remove this call.
LangGraphInstrumentor().instrument(tracer_provider=trace_provider)

Troubleshooting

LangGraph not being traced

  1. Make sure you instrumented LangChainInstrumentor — LangGraph is traced through it (LangGraphInstrumentor is a no-op).
  2. Install the langgraph extra if you use LangGraph: pip install traceAI-langchain[langgraph].
  3. Check that langgraph is installed: pip show langgraph.

Metadata

Release files for traceAI-langchain 0.2.2

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

Source distribution (sdist)

Source distribution for traceAI-langchain 0.2.2
File Size Uploaded Provenance Actions
traceai_langchain-0.2.2.tar.gz 26.4 kB With provenance Details for traceai_langchain-0.2.2.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for traceAI-langchain 0.2.2
File Interpreter ABI Platform Actions
traceai_langchain-0.2.2-py3-none-any.whl Python 3 none any Details for traceai_langchain-0.2.2-py3-none-any.whl

Total release size: 51.0 kB

Release files / traceai_langchain-0.2.2.tar.gz

Download URL traceai_langchain-0.2.2.tar.gz
Size 26.4 kB
Tags Source
SHA-256 checksum
How to use checksums
ed2e172ca5eac9e4cf4ffe0d233eb74858d42a4acb5af37e0b4661931bccc581
BLAKE2b-256 checksum
How to use checksums
ffd8fff7c1194115d93b6a50e497b66774e93e3a41fce2934c69222db4c2c941
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Nov 10, 2026.

Transparency log

Release files / traceai_langchain-0.2.2-py3-none-any.whl

Download URL traceai_langchain-0.2.2-py3-none-any.whl
Size 24.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c75c9a3a8fd36045d68f08fcd5b671fc64fb9506c2be2dbe43617d0e7e45ce47
BLAKE2b-256 checksum
How to use checksums
d6b15fc28eb47221b52171f4f05b1a124cd5cd4f30db28420d99570331e2c4ae
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Nov 10, 2026.

Transparency log

Security for traceAI-langchain 0.2.2

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.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for traceai_langchain-0.2.2.tar.gz

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 Nov 10, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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