Graph Execution Frontend
Status: ACTIVE (pulled from docs.langchain.com) Source: https://docs.langchain.com/oss/python/langgraph/frontend/graph-execution Timestamp: 2026-05-11
Visualize multi-step graph pipelines with per-node status cards and streaming content. Users see exactly what the agent is doing, which step it's on, and what each step produced.
Mapping Nodes to UI Cards
Each graph node becomes a UI card with status tracking:
const PIPELINE_NODES = [
{ name: "classify", stateKey: "classification", label: "Classify" },
{ name: "do_research", stateKey: "research", label: "Research" },
{ name: "analyze", stateKey: "analysis", label: "Analyze" },
{ name: "synthesize", stateKey: "synthesis", label: "Synthesize" },
];
Setting Up useStream
import { useStream } from "@langchain/react";
export function PipelineChat() {
const stream = useStream<typeof myAgent>({
apiUrl: "http://localhost:2024",
assistantId: "graph_execution_cards",
});
return (
<div>
<PipelineProgress nodes={PIPELINE_NODES} values={stream.values} />
<NodeCardList
nodes={PIPELINE_NODES}
messages={stream.messages}
values={stream.values}
getMetadata={stream.getMessagesMetadata}
/>
</div>
);
}
Routing Streaming Tokens to Nodes
function getStreamingContent(
messages: BaseMessage[],
getMetadata: (msg: BaseMessage) => MessageMetadata | undefined
): Record<string, string> {
const content: Record<string, string> = {};
for (const message of messages) {
if (message.type !== "ai") continue;
const metadata = getMetadata(message);
const node = metadata?.streamMetadata?.langgraph_node;
if (node && PIPELINE_NODE_NAMES.has(node)) {
content[node] = typeof message.content === "string" ? message.content : "";
}
}
return content;
}
Node Status
| Status | Meaning |
|---|---|
| idle | Not started yet |
| streaming | Currently producing output |
| complete | Output finalized |
type NodeStatus = "idle" | "streaming" | "complete";
function getNodeStatus(
node: { name: string; stateKey: string },
streamingContent: Record<string, string>,
values: Record<string, unknown>
): NodeStatus {
if (values?.[node.stateKey]) return "complete";
if (streamingContent[node.name]) return "streaming";
return "idle";
}
Streaming vs Completed Content
| Source | When to Use |
|---|---|
streamingContent[node.name] |
While node is actively streaming (tokens arriving) |
stream.values[node.stateKey] |
After node completes (final committed output) |
Best Practices
- Define nodes declaratively as single source of truth
- Prefer streaming content for active nodes (immediate feedback)
- Auto-collapse completed nodes to focus on active steps
- Add global progress indicator ("Step 2 of 4")
- Handle errors per node without collapsing entire pipeline
- Handle dynamic pipelines by checking which state keys have values