Nova's Team Goes Live with LangGraph

Part of the free Generative AI course on LogicWiz, module: Nova Builds a Team.

Episode 24: Nova's Team Goes Live with LangGraph

"On the whiteboard, Nova's travel team looks perfect: a router, two specialists, a synthesizer. But a diagram doesn't book a flight. To make it real — resilient, resumable, production-grade — Nova needs a framework that turns the picture into a running graph."


Nova Needs a Framework

You could wire agents together by hand, but people have built frameworks so you don't. The landscape: LangGraph (the one we'll use), plus Google ADK, Microsoft AutoGen, CrewAI, JADE, and LlamaIndex.

Why LangGraph? It's a low-level orchestration framework — it gives you fine-grained control instead of hiding the machinery, which is what you want for anything beyond a toy:

  • Fine-grained control over how agents move through the flow.
  • Streaming-first — responses stream out as they're generated.
  • Built-in persistence — state survives across steps and restarts.
  • Debuggability & observability — inspect and troubleshoot (it pairs with LangSmith).
  • Human-in-the-loop — pause for a person to review or decide, then resume.
  • Production-ready with LangGraph Platform, and the largest ecosystem — so when you hit a bug, someone has already solved it online.

LangGraph Is Just a Stateful Graph

Strip away the buzzwords and LangGraph is three things you already understand: nodes, edges, and a shared state.

{{visual:langgraph-anatomy}}

  • A node is just a function — a computation step. It processes input, makes a decision, or calls an API. A node can be an agent, but it doesn't have to be; it might be a plain function or a tool. (So a LangGraph can even run non-agentic, hard-coded workflows.)
  • An edge connects two nodes and defines the flow — which node runs next.
  • A conditional edge makes that dynamic: LangGraph reads the current state and decides where to go next. This is what lets the graph branch, loop, and choose.

That's the whole vocabulary. Everything else is arranging these pieces.

State: The Shared Whiteboard

Here's the piece that makes multi-agent coordination actually work. State is a shared whiteboard that every node reads from and writes to — not private notebooks each agent keeps to itself.

{{visual:shared-state}}

Think of it as the context or memory of the whole system: a living thing that's updated at every step. The Search Agent writes its findings to state; the Itinerary Agent reads them and adds its own; the Synthesizer reads everything. It's like four people working in one room where everyone can see what everyone else is doing. When we say one agent "accesses another agent's output," this is how — through the shared state.

And because the state lives in one place, LangGraph can checkpoint it — save the whole thing to a persistent store at each step. That buys three things that separate a demo from production:

  • Resume after failure — a node crashes, you reload from the last checkpoint instead of restarting from scratch.
  • Human-in-the-loop — pause, let a person weigh in, then pick up exactly where you left off.
  • Fault tolerance — network hiccups don't lose work.

💡 Checkpoints are per-conversation ("thread"). To share memory across threads — remembering a returning user in a brand-new session — LangGraph adds a Store interface, usually backed by an external database in production.

Wiring Nova's Travel Team

Now put it together. Nova's Smart Travel Planner is a graph: an Intake node takes the query, a Router node detects intent, the Search Agent and Itinerary Agent nodes do the specialized work, and a Synthesizer decides — via a conditional edge — whether the answer is complete or the itinerary flow also needs to fire.

{{visual:travel-graph}}

That conditional edge is the payoff of everything this chapter taught: a simple query ("cheapest flight to London?") resolves through the Search Agent alone; a complex one ("plan my week in London") triggers both flows in parallel, then the Synthesizer fuses them into one recommendation. Let's build a tiny version of exactly this — State, nodes, edges, compile, invoke:

{{cell:l24-graph}}

The Real Tools Behind the Graph

The tiny graph above uses plain Python nodes so it runs anywhere. The production travel planner wires the same shape to real tools. Two search APIs power the specialists:

  • SERP API — specialized hotel and flight searches (the Search Agent's tools).
  • Tavily API — general internet search, like a browser call behind an API (the Itinerary Agent's web tool).

And the Itinerary Agent's deep-research sub-agent is built with deepagents (create_deep_agent) — a pre-built ReAct loop, so you don't hand-roll reason → act → observe. Here's the real setup. It needs Tavily/SERP keys and the deepagents package, so it runs in Colab, not this in-browser sandbox:

from langchain_tavily import TavilySearch
from deepagents import create_deep_agent

# General web search tool (Tavily) — the Itinerary Agent's quick-lookup tool
internet_search = TavilySearch(
    max_results=5,
    topic="general",
    search_depth="advanced",
)

# A deep-research SUB-AGENT: deepagents gives you a ready-made ReAct research loop
itinerary_research = create_deep_agent(
    tools=[internet_search],
    instructions=(
        "You are a professional travel itinerary researcher. "
        "Only answer travel-related requests; politely decline anything else."
    ),
)

The Itinerary Agent keeps internet_search for quick Q&A and delegates heavy planning to itinerary_research — a sub-agent, exactly the context-quarantine pattern from the last episode. The Search Agent, meanwhile, calls the SERP API for live flight and hotel availability.

💡 Grab free keys at tavily.com (web search) and serpapi.com (flights/hotels). Load them from the environment — Colab's Secrets pane in a notebook, a real secrets manager in production — and never hard-code a key into a cell.

One Model, or Many?

A subtle but money-saving detail. If you write llm = ChatOpenAI() once and hand that same object to three agents, they share one instance (one underlying config). If you instead write llm1, llm2, llm3 as separate ChatOpenAI(...) calls, you get three independent instances, each with its own memory and settings.

Either way, an agent's behavior comes from its prompt, not the instance — three agents can share one LLM object and still act completely differently because their instructions differ.

This unlocks tiered models: give the router and simple responders a cheaper, lighter model, and reserve a stronger model for the agent doing heavy reasoning. Since minimizing tokens is a top priority, matching model capability to task complexity — right there in how you instantiate your LLMs — is one of the biggest levers you have.

⚠️ Don't reach for a multi-agent system by reflex. Start with one agent; add agents only when it hits a wall. The complexity you add — extra calls, tokens, coordination — has to earn its place.

What Nova Learned

Look how far Nova has come. She retrieves with RAG, reasons and calls tools as an agent, and now — when one agent isn't enough — she coordinates a team: routing work to specialists, orchestrating workers in parallel, quarantining messy subtasks in sub-agents, and running it all on a stateful, checkpointed LangGraph. That's not a chatbot anymore. That's a production multi-agent system — the same architecture that turned a 30-minute, $15 incident into a 30-second, sub-dollar one.

That's the end of Nova's build. From a blank model to a coordinated, measured, resilient system — you now know how the whole thing fits together.