Skip to main content

LLM Tracekit - LangGraph

OpenTelemetry instrumentation for LangGraph, focused on span structure and node attributes for graph runs. Use it together with LangChain, OpenAI, or other LLM instrumentors for full observability.

Span structure (3 levels)

  1. Global span — One per graph invocation. Starts when execution leaves START and ends when it reaches END. Span name: "LangGraph".
  2. Node spans — One per graph node execution, as children of the global span. Span name: "LangGraph Node <node_name>". Each node span has two attributes: node name (gen_ai.langgraph.node) and step number (gen_ai.langgraph.step, when provided by LangGraph). The node span is the current span while the node runs, so any LLM calls inside the node are traced by other instrumentors as children of that node span. Tool nodes (nodes that only run tools and do not call an LLM) get a node span too; they have no LLM child spans.
  3. LLM spans — Created by other instrumentors (LangChain, OpenAI, Gemini, etc.) when a node calls an LLM. They appear as children of the corresponding node span.

Resulting trace: LangGraph → LangGraph Node … → chat/completion (from LangChain/OpenAI/etc.) where the node runs an LLM; tool-only nodes appear as LangGraph Node <name> with no child.

Installation

pip install "llm-tracekit-langgraph"

Usage

Setting up tracing

You can use the setup_export_to_coralogix function to setup tracing and export traces to Coralogix:

from llm_tracekit.langgraph import setup_export_to_coralogix

setup_export_to_coralogix(
    service_name="ai-service",
    application_name="ai-application",
    subsystem_name="ai-subsystem",
)

Alternatively, set up tracing manually with your preferred TracerProvider and exporter.

Activation

To instrument all LangGraph runs that use LangChain's callback manager:

from llm_tracekit.langgraph import LangGraphInstrumentor

LangGraphInstrumentor().instrument()

Capturing LLM call spans

This instrumentor only creates the graph-level and node-level spans above. It does not create spans for LLM calls. To get LLM spans (model, token usage, tool calls, etc.) as children of the node span that runs the LLM:

  • Use LangChain: llm-tracekit-langchain and LangChainInstrumentor().instrument(...) in addition to LangGraphInstrumentor().instrument(...). Both can run together; LangChain will create child spans under the current (node) span.
  • Or use provider-specific instrumentors (OpenAI, Bedrock, etc.) instead of or alongside LangChain.

Install and activate the extra instrumentor(s) you need. The same tracer provider can be passed to all of them. LLM spans will appear under the correct node span because the node span is set as the current span while the node runs.

Uninstrument

LangGraphInstrumentor().uninstrument()

Full example

Minimal graph (no LLM):

from langgraph.graph import StateGraph, START, END
from langgraph.checkpoint.memory import MemorySaver

from llm_tracekit.langgraph import LangGraphInstrumentor, setup_export_to_coralogix

setup_export_to_coralogix(service_name="ai-service")

LangGraphInstrumentor().instrument()

def node_a(state: dict) -> dict:
    return {"messages": state.get("messages", []) + ["A"]}

def node_b(state: dict) -> dict:
    return {"messages": state.get("messages", []) + ["B"]}

graph = StateGraph(dict)
graph.add_node("a", node_a)
graph.add_node("b", node_b)
graph.add_edge(START, "a")
graph.add_edge("a", "b")
graph.add_edge("b", END)

app = graph.compile(checkpointer=MemorySaver())
result = app.invoke({"messages": []}, config={"configurable": {"thread_id": "1"}})

Manual handler

You can also add the handler explicitly when invoking a graph (e.g. for testing or when not using the instrumentor):

from llm_tracekit.langgraph.callback import LangGraphCallbackHandler

tracer = tracer_provider.get_tracer(__name__)
handler = LangGraphCallbackHandler(tracer=tracer)
result = app.invoke(initial_state, config={"callbacks": [handler], "configurable": {"thread_id": "1"}})

Semantic Conventions

Node span attributes

Attribute Type Description Examples
gen_ai.langgraph.node string The name of the LangGraph node being executed agent, tools
gen_ai.langgraph.step int Step counter for this node execution within the graph run 1, 2
gen_ai.request.user string A unique identifier representing the end-user (from config={"metadata": {"user": "..."}} or config={"configurable": {"user": "..."}}) user@company.com

Passing user identity

Pass the user identifier in either the metadata dict or the configurable dict of the LangGraph config:

# Option 1: via metadata (preferred)
result = app.invoke(
    {"messages": [HumanMessage(content="Hello")]},
    config={
        "configurable": {"thread_id": "1"},
        "metadata": {"user": "user@company.com"},
    },
)

# Option 2: via configurable (also supported)
result = app.invoke(
    {"messages": [HumanMessage(content="Hello")]},
    config={
        "configurable": {"thread_id": "1", "user": "user@company.com"},
    },
)

Metadata

Release files for llm-tracekit-langgraph 1.3.0

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

Source distribution (sdist)

Source distribution for llm-tracekit-langgraph 1.3.0
File Size Uploaded
llm_tracekit_langgraph-1.3.0.tar.gz 11.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for llm-tracekit-langgraph 1.3.0
File Interpreter ABI Platform
llm_tracekit_langgraph-1.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 27.0 kB

Release files / llm_tracekit_langgraph-1.3.0.tar.gz

Download URL llm_tracekit_langgraph-1.3.0.tar.gz
Size 11.2 kB
Tags Source
SHA-256 checksum
How to use checksums
5cad8fb448ddf4e4d7489be4f24c2150869e0aa0831ebcc603243eb020bf33ac
BLAKE2b-256 checksum
How to use checksums
2a72144c15519a74b2fe74ed7fe9495323d6adf15b60726af00431db5f14cfe2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.11.5 {"installer":{"name":"uv","version":"0.11.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / llm_tracekit_langgraph-1.3.0-py3-none-any.whl

Download URL llm_tracekit_langgraph-1.3.0-py3-none-any.whl
Size 15.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
cd584be225501fc69cde487e85b741b1b8cc195bdef834c32b2f1d1edac4de61
BLAKE2b-256 checksum
How to use checksums
5ecb703fab4d0e9d395b8e5b6328fa870b8ed01f883248eac68925afe41474b6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.11.5 {"installer":{"name":"uv","version":"0.11.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

1.3.0 This release

2 release files

1.2.0

2 release files

1.1.0

2 release files

1.0.0

2 release files

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