Transcript (captions)
Watch this agent work. 38 steps in, 40 minutes of tool calls, and the Python process dies. It comes back with nothing. No memory of step one, no memory of step 37. It starts over and spends the money again.
That failure is the reason LangGraph exists, which is strange, because most explainers of it open somewhere else entirely. They open with boxes and arrows, and they teach you how to draw the graph. The drawing is the easy half of this. You can learn the entire graph API in about 20 lines of Python, and all 20 of them are coming up shortly. The half that survives that crash sits underneath the drawing, and you switch it on with one extra argument.
So, this video swaps the emphasis. Two minutes on the picture most tutorials teach, and the rest on the runtime. It earns that time. LangGraph is downloaded over 65 million times a month, going by LangChain's own July count. Klarna, Replit, Elastic, Uber, LinkedIn, and Cisco run it in production, and the library itself is MIT licensed and free.
The release you install today landed 9 days ago, which tells you how fast this ground is still moving under you. By the end, you will know the four pieces, what the runtime under them buys you, and the project where skipping it is correct. Piece one is state. You declare a typed dictionary, or a data class, or a Pydantic model, and that one object is the only thing every step of your agent reads from and writes to. Not a hidden context, not a chain of arguments, one shared schema you can print.
Piece two is a node, and this is where LangGraph is smaller than its reputation. A node is a Python function that takes the state and returns a partial update. No base class, no interface to implement, and it can be synchronous or async. The documentation is explicit about that. Piece three is edges.
A fixed edge says, "After node A, run node B." A conditional edge runs a routing function first and lets it pick the next node by name at runtime from whatever the state now holds. There is also a command object that does both at once. Update the state and name where to go next in a single return. Piece four is compile. You wire the built-in start marker to your first node, end to your last, call compile.
And you have an object you can invoke like any other function. That is the whole graph API. State, node, edge, compile. Under 20 lines for a working agent, and the people who say they could write this themselves in an afternoon are right. That is not the part you are buying.
But there is a fifth idea hiding inside piece one, and skipping it is why a first graph so often behaves strangely. Reducers. By default, when a node returns a value for a key, it replaces whatever was there. Attach a reducer, and you change that rule for that field alone. The built-in add messages reducer appends to the conversation instead of flattening it, and it will deserialize raw message dictionaries for you on the way in.
Reducers exist because of what happens when two branches run at the same time. Both write to the same key in the same step, and something has to decide how those two updates merge rather than clobber. That decision is yours, and it is one annotation on one field. And this is where the shape stops being a flowchart. Sydney Runcle and Harrison Chase put it plainly in a July post.
Agent graphs are usually not DAGs. Production agents need cycles, retrying failed tool calls, asking users for missing information, revising answers after validation. In that same post, they hand the argument to the other side, which I respect. A loop, they write, is just a directed cyclic graph. LangChain's own high-level agent is a loop, and it is built on top of LangGraph.
Therefore, the interesting question stops being which shape you prefer. It becomes what the thing running the shape is doing for you, and what it is doing underneath is stranger and older than a flowchart. Your nodes never call each other. They read name channels, and they write name channels, and the runtime moves a whole graph forward in rounds that it calls super steps. Inside a super step, every active node runs once and its right state invisible to the others.
At the boundary, the runtime applies them all through their reducers, works out whose inputs changed, and dispatches that set next. That is what turns a parallel branch into something reproducible instead of a race you get away with. That model is not new and LangGraph has never pretended it is. It is the Pregel model out of a Google paper published in 2010, 16 years of distributed graph processing, repointed at language models. Cycles are a first-class citizen there, which is exactly why a retry loop is not a special case here.
It also solves the thing a static diagram cannot. Chase and Runkle's own example, you know the research should fan out and then synthesize, but you do not know how many sources there will be. So, if you cannot draw the fan out in advance, what is the graph actually doing for you? The answer is the send API. A conditional edge returns a list of send objects, one per item, each carrying its own slice of state, and the runtimes bonds exactly that many workers.
MapReduce with the width decided by the data instead of by you. And because a cycle can run away, there is a step cap. Hit it and the graph raises a recursion error rather than billing you forever. Now, the part this whole video is built around. You pass one more argument to compile, a checkpointer, and you pass a thread ID when you invoke it.
Two lines of typing. From that moment on, the full state of your agent is written to storage after every single step, not just the messages, the state. What each node produced, which branch is live, what is still pending. So, run that dying agent again. The process is killed at step 38, the machine restarts, you invoke with the same thread ID, and it picks up at step 38.
The 40 minutes of work are still sitting there. You choose how paranoid that is. Three durability modes, straight from the type definition, sync rights before the next step starts, async rights while the next step runs, exit rights only when the graph finishes. Safety at one end, throughput at the other, one string in between, and you choose where it lands. In-memory saver for tests, SQLite for a laptop, Postgres for production.
The documentation carries a warning worth reading twice because it has caught a lot of people on their first deploy. The memory saver does not persist between restarts. Once complete state is on disk after every step, three features fall out of that one decision, and each of them is far harder to build yourself than it looks from the outside. The first is the human. Call interrupt inside a node, and the run stops right there with its state saved, handing you whatever value you passed in.
The draft email, the refund amount, the migration it wants to run against your database. Your reviewer can take an hour or a week. When they answer, you invoke again with a resume command. The value lands back at the interrupt call, and the agent carries on as though the pause had not happened. But, the documentation puts a warning here that catches people in production, so it is worth learning now rather than at 2:00 in the morning.
On resume, the runtime restarts the entire node from the beginning. It does not continue from the line where interrupt was called. Everything above that line runs a second time, which means any side effect before that interrupt has to be idempotent. Charge a card above that line, and you can charge it twice, or write the same row twice. Move the right below the interrupt, or make repeating it harmless.
One more trap in the same family. Never wrap an interrupt in a try except. It pauses by throwing a special exception, so catching that exception swallows the pause, and the whole mechanism goes quiet without failing. The second feature is time travel, and it is the one that changes how you debug. Ask a thread for its state history, and you get back every checkpoint it has ever had, newest first, each carrying its own ID.
Hand one of those IDs back, and the graph replays from that point forward. Update the state first, and you fork instead, a new branch growing out of an old moment. So, you can ask what this agent would have done if that one tool call had returned something else. The docs state the limit plainly, which I appreciate. Replay re-executes the nodes after your checkpoint.
It is not a cache. The model calls fire again. The API calls fire again, and the answers can come back different. The third feature is what you show a user while all of this is happening. Seven streaming modes: full state, state updates, model tokens, your own custom events, checkpoints, task starts and finishes, and a debug firehose that combines a lot.
And sitting beside all of it there is the store, which is the piece people skip. The checkpointer remembers one conversation. The store keeps what you learned about a user across every conversation they ever have with you. But look at what has accumulated. Type state, reducers, channels, super steps, checkpointers, durability modes, interrupts, forks.
That is a great deal of machinery to put behind a chatbot, and there are projects where it is the wrong call. The documentation says so itself near the top. LangGraph does not abstract prompts or architecture. It is deliberately low-level, and low-level means you write the schema, the nodes, and the wiring by hand. Reviewers put the ramp at 1 to 2 weeks, and the Python library still leads the JavaScript one on features.
So, if your agent is five deterministic retrieval steps or one tool loop that either finishes in 30 seconds or does not, you are paying a complexity tax for durability you are not going to use. A while loop and a JSON dump is the correct engineering there, and the reviewers who ship both architectures say exactly that. Therefore, LangChain built the exits themselves. Their high-level create agent gives you a working agent in a few lines with middleware for the customizations that used to force people down into graph definitions. Version 1.0 froze that API last October, and it broke almost nothing on the way.
Above that sits deep agents, an opinionated harness with planning, a virtual file system, sub agents, and skills already wired up. Version 0.7.4 landed 2 days ago, and its own documentation says it uses a LangGraph runtime for durable execution, streaming, and human in the loop. Stripe built their company-wide agent on that path. One engineer, roughly 1 week, 296 users at preview, and about 4 weeks later, 16 times that, past 5,000 people, 60,000 sessions, and 1,000 internal skills to draw on. Their engineering manager, Sharad Krishnamurthy, described the appeal in one line.
The deep agents layer solves all the non-stripy problems so that we can focus on solving the stripy agent problems. And if you want that runtime with no graph at all, there is a functional API. Decorate your function with entry point. Decorate your steps with task, and you get persistence, memory, human in the loop, and streaming over ordinary Python control flow. Same runtime, no diagram.
Which brings me to the thing that changed how I read this whole framework. The largest piece of LangGraph engineering this year was not a graph feature at all. Under full snapshot checkpointing, checkpoint number N contained everything from steps 1 through N. Storage grew with the square of the run length. A 200-turn coding agent wrote 5.3 GB of checkpoints across that one run.
In May, they shipped delta channels. Write only the diff each step with a full snapshot every so often so recovery stays bounded. Same agent, same 200 turns, 129 MB. Over 40 times less, and it is still marked beta. You do not rewrite your storage layer for a diagram.
So, here is my verdict. The graph is not the product. The runtime is the product, and the graph is simply the syntax you happen to configure it with. Take LangGraph the moment your agent has to survive something, a restart, a human, a week, an incident review that asks what state it was in at step 38. That covers most teams building anything real, and it is exactly the part a hand-rolled loop becomes a worse version of, which you then maintain forever.
Skip it for the short deterministic pipeline. LangChain will tell you that themselves, their own July post says some tasks are more agentic by nature, and forcing them down deterministic paths is the wrong move. The framework is free either way. The bill only starts if you let them host it. I would still take this runtime at twice the learning curve because the week you lose to type state and reducers is far cheaper than the first production incident you cannot replay.
So, here is what I would ask before you write a single node. If the durability is the product, and their own fastest-growing tool ships with no graph in it at all, how much of your architecture are you drawing for the machine, and how much of it are you drawing for yourself?