Wire nodes with LangGraph StateGraph
With the nodes and the state defined, we can finally wire them together. LangGraph uses a StateGraph. You add each node by name, declare edges to say who runs after whom, pick an entry point, and compile. The graph is a dependency spec, not a script.
The compiled StateGraph
Four nodes, five edges, one entry point.
One catch before we wire anything. The graph registers four nodes, but so far we have only written search_node and content_extraction_node. If you run the wiring cell now, Python raises a NameError because synthesis_node and refinement_node do not exist yet. So we drop in two tiny stubs first. They stamp current_step and pass the state through, which is enough for the graph to compile and run end to end.
# Temporary stubs so the graph compiles and runs end to end.
# We swap in the real implementations when we build the synthesis
# and refinement prompts.
def synthesis_node(state: ResearchState) -> ResearchState:
"""Stub: will synthesize a cited answer from extracted content."""
state["current_step"] = "synthesizing"
state["synthesized_answer"] = "(synthesis coming soon)"
return state
def refinement_node(state: ResearchState) -> ResearchState:
"""Stub: will refine the draft for concision."""
state["current_step"] = "refining"
state["final_answer"] = state["synthesized_answer"]
return stateSame node signature as the real thing: take state, mutate it, return it. Because the graph only cares about the signature, we can wire everything now and upgrade these two functions later without touching the graph.
from langgraph.graph import StateGraph, END
def create_research_assistant():
"""Create the research assistant graph."""
workflow = StateGraph(ResearchState)
workflow.add_node("search", search_node)
workflow.add_node("extract_content", content_extraction_node)
workflow.add_node("synthesize", synthesis_node)
workflow.add_node("refine", refinement_node)
# Define edges
workflow.set_entry_point("search")
workflow.add_edge("search", "extract_content")
workflow.add_edge("extract_content", "synthesize")
workflow.add_edge("synthesize", "refine")
workflow.add_edge("refine", END)
return workflow.compile()
research_assistant = create_research_assistant()Each add_node registers a function as a graph node. Each add_edge declares the order. The END constant is a sentinel LangGraph uses to mark the exit.
Ordering exercise: Order the graph-building steps
Loading practice…
END is a sentinel from langgraph.graph that marks a terminal edge. Using the constant instead of a plain string means LangGraph knows the graph ends there, and it refuses to compile if you forgot to connect one of your nodes to it. The strictness catches the classic bug where you forget the last edge and the graph just hangs.
Quiz: Quiz
Loading practice…