PromptABCD
FeaturesLearnHow it worksUse casesFAQGuideBlogContext Blocks
Sign inGet started free
Sign inSign up
PromptABCD

A calm home for your best AI prompts. Save them once, find them in seconds, reuse them forever.

Product

  • Features
  • Chrome Extension
  • Free Courses
  • How it works
  • Use cases
  • Blog
  • Context Blocks
  • Export Anywhere
  • FAQ

Resources

  • User guide
  • Learn prompting
  • Sign in
  • Get started free

© 2026 PromptABCD. All rights reserved.

Privacy PolicyTerms and Conditions
Home/Blog/AI Agents/Building an AI Agent With LangGraph
AI Agents

Building an AI Agent With LangGraph

Most LangGraph agent tutorials start you at the hardest place. This one shows the one-line prebuilt path first — and exactly when to graduate to a hand-built graph.

August 15, 2026·8 min read
ShareShare
⚡Featured Prompt— copy and use right now
from langgraph.prebuilt import create_react_agent

# tools are plain functions; the docstring becomes the description
agent = create_react_agent(model, tools=[search_docs, lookup_order])

result = agent.invoke(
    {"messages": [{"role": "user", "content": "Where is order ORD-5?"}]}
)
print(result["messages"][-1].content)

Here's a stat that should change how you approach this: the overwhelming majority of LangGraph agents that reach production for standard tool-calling never hand-build a graph at all — they use the prebuilt

create_react_agent
in a line or two. Yet nearly every LangGraph agent tutorial opens by walking you through nodes, edges, and state by hand, which is the hardest possible on-ramp for the most common case. This one goes the other way.

Let me show it through a team that learned the ordering the hard way.

The Problem: A LangGraph Agent Tutorial That Skipped the Prebuilt Path

A three-person team wanted an agent that answered support questions using two tools: a docs search and an order lookup. Standard stuff — a model that calls tools in a loop until it can answer. They followed a popular tutorial that built everything manually: a

StateGraph
, node functions, edges wiring the model to the tools and back, a conditional edge to decide whether to loop or finish.

It took them three days and about two hundred lines. It worked, eventually. Then they discovered that LangGraph ships

create_react_agent
, a prebuilt that does exactly the standard tool-calling loop, and realized their two hundred lines reproduced — less reliably — what a one-liner already did.

Every one of those lines was correct, which is what made it frustrating. They hadn't done anything wrong in the tutorial's terms. They'd just followed a tutorial that answered a question — how do LangGraph's primitives work — that wasn't the question their task was asking, which was simply how to ship a tool-calling agent.

The Wrong Approach

Their mistake wasn't using LangGraph. It was starting at the wrong level of the framework. LangGraph has a deliberate two-level design: high-level prebuilts for common patterns, and the low-level

StateGraph
primitive for when you need custom control. They'd reached for the primitive to build something the prebuilt already handled.

The manual graph gave them nothing their task needed. A standard tool-calling agent is a solved pattern; reimplementing it by hand just meant more code to maintain and more places for their version to diverge from the well-tested one.

There's a deeper cost too. By hand-building the standard loop, they'd taken on maintenance of something LangGraph's team maintains for them. Every upgrade that improved the prebuilt agent passed them by, because they were effectively running their own fork of the pattern. Reimplementing a solved problem doesn't just cost the initial days — it opts you out of every future improvement to the thing you reimplemented.

⚡ Pro tip: For any standard tool-calling agent, start with

create_react_agent
. Reach for a hand-built
StateGraph
only when you need control the prebuilt doesn't give you — not before, because the primitive is the expert tool, not the beginner one.

The Correct Pattern

They deleted the two hundred lines and replaced them with the prebuilt.

hljs python
[object Object], langgraph.prebuilt ,[object Object], create_react_agent

,[object Object],
agent = create_react_agent(model, tools=[search_docs, lookup_order])

result = agent.invoke(
    {,[object Object],: [{,[object Object],: ,[object Object],, ,[object Object],: ,[object Object],}]}
)
,[object Object],(result[,[object Object],][-,[object Object],].content)

What this does: it builds a complete tool-calling agent — the model, the loop, the tool dispatch, the stop condition — in one call.

create_react_agent
wires the ReAct pattern (reason, act, observe, repeat) for you, so you write the tools and nothing else. This is the same agent their two hundred lines built, minus the two hundred lines.

Notice what you still write: the tools.

create_react_agent
handles the orchestration, but the tools — and their docstrings — are yours, and they're where the agent's real behavior comes from. The prebuilt saves you the plumbing, not the thinking about what your agent should be able to do.

⚡ Pro tip: In LangGraph, a tool is a normal Python function and its docstring becomes the description the model reads. Everything you know about writing sharp tool descriptions applies directly to the docstring — that text does the heavy lifting.

Results and What Changed

The rewrite cut their agent code by roughly 90% and made it more reliable, because the prebuilt is battle-tested across thousands of deployments while their hand-rolled loop was tested across three days.

The reliability gain is easy to underrate. A prebuilt used across thousands of production agents has had its edge cases found and fixed by other people's incidents. Your three-day version has had its edge cases found by your customers. Standing on well-worn code is a feature, not a compromise.

Then, weeks later, a real requirement arrived that finally justified the graph: before issuing any refund, a human had to approve. That's not the standard loop — it's a branch that pauses for outside input. This time, dropping to

StateGraph
was the right call, because now they needed control the prebuilt didn't offer.

hljs python
[object Object], langgraph.graph ,[object Object], StateGraph, START, END

builder = StateGraph(State)
builder.add_node(,[object Object],, decide_node)
builder.add_node(,[object Object],, approval_node)
builder.add_node(,[object Object],, execute_node)
builder.add_edge(START, ,[object Object],)
builder.add_conditional_edges(,[object Object],, route, {,[object Object],: ,[object Object],,
                                                ,[object Object],: ,[object Object],})
builder.add_edge(,[object Object],, ,[object Object],)
builder.add_edge(,[object Object],, END)
graph = builder.,[object Object],()

What this does: it builds a custom flow where a routing function sends risky actions through a human-approval node and safe ones straight to execution. This is exactly what the graph model is for — cycles, branches, and human-in-the-loop that the prebuilt can't express. The complexity is now buying something.

This is the payoff of understanding the two levels. The team didn't fight the framework or over-build up front; they used the simple thing until a real requirement demanded the powerful thing, then reached for exactly the powerful thing they needed. That sequencing — simple until proven insufficient — is the whole art of using LangGraph well.

⚡ Pro tip: The signal that you've genuinely outgrown

create_react_agent
is a requirement the standard loop can't express — a human approval step, a branch, a cycle with custom routing. Until you hit one of those, the prebuilt is not a limitation, it's a gift.

How to Apply This to Your Situation

Start every LangGraph project with

create_react_agent
and real tools. Get it answering correctly first. That alone covers a large share of agent use cases, and you'll have working software in an hour instead of three days.

Concretely, this ordering fits most teams. A startup shipping a support agent uses the prebuilt and moves on. A fintech team adds a

StateGraph
only around the approval gate their compliance team requires. A data team building a multi-step research pipeline reaches for the graph because the steps genuinely branch. Prebuilt for the common case, graph for the specific need — the same rule across very different projects. The instinct to build the general thing first is natural for engineers, but with frameworks that ship strong defaults, it's usually the expensive path.

When a requirement appears that the standard loop can't handle — approval gates, multi-step branching, resumable long-running flows — then drop to

StateGraph
for that specific need. You'll understand exactly why you're adding the complexity, which makes the graph easier to design and debug.

And when you do build a graph, keep the state definition small. The

State
TypedDict is the data flowing between nodes; the leaner it is, the easier the graph is to reason about.

A good habit: add a field to

State
only when a node actually needs to read or write it. State that exists "just in case" is state every future node has to account for and every bug has to be checked against — lean state is faster to build and far faster to debug.

⚡ Pro tip: Keep your graph's

State
as minimal as the task allows. Every field is something each node might read or write, so a bloated state object makes every node harder to understand and every bug harder to trace.

Next Steps

The right LangGraph agent tutorial ordering is prebuilt first, primitive second. Use

create_react_agent
for standard tool-calling agents and drop to
StateGraph
only when a real requirement — a branch, a cycle, a human approval step — needs control the prebuilt can't give. Starting at the primitive is the single most common way teams turn an hour of work into three days. The framework isn't the enemy and neither is simplicity — the enemy is mismatching the two, reaching for power you don't need or hand-rolling a pattern that already exists and is better maintained than yours ever will be.

⚠️ Common mistake: Hand-building a

StateGraph
for a standard tool-calling agent because that's what the tutorial showed, ending up with hundreds of lines that reproduce, less reliably, what a prebuilt one-liner already does. Match the level of the framework to the complexity of your task, not to the length of the tutorial you happened to read.

Whether you use the prebuilt or a custom graph, the tool docstrings and system instructions that steer the agent are the same reusable assets. PromptABCD keeps them versioned in one place, so when you graduate from

create_react_agent
to a hand-built graph, your carefully written tool descriptions carry over untouched instead of being retyped into node functions.

langgraph agent tutoriallanggraphai agentspythoncreate_react_agentagent tutorial

Continue Reading

Building an AI Agent With the OpenAI Agents SDK
AI Agents

Building an AI Agent With the OpenAI Agents SDK

Spent a week hand-rolling retries and tracing? This OpenAI Agents SDK tutorial gets you a tool-using agent — with handoffs and guardrails — in far fewer lines.

August 15, 2026·8 min read
Do You Even Need an Agent Framework?
AI Agents

Do You Even Need an Agent Framework?

Most agent tutorials push a framework you may not need. This teardown of the agent framework vs no framework decision shows when raw code wins and when it doesn't.

August 15, 2026·8 min read
AI Agent Frameworks Compared: LangGraph vs CrewAI vs AutoGen
AI Agents

AI Agent Frameworks Compared: LangGraph vs CrewAI vs AutoGen

Want AI agent frameworks compared without the hype? Here's the honest 2026 rundown of LangGraph, CrewAI, and AutoGen — including the one that quietly went into maintenance mode.

August 15, 2026·8 min read

Save the prompts from this post

PromptABCD is a free prompt manager. Paste, organize, and reuse your best AI prompts — no more hunting through chat history.

Start free →
← PreviousBuilding an AI Agent With the OpenAI Agents SDK
Share this post:
ShareShare