LangGraph (tracing)

LangGraph is a framework for building stateful, multi-step agent workflows as graphs. Nodes represent operations such as LLM calls, tools, and routing decisions, while edges define the flow between them. Respan gives you full observability over every graph run, node, tool call, and LLM generation — and gateway routing through the OpenAI-compatible Respan endpoint.

Create an account at platform.respan.ai and grab an API key.

Run npx @respan/cli setup to set up with your coding agent.

See LangGraph gateway setup to route this integration through the Respan gateway.

Setup

1

Install packages

$pip install respan-tracing respan-instrumentation-langchain langgraph langchain-openai python-dotenv
2

Set environment variables

$export RESPAN_API_KEY="YOUR_RESPAN_API_KEY"
$export RESPAN_BASE_URL="https://api.respan.ai/api"

RESPAN_API_KEY is used to export traces to Respan. Set OPENAI_API_KEY too when graph nodes call provider-backed models.

3

Initialize and run

Use respan-instrumentation-langchain for LangGraph because LangGraph runs through LangChain callback managers.

1import os
2from contextlib import suppress
3from typing import TypedDict
4
5from langgraph.graph import StateGraph, START, END
6from respan_instrumentation_langchain import add_respan_callback
7from respan_tracing import RespanTelemetry
8
9telemetry = RespanTelemetry(
10 app_name="langgraph-quickstart",
11 api_key=os.environ["RESPAN_API_KEY"],
12 base_url=os.getenv("RESPAN_BASE_URL", "https://api.respan.ai/api"),
13 is_auto_instrument=False,
14 is_batching_enabled=False,
15)
16
17class State(TypedDict):
18 topic: str
19 joke: str
20
21def generate_joke(state: State) -> dict:
22 return {"joke": f"A short joke about {state['topic']}"}
23
24graph = StateGraph(State)
25graph.add_node("generate", generate_joke)
26graph.add_edge(START, "generate")
27graph.add_edge("generate", END)
28
29app = graph.compile()
30try:
31 result = app.invoke(
32 {"topic": "AI tracing"},
33 config=add_respan_callback(
34 {
35 "run_name": "joke_graph",
36 "tags": ["langgraph", "quickstart"],
37 "metadata": {"framework": "langgraph"},
38 }
39 ),
40 )
41 print(result)
42finally:
43 with suppress(Exception):
44 telemetry.flush()
4

View your trace

Open the Traces page to see the graph execution with node spans, LLM calls, and state transitions.

Configuration

ParameterTypeDefaultDescription
api_keystr | NoneNoneFalls back to RESPAN_API_KEY env var.
base_urlstr | NoneNoneFalls back to RESPAN_BASE_URL env var.
instrumentationslist[]Plugin instrumentations to activate, e.g. LangChainInstrumentor().
include_contentboolTrueIncludes graph inputs, node inputs, and outputs on spans.
include_metadataboolTrueIncludes LangGraph tags, metadata, and serialized runnable details.
customer_identifierstr | NoneNoneDefault customer identifier for all spans.
metadatadict | NoneNoneDefault metadata attached to all spans.
environmentstr | NoneNoneEnvironment tag, e.g. "production".

Attributes

In Respan()

Set defaults at initialization — these apply to all spans.

1from respan import Respan
2from respan_instrumentation_langchain import LangChainInstrumentor
3
4respan = Respan(
5 instrumentations=[LangChainInstrumentor()],
6 customer_identifier="user_123",
7 metadata={"service": "graph-api", "version": "1.0.0"},
8)

With propagate_attributes

Override per-request using a context scope.

1from respan import propagate_attributes
2from respan_instrumentation_langchain import add_respan_callback
3
4def handle_request(user_id: str, topic: str):
5 with propagate_attributes(
6 customer_identifier=user_id,
7 thread_identifier="conv_abc_123",
8 metadata={"plan": "pro"},
9 ):
10 result = app.invoke(
11 {"topic": topic},
12 config=add_respan_callback({"run_name": "user_graph"}),
13 )
14 print(result)
AttributeTypeDescription
customer_identifierstrIdentifies the end user in Respan analytics.
thread_identifierstrGroups related messages into a conversation.
metadatadictCustom key-value pairs. Merged with default metadata.

Decorators (optional)

Decorators are not required. Attach the Respan callback config to the graph invocation to trace graph and node runs. Use @workflow and @task (Python) or withWorkflow and withTask (TypeScript) to group graph runs inside larger application workflows.

1from respan import workflow, task
2from respan_instrumentation_langchain import add_respan_callback
3
4@task(name="run_joke_graph")
5def run_joke_graph(topic: str):
6 return app.invoke(
7 {"topic": topic},
8 config=add_respan_callback({"run_name": "decorated_graph"}),
9 )
10
11@workflow(name="joke_pipeline")
12def pipeline(topic: str):
13 print(run_joke_graph(topic))
14
15pipeline("AI tracing")
16respan.flush()

Examples

Streaming updates

Stream graph node updates while keeping the same trace.

1for update in app.stream(
2 {"topic": "AI tracing"},
3 config=add_respan_callback({"run_name": "streaming_graph"}),
4 stream_mode="updates",
5):
6 print(update)

Tool nodes

Tool calls inside graph nodes are captured as tool spans.

1from langchain_core.tools import tool
2from langgraph.prebuilt import ToolNode
3
4@tool
5def search_docs(query: str) -> str:
6 """Search docs."""
7 return f"Results for {query}"
8
9tools = ToolNode([search_docs])