Zenaique

When does the LangChain create_agent prebuilt work better than a hand written StateGraph?

MCQ·Medium·4.0 · 0·~1 min·Asked atCapgeminiDeloitteEvenup
Attempt it
TL;DR

The create_agent prebuilt wins on the standard tool-calling loop. Reach for a hand-written StateGraph when routing, state-driven topology, or interrupts need custom logic.

Memory aid
Sign in to see the mnemonic that makes this stick.
Easy to grasp

Imagine ordering coffee. The default menu has espresso, latte, and cappuccino: three preset orders the barista makes in seconds. If that is what you want, you say 'latte' and you are done. If you want oat milk, half the foam, an extra shot, and a sprinkle of cinnamon on top, you have to spell out each step. The preset menu does not have a button for it. The create_agent prebuilt is the preset menu: a standard tool-calling loop with one well-known shape. The hand-written StateGraph is the custom order. It takes more typing, but you can spell out every step the way you want.

Concept explanation~2 min read

Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.

There are two surfaces for building LangGraph agents. One is create_agent from langchain.agents, a prebuilt that encapsulates the most common loop and replaces the deprecated create_react_agent. The other is StateGraph, the lower-level primitive that lets you draw any graph. Choosing between them is one of the first decisions in a LangGraph project. The wrong choice shows up either as boilerplate you did not need or as a prebuilt you cannot extend.

The ReAct loop the prebuilt encodes

create_agent is a single function that assembles and compiles a LangGraph graph: a model node that calls the LLM, a tools node that executes any tool calls the model emitted, and conditional edges that loop back to the model after tools or end if there were no tool calls.

python
from langchain.agents import create_agent
from langchain_core.messages import HumanMessage
from langchain_openai import ChatOpenAI
from langgraph.checkpoint.memory import InMemorySaver

model = ChatOpenAI(model='gpt-5.5')
agent = create_agent(model, tools=[search_tool, calc_tool], checkpointer=InMemorySaver())

result = agent.invoke(
    {'messages': [HumanMessage('What is the current temperature in Paris in F?')]},
    config={'configurable': {'thread_id': 'thread-1'}},
)

Under the hood the state is AgentState, a TypedDict whose messages key uses the add_messages reducer to append to the list. The agent loop reads the latest message, decides if it is a tool call, runs the tools, appends the results, and re-invokes the model. The loop terminates when the model emits a message with no tool calls. The checkpointer persists the state at every super-step so the run is resumable.

This covers the canonical 'tool-using assistant' shape that ~70% of agent apps need. The prebuilt's value is not novelty. It is the well-tested boilerplate, the streaming defaults, the LangSmith / Langfuse tracing that needs little setup, and the consistent interrupt API.

What the prebuilt locks you into
Interrupts: per-tool middleware vs any node
Migration: prebuilt to StateGraph without losing checkpoints
Sign in to unlock the full deep dive.

Situations where this technique stops working.

Sign in to see when this approach fails.

2–4 min · Everything important, quickly.

Sign in to see the quick scan of the deep dive.
Axiscreate_agent prebuiltHand-written StateGraph
State schemaAgentState (messages), extendable with a TypedDict state_schemaAny TypedDict you define
Topologymodel → tools → modelAny nodes and edges you need
Custom routingNoConditional edges, per-output dispatch
InterruptsHumanInTheLoopMiddleware, per toolinterrupt() inside any node
Parallel branchesParallel tool calls onlyYes (super-step + reducers)
Best forTool-using agent with no custom flowMulti-agent, plans, structured state, HITL

Real products, models, and research that use this idea.

  • LangChain's own agent templates default to create_agent for tool-using bots, swapping to StateGraph for the supervisor and swarm templates.
  • LangSmith Studio shows create_agent runs as a fixed model-and-tools graph; custom StateGraphs render with whatever topology the developer drew.
Sign in to see more production examples.

What an interviewer would ask next. Try answering before peeking at the approach.

QHow would you migrate from the create_agent prebuilt to a hand-written StateGraph without losing checkpoint compatibility?
A

Mirror the prebuilt's messages key and its add_messages reducer in your TypedDict, and attach the same checkpointer. Then add your custom fields and routing. Existing checkpoints replay because the messages slice is byte-compatible.

2 more follow-ups an interviewer would ask next. Sign in to reveal them.

Red flags & common mistakes

The phrases that signal junior thinking. Click to expand.

Most common mistake

Writing a StateGraph for a vanilla tool-calling loop. That is 40 lines of boilerplate the create_agent prebuilt would have given you.

Sign in to see all red flags and common mistakes.

60 second bullets to scan on the way to the call.

  • The ReAct loop shape (LLM, tool, LLM, done)

  • What state schema create_agent uses and how state_schema extends it

Sign in to unlock the revision sheet.

Primary sources. Browse if you want the original framing.

Similar questions

Same topic, related formats. Practice these next.

4 curated
Next question
Identify the concrete lock in costs a framework imposes on a production codebase (select all that apply)
Multi-select·Medium