I'm pretty sure you've already heard about LangGraph—otherwise, you wouldn't have clicked on this post :)
GenAI is the hottest topic in tech right now, and it feels like we're just getting started. New roles are popping up everywhere that require a solid grasp of the space, along with familiarity with the core tools, frameworks, and concepts.
The problem? Most of the resources out there are in Python.
So, I decided to start a series of bite-sized posts to teach you the key concepts of one of the core building blocks of GenAI-based development: LangGraph—but in TypeScript.
My approach is to be very practical. Instead of going deep into the theory early on, we’ll jump straight into code and learn by doing. Each post focuses on a small, self-contained concept with real, working examples.
We’ll keep things simple at first—no AI models, no agents—just the core building blocks. Once we have a good grip on the fundamentals, we’ll gradually move into more advanced topics like routing, conditionals, memory, tool calling, and building actual agents.
The source code of the entire series is available here:
Also, the you can find the source code of this post here:
👉 1-simple-graph-chain
I suggest you fork and clone the repository, and open the file in your IDE so you always can see the full picture, follow along more easily, and tweak the code as you learn.
Introduction to LangGraph
LangGraph is a framework for building agents and multi-agent systems. At the core of LangGraph is a graph, which is a collection of nodes and edges.
Each node adds a specific functionality to the system, and edges define the flow between those nodes. Think of it like a flowchart where data moves from one step to the next.
In typical software, we have some sort of initial data which we process step by step in a deterministic workflow. But when we work with AI, decisions are often dynamic—based on model responses or environment inputs. LangGraph allows you to model those flows naturally using a graph-based structure.
What We'll Build
In this first lesson, we’ll build a simple graph chain:
A linear set of steps where each node is executed in sequence. This is a very basic use case, but it sets the foundation for more advanced patterns later.
State Graph in LangGraph
To build a graph, we use the StateGraph
class.
Here’s a quick breakdown of the key concepts:
- Node: A function that takes some state and returns new state.
- Edge: A directional connection between two nodes.
- State: The shared data passed between nodes.
Let’s take a closer look at each component.
State
In LangGraph, the execution flows through multiple nodes—each responsible for performing a part of the overall task. These nodes often need to share data: inputs, intermediate results, and outputs.
To make this possible, LangGraph introduces the concept of State—a shared structure that travels through the graph and can be read or updated by each node.
Here’s what it looks like in our example:
interface SimpleGraphState {
step: number;
}
This very simple interface defines the shape of our graph’s state. In this case, we’re keeping track of a single field called step
.
Channels
Each field in the state is controlled by a channel. Channels allow you to store and update different pieces of the state as the graph executes.
Here’s how we define the channel for step:
const graphStateChannels: StateGraphArgs<SimpleGraphState>["channels"] = {
step: {
value: (prevStep: number, newStep: number) => newStep,
default: () => 0,
},
};
This tells LangGraph two things:
Use 0 as the default value when the graph starts.
Always use the most recent update (
newStep
) if multiple nodes update the step.
And then, we pass these channels into the graph like so:
new StateGraph({ channels: graphStateChannels })
This gives LangGraph full control over how the state is initialized, updated, and maintained across the execution of nodes.
Nodes
A node in LangGraph is just a function that takes in some state and returns some (possibly updated) state. It’s the basic unit of logic in the graph.
Here’s how we define a simple node:
function firstNode(state: SimpleGraphState): SimpleGraphState {
console.log("Executing Node 1");
return {
step: state.step + 1,
};
}
This node does exactly one thing: it logs that it’s running and increments the step field in the state.
Edges
Once we’ve defined our nodes, the next step is to wire them together using edges. Edges determine the flow of execution—what node comes next after another.
We use the addNode
method to register each node, and then use addEdge(from, to)
to connect them:
const graphBuilder = new StateGraph({ channels: graphStateChannels })
.addNode("first", firstNode)
.addNode("second", secondNode)
.addNode("third", thirdNode)
.addEdge(START, "first")
.addEdge("first", "second")
.addEdge("second", "third")
.addEdge("third", END);
A few things to note here:
START
is a special entry point in the graph. It defines where the graph should begin execution.END
is a special marker that signals the termination point—once a node leads here, the graph stops.Each
addEdge
call links two nodes together, forming a directed path.
Compile and Invocation
Once the graph is built, we compile it to create an executable graph object:
export const graph = graphBuilder.compile();
And then we invoke it like this:
const result = await graph.invoke({
step: 0, // This could be any initial value
});
We start by passing an initial state—step: 0. Each node updates the step field, so by the end of the execution, we’ve gone from 0 to 3.
Run the Code
To run the example, first make sure you’ve cloned the repository:
git clone https://github.com/mkamrani/next-gen-platforms.git
cd next-gen-platforms/LangGraph/Typescript
Then install the dependencies - some of the dependencies will be used in the next lessons:
npm install
And finally run the code:
cd src/1-simple-graph-chain
npm run dev-1
You should see the following logs in your terminal:
=== Starting Graph Execution ===
Executing Node 1
Executing Node 2
Executing Node 3
=== Graph Execution Complete ===
Final state: { step: 3 }
Graph execution completed successfully
Happy Coding!
Top comments (0)