Problem
When using LangGraph Server via the RemoteGraph pattern, LangSmith displays two separate runs (rows) per single user message - one for the client-side orchestrator and one for the server-side graph execution. This creates fragmented traces that are difficult to analyze.
Solution
Enable distributed tracing to merge these runs into a single unified trace hierarchy. This requires configuration on both the client and server sides.
Step 1: Enable Distributed Tracing on the Client
Set distributed_tracing=True when creating your RemoteGraph instance:
from langgraph.pregel.remote import RemoteGraph
remote_graph = RemoteGraph(
"my-graph",
url="https://my-deployment.langgraph.app",
distributed_tracing=True # Enable trace context propagation
)When enabled, the client automatically adds langsmith-trace headers containing the trace context (dotted_order, trace_id, etc.) to all requests sent to the server.
Step 2: Configure the Server to Accept Trace Context
On the server side, use a context manager to extract and apply the trace context from incoming requests:
For synchronous graphs:
import contextlib
import langsmith as ls
my_graph = builder.compile(name="ReAct Agent")
@contextlib.contextmanager
def graph(config):
configurable = config["configurable"]
parent_trace = configurable.get("langsmith-trace")
parent_project = configurable.get("langsmith-project")
with ls.tracing_context(parent=parent_trace, project=parent_project):
yield my_graphFor asynchronous graphs:
import contextlib
import langsmith as ls
my_graph = builder.compile(name="ReAct Agent")
@contextlib.asynccontextmanager
async def graph(config):
configurable = config["configurable"]
parent_trace = configurable.get("langsmith-trace")
parent_project = configurable.get("langsmith-project")
with ls.tracing_context(parent=parent_trace, project=parent_project):
yield my_graphHow It Works
Client side: When
distributed_tracing=True, theRemoteGraphcallsRunTree.to_headers()which produces:langsmith-trace: Contains thedotted_orderfor trace correlationbaggage: Containslangsmith-project,langsmith-metadata, andlangsmith-tags
Server side: LangGraph Server extracts these headers and passes them through the
configurabledict:langsmith-trace: The trace context stringlangsmith-project: The project name to trace tolangsmith-metadata: Any metadata passed from the clientlangsmith-tags: Any tags passed from the client
Trace merging: The
ls.tracing_context(parent=...)context manager reconstructs the parent run tree, causing all server-side spans to appear as children of the client's trace.
Requirements
langsmith SDK: Version
>= 0.4.56(earlier versions have issues with malformeddotted_ordervalues)LangGraph SDK: Any recent version with
RemoteGraphsupport
Troubleshooting
Traces Still Appear Separate
Verify
distributed_tracing=Trueis set on the client'sRemoteGraphinstanceCheck SDK versions: Ensure
langsmith >= 0.4.56Confirm server-side context manager: The server must explicitly use
tracing_context(parent=...)to opt-in to distributed tracing
Missing Project or Metadata
Ensure you're extracting both langsmith-trace and langsmith-project from the configurable:
parent_trace = configurable.get("langsmith-trace")
parent_project = configurable.get("langsmith-project")Alternative: Trace to Different Projects
If you prefer to keep the traces separate but organized, you can trace the client and server to different LangSmith projects instead of merging them.