Module 6 Lesson 3: Nodes, Edges, and State
The building blocks of LangGraph. Learning how to write functions that play nice with the graph schema.
Nodes, Edges, and State: The Technical Details
In the previous lesson, we saw the high-level architecture. Now, we dive into the code. To build a LangGraph application, you must master the syntax of its three core components.
1. Defining the State (The Annotated List)
The State is a schema that tells LangGraph how to merge new information into the existing data. A common pattern is using Annotated with add_messages so that every new message is appended to the list rather than overwriting the whole list.
from typing import Annotated, TypedDict
from langgraph.graph import add_messages
class GraphState(TypedDict):
# This says: whenever a node returns 'messages',
# add them to the previous list of messages.
messages: Annotated[list, add_messages]
sender: str
2. Writing a Node (The Worker)
A node is a function that receives the state and returns an Update. You don't return the whole state, only the keys you want to change.
def my_node(state: GraphState):
print(f"I am the {state['sender']} node!")
# We do some logic here...
return {"messages": ["New message from node"], "sender": "bot"}
3. Defining Edges (The Router)
Edges can be simple or conditional.
Simple Edge
workflow.add_edge("node_a", "node_b")
"Always go from A to B."
Conditional Edge
This uses a "Routing Function" to decide the path.
def router(state: GraphState):
if len(state["messages"]) > 5:
return "end"
return "continue"
# If router returns 'end', go to END. If 'continue', go to 'agent'.
workflow.add_conditional_edges(
"agent",
router,
{"end": END, "continue": "agent"}
)
4. Visualizing the Graph Logic
graph LR
START --> NodeA[Node A: Set Context]
NodeA --> NodeB[Node B: LLM Call]
NodeB --> Router{Router Function}
Router -->|Done| END
Router -->|Retry| NodeB
Router -->|Tool Needed| NodeC[Node C: Run Tool]
NodeC --> NodeB
5. The Power of "Reducers"
add_messages is a type of Reducer. You can create your own reducers for complex math or state logic.
- "If Node A returns a list [1, 2] and Node B returns [3, 4], the state should be [1, 2, 3, 4]." Without reducers, Node B would simply overwrite the state to [3, 4], and you would lose the data from Node A.
Key Takeaways
- State is usually a TypedDict with specific Reducers (like
add_messages). - Nodes return partial state updates.
- Conditional Edges use routing functions to manage the "Logic Flow."
- Reducers are the key to building complex, multi-turn memory.