Understanding Nodes and Edges in LangGraph
Move beyond fragile while-loops. In this lesson, we transition to LangGraph state machines: modeling agents as discrete functional nodes connected by directed and conditional edges with built-in cyclical loops.
1. Core Anatomy of a Graph Agent
Select a concept to inspectLangGraph Construction Inspector
# 1. NODES: Standard Python functions returning partial state updates
from typing import TypedDict, Annotated
from langchain_core.messages import BaseMessage, HumanMessage, AIMessage
class AgentState(TypedDict):
messages: list[BaseMessage]
sender: str
def agent_node(state: AgentState) -> dict:
"""Node: Calls LLM and returns the new assistant message."""
messages = state["messages"]
model_response = model.invoke(messages)
# Return partial update — LangGraph merges this into state
return {"messages": [model_response], "sender": "agent"}
def tool_executor_node(state: AgentState) -> dict:
"""Node: Executes tools requested by model."""
last_msg = state["messages"][-1]
results = []
for tool_call in last_msg.tool_calls:
output = run_tool(tool_call["name"], tool_call["args"])
results.append(output)
return {"messages": results, "sender": "tools"}2. Interactive LangGraph Topology Visualizer
Node-Edge Interactive InspectorLangGraph StateGraph VisualizerNodes & Edges
Visualize how Normal Edges and Conditional Edges route state between functions in a graph
from langgraph.graph import StateGraph, START, END
builder = StateGraph(State)
builder.add_node("call_model", call_model)
builder.add_node("call_tools", call_tools)
builder.add_edge(START, "call_model")
builder.add_conditional_edges(
"call_model",
should_continue,
{"tools": "call_tools", "end": END}
)
builder.add_edge("call_tools", "call_model") # loop back!Common Engineering Traps
Writing state["messages"].append(msg) inside a node breaks LangGraph's time-travel, checkpointing, and branch rollback capabilities. Nodes must always return a new dictionary with updates (e.g. return {"messages": [msg]}) so LangGraph reducers manage state immutably.
If your conditional router function has an unhandled condition branch that returns an unregistered string, LangGraph raises a runtime KeyError. Always define an explicit fallback mapping to END in your path dictionary.
Key Architectural Takeaways
- 1.Decoupled Architecture: Nodes don't know who called them or who runs next. They just transform State. The graph topology alone controls workflow order.
- 2.Cyclic Workflows Supported: Unlike DAG-only orchestrators (Airflow), LangGraph is built natively for cycles — allowing agents to loop indefinitely until exit conditions are met.
- 3.Persistence Ready: Because every step transition is a state snapshot, you can attach any checkpointer (Postgres, Redis) to enable full time-travel debugging and pause-and-resume.
Defining and Managing State in LangGraph
State is the lifeblood of your graph. Learn how TypedDict schemas, add_messages reducers, and custom aggregation functions prevent data loss during multi-node execution.