Agentic Chatbot Frameworks with LangGraph
Stateful Logic Architectures
From Chains to Graphs
Simple, linear chains are great for straightforward tasks. You input a prompt, it moves through a sequence, and you get an output. But what happens when a conversation needs to remember what was said three turns ago? Or when the application's next step depends on the result of a tool's output? The linear model starts to break down.
This is where LangGraph comes in. It shifts the paradigm from a simple, one-way street to a dynamic, stateful graph. Think of it as upgrading from a basic assembly line to a full-fledged workshop. In the workshop, different stations (nodes) can be visited in any order, and everyone shares a common blueprint (the state) that gets updated as the project progresses.
LangGraph is a powerful framework by LangChain designed for creating stateful, multi-actor applications with LLMs.
The core mental model of LangGraph revolves around three key components:
- State: A shared object that persists across the entire workflow. It’s the single source of truth, containing the conversation history, intermediate results, and any other data your application needs to maintain context.
- Nodes: Python functions that do the work. A node takes the current state as input, performs some action (like calling an LLM, querying a database, or using a tool), and returns an object to update the state.
- Edges: The connections that direct the flow from one node to another. Edges use the current state to decide which node to execute next, enabling conditional logic, branching, and cycles.
Defining Your Application's Memory
Before building the graph, you must define its memory. The StateGraph object is typed to a specific state schema, which ensures that all nodes operate on a consistent data structure. This schema is the blueprint for your application's memory.
You can define this schema using Python's built-in TypedDict or, for more complex applications, the powerful Pydantic library. For our purposes, we'll start with TypedDict. It allows us to define a dictionary-like object with specific keys and value types. This brings clarity and predictability to your state management.
from typing import List, TypedDict
from langchain_core.messages import BaseMessage
# This defines the structure of our application's state.
# Every node in the graph will have access to an object with this shape.
class AppState(TypedDict):
# A list of messages, representing the conversation history.
messages: List[BaseMessage]
# Metadata specific to a business sector, like 'finance' or 'healthcare'.
sector: str
# Documents retrieved from a vector store.
retrieval_results: List[str]
In this example, our AppState will track the conversation history, a piece of business-specific metadata (sector), and any documents retrieved for context. Every node we add to our graph will receive an AppState object and can modify it. Using a ensures that if a node tries to access state['sector_name'] instead of state['sector'], your code editor can catch the error immediately.
Initializing the Graph
With the state schema defined, you can initialize the StateGraph. This object is the main container for your workflow. You pass it your state schema, and it provides the methods for adding nodes and edges.
from langgraph.graph import StateGraph, END
# Initialize the graph, passing our AppState schema.
# The graph's state will now always conform to the AppState structure.
graph_builder = StateGraph(AppState)
At this point, the graph is empty. It knows what its memory should look like, but it has no nodes to perform work and no edges to direct traffic. The next step is to define your worker nodes and set an entry point—the first node to be executed when the graph is run. This structured approach is what makes LangGraph so reliable for building complex, context-aware applications.
What is the primary problem with simple, linear chains that LangGraph is designed to solve?
In the LangGraph framework, what is the role of a 'Node'?
Now that you have the foundational concepts, you're ready to start populating the graph with logic.