Beginner’s Guide to LangGraph: Understanding State, Nodes, and Edges — Part 1
LangGraph — State, Node and Edge Explained
In this article, we will discuss the basics of LangGraph. Mainly, we will focus on various components of LangGraph: State, Node, and Edges, and how to build a complete graph from these components. Once we understand these components, we will be able to build relatively complex LangGraph-based agents.
The Comprehensive LangGraph Guide is available here.
All the sample codes associated with this article are available in this notebook.
First, let’s understand the various components, and then use them to construct a complete graph.
Nodes: Nodes are the fundamental building blocks of a graph. Each node represents a specific function or operation that processes the current state. Nodes can perform computations, modify the state, or generate outputs based on the input they receive. They are typically defined as Python functions or classes that take the current state as input and return an updated state.
Edges: Edges define the connections between nodes, determining the flow of execution within the graph. They specify how the output of one node is passed as input to another node. Edges can be normal (directly connecting one node to another) or conditional (routing to different nodes based on certain criteria). They play a crucial role in controlling the sequence of operations and how nodes interact with each other in the graph.
State: In LangGraph, the state is a shared data structure that captures the current snapshot of our application. It can be any Python type, though it is typically either a TypedDict or a Pydantic BaseModel. The state plays a crucial role in the functionality of LangGraph by enabling nodes to communicate and exchange data. Each node in a LangGraph graph has the ability to access, read, and write to the state. When a node modifies the state, it effectively broadcasts this information to all other nodes within the graph. This broadcasting mechanism allows other nodes to respond to changes in the state and adjust their behavior accordingly.
LangGraph: It is a Python library for building and running graphs of nodes that communicate by reading and writing to a shared state. LangGraph is designed to make it easy to create complex, multi-agent workflows that can be used for a variety of applications.
StateGraph: StateGraph in LangGraph is a class that allows us to create graphs whose nodes communicate by reading and writing to a shared state. The StateGraph class is parameterized by a user-defined State object, which represents the shared data structure that the nodes in the graph will communicate through.
Let’s explore various scenarios where we define state differently and include different Python functions and classes into the nodes to construct a simple graph. Depending on our state schema, we should adjust our inputs accordingly. The following examples will help us in understanding how these components interact within the graph.
Example 1: Dictionary as State
Here, we directly define the state graph using builder = StateGraph(dict), where the state is simply a Python dictionary.
Using a dictionary as a state is straightforward but can be challenging to manage. Since there is no predefined schema, nodes can read from and write to the state without strict type constraints. This flexibility enables dynamic data handling; however, it also requires the developer to ensure that the keys and values are consistently managed throughout the graph’s execution.
Overall, this graph sets up a simple workflow where a value is incremented (by node 1st — add function) and then doubled (by node 2nd — multiply function), demonstrating how nodes can interact through a shared state in a graph. It’s important to note that the state contains information from only one node at a time. This means that when a node processes the state, it only has access to the data relevant to its specific operation, ensuring that each node’s logic is isolated and focused.
Example 2: Schema Defined State
In this graph, the state is defined as a structured dictionary that contains a key called messages, which holds a list of strings. This state is used to manage the data that nodes will process during execution. The schema for the state is defined using a TypedDict called State, which specifies that messages is an annotated list of strings. The annotation includes operator.add, indicating that the list can be updated by combining new messages with existing ones using the addition operation. This schema ensures that the state is consistently structured and allows for proper type checking during the graph's execution.
Example 3: Defining a Node Class
The ReturnNodeValue class is used to create nodes that return specific messages when invoked. Each instance of this class represents a node in the graph, and its __call__ method defines what happens when that node is executed. In this case, it outputs a message that gets added to the messages list in the state. When the graph is executed, it processes the nodes in order, starting from "Hello" and then moving to "World".
Example 4: Using LLM
This example illustrates how to integrate an LLM into a LangGraph workflow, allowing for dynamic message processing and interaction with the model. The remaining components are identical to those in the previously defined graphs. Here, the first node invoke the llm and produces an output, which is simply an AIMessage. The second node then straightforwardly translates the AIMessage from the previous node into a HumanMessage.
This article introduced the basic elements of LangGraph — Nodes, Edges, and State — and showed how to build a simple graph. We explored how nodes perform operations, how edges control the flow, and how the state facilitates node communication. Through examples, we demonstrated practical applications of LangGraph for building dynamic systems. In future articles, we’ll dive into more complex scenarios to further expand our use of LangGraph.