Why tonight changes the track
Sessions b2-b4 lived at the create_agent altitude: one model, some tools, middleware around a loop you never saw. That loop is a LangGraph graph - a prebuilt one. Real systems need shapes create_agent does not ship: a router in front of two specialists, a deterministic validation step after every model call, parallel branches, a cycle with an exit condition. LangGraph is the machine for building those shapes, and the whole API is smaller than you fear: one state schema, functions as nodes, edges between them, compile. Everything b6-b9 adds - memory, approval gates, multi-agent - is a feature OF this machine, which is why tonight is the hinge session of the track.
From loop to graph 9 min live
The agent loop you wrote by hand in b1 is one control-flow shape among many. Graphs let you draw the shape your problem actually has - and keep the drawing and the code the same artifact.
LiveWhy graphs - the shapes create_agent cannot draw4 min▶
create_agent gives you exactly one control flow: model → tools → model, repeat. It is the right default - but the moment DataDesk needs anything else, you are fighting the abstraction instead of using it:
- Routers: "stats questions go to the CSV agent, docs questions go to retrieval, small talk gets a cheap model." A classifier in front of specialists - not expressible as one agent loop.
- Deterministic segments: "ALWAYS validate the SQL before running it." Fixed steps the model cannot skip - a workflow edge, not a model choice.
- Cycles with YOUR exit condition: "retry the extraction until the schema validates, max 3 times." You own the loop counter, not the model.
- Parallel paths: "profile all 12 tables at once, then merge." Fan-out and fan-in.
The 2026 division of labor: start at create_agent, eject to LangGraph when the shape demands it. Because create_agent runs ON LangGraph, ejecting is a refactor, not a rewrite - your tools, middleware lessons and model swap all carry over.
LiveThe four primitives - the entire vocabulary5 min▶
Everything in LangGraph is built from four ideas. Learn these and you have learned the framework:
| Primitive | What it is | In code |
|---|---|---|
| State | One typed, shared document every node reads and writes - a TypedDict, dataclass, or Pydantic model | class State(TypedDict): ... |
| Nodes | Plain Python functions: take the state, return a PARTIAL update (only the keys you changed) | def step(state): return {"route": "stats"} |
| Edges | Fixed arrows: after node A, always node B. START and END are built-in endpoints | add_edge("a", "b") |
| Conditional edges | A routing function reads the state and returns the NAME of the next node | add_conditional_edges("a", pick, {...}) |
Two details that prevent 90% of beginner bugs: nodes return partial updates, never the whole state (LangGraph merges them for you), and routing functions return strings - node names - not node objects.
The whiteboard that compiled. A data team designed their pipeline-triage assistant as boxes and arrows in a design review: classify → (sql_check | doc_search) → summarize. The LangGraph file that shipped two days later had exactly those node names. When an auditor later asked "what can this system do?", they printed the graph. The diagram IS the code - that is the property you are buying tonight.
Self-studyCommand, the functional API, and when to eject4 min read▶
- Command - update and go in one move. A node can return
Command(update={"route": "stats"}, goto="stats")instead of relying on a separate conditional edge - state change and routing decision travel together. Cleaner when the node that computes the decision should also act on it. - Send - the map-reduce edge. A conditional edge can return a list of
Send("worker", {...})objects to fan one item of work out to N parallel node runs, each with its own payload. This is the engine under session b9's map-reduce pattern - namecheck now, hands-on later. - The functional API (
@entrypoint/@task) wraps ordinary Python control flow - ifs, loops - and still gets checkpointing. It suits "mostly normal code with a few LLM calls"; the graph API suits systems you want to draw, inspect, and gate. This course teaches the graph API; know the other exists. - The eject checklist. Move from create_agent down to LangGraph when you need: custom control flow (routers, validation steps, retry loops with your exit condition), deterministic segments the model must not skip, or multi-agent coordination. Stay at create_agent when the tool-calling loop plus middleware covers it - altitude is a feature, not a compromise.
Reading a graph like code 5 min live
Every LangGraph file, from tutorials to Uber-scale production, is the same five-call build sequence. Once you can spot it, unfamiliar codebases open like a map.
LiveThe build sequence - the whole API in five calls5 min▶
Say it as a sentence: declare the state, register the nodes, wire the edges, compile. In code:
Reading order for someone else's graph: find the StateGraph(...) call to learn the state schema, scan the add_node lines for the cast of characters, then follow edges from START. The compile() call is where the later superpowers plug in - compile(checkpointer=...) is next week's entire session in one argument.
Self-studyReducers, multiple schemas, and the 1.2 node options4 min read▶
- Reducers - how updates merge. By default a returned key OVERWRITES the old value. Annotate a key with a reducer to change that:
messages: Annotated[list, add_messages]makes message updates APPEND (and dedupe by id) instead of replace. That one annotation is why every node can return just its new message and the conversation still accumulates. create_agent uses exactly this under the hood. - Multiple schemas. A graph can declare separate input and output schemas, and nodes can use private state channels the caller never sees - useful when internal bookkeeping (retry counts, routing labels) should not leak into your API.
- Per-node timeouts + error handlers (langgraph 1.2). Nodes can now carry their own timeout and an error handler, so one slow or flaky step fails alone instead of hanging the whole run. Pair with b4's retry middleware thinking: retries at the agent altitude, timeouts at the node altitude.
- State typing choices. TypedDict is the lightweight default; dataclasses add defaults; Pydantic models add runtime validation at a small speed cost. Start TypedDict, upgrade the day bad state actually bites.
DataDesk gets a spine ★ 12 min · everyone builds
DataDesk v2: a router graph that reads each question, sends stats questions to your existing b3 create_agent (now demoted to one node among peers), and answers everything else with a plain model call. Three nodes, one conditional edge, about 40 lines.
Open your DataDesk project. Confirm pip install "langgraph>=1.2,<2" and that your b3 file exposes agent (the create_agent object) importably.
Define DataDeskState: a TypedDict with messages (annotated with add_messages) and route. This is the shared document all nodes will pass around.
Write three node functions: classify (asks the model for one word - stats, docs or other - and writes it to route), stats_agent (wraps your b3 agent), and fallback (plain model answer).
Wire it: START → classify, conditional edges off pick_route, both specialists → END. Compile.
Run the three test questions below and watch route differ per question - a stats question exercises your whole b3 agent inside one node; a haiku request never touches it. That divergence is the moment: control flow is yours now.
pick_route defaults anything unrecognized to "other". Defensive routing is production thinking, not demo polish.
Draw what you built ★ 8 min · build your own
A compiled graph knows its own shape. Print it, trace one run through the printed picture, and prove the engine swap still holds at this altitude.
Add two lines to the bottom of datadesk_v2.py and re-run - the compiled structure appears as a Mermaid diagram (paste it into any Mermaid renderer) or straight ASCII in your terminal.
Trace last demo's haiku question through the printed diagram with your finger: START → classify → fallback → END. The stats branch never fired. What you drew is what ran - no hidden steps.
Engine-swap test: flip the init_chat_model line to the other engine and re-run all three questions. The graph, the routing logic and the diagram are engine-agnostic - only answer quality and speed change.
Keep the printed diagram. In b6 the same picture grows a checkpointer; in b7 a pause gate appears between two of these boxes.
The diagram in the design review. Teams that ship agents to regulated environments increasingly attach the rendered graph to change requests: reviewers approve a shape, not a prose description. Your two-line print is the toy version of a real governance artifact - the leader track's a4 audience is being taught to ASK for this exact picture.
Try it yourself - this week ◐ 30-45 min total
- Finish DataDesk v2 if you did not complete it live, on both engines. Commit it - b6 builds directly on this file.
- Add a fourth node:
sql_guard, a deterministic (no-LLM) node that runs afterstatsand refuses to pass along any answer containing "DROP" or "DELETE". Fixed edge in, fixed edge out - your first workflow segment inside an agent system. - Rewrite
classifyto returnCommand(update={"route": ...}, goto=...)instead of using a conditional edge (self-study card 1c). Decide which style you prefer and write one sentence why. - Print the Mermaid diagram before and after your changes and diff the two pictures - feel the "diagram is the code" property directly.
- Optional reading: the LangGraph graph-api concepts page on docs.langchain.com - after tonight it reads as a reference, not a tutorial.
Official sources covered
This track teaches from the official docs and the free LangChain Academy curricula (login required for lesson content; certificates stay with the Academy - all free). This page covers:
Three questions before you go 🎯 ◐ 90 seconds
1 · A LangGraph node is...
No classes, no magic: functions in, partial dict updates out, LangGraph merges them (via reducers where declared). Returning the whole state is the classic beginner bug.
2 · How does execution decide between the stats node and the fallback node in DataDesk v2?
add_conditional_edges registers a plain function that returns a string. The model only wrote "stats" into state; YOUR function turned that into control flow.
3 · When should you eject from create_agent down to LangGraph?
create_agent is production-grade for the tool-loop shape and runs ON LangGraph. Eject when the SHAPE no longer fits - routers, guaranteed steps, cycles you control, multiple agents.