07 Oct LangGraph Prebuilt Agents: create_agent vs Custom Graphs
In Chapter 11, you built a ReAct agent by hand, with about 20 lines of wiring. LangGraph’s ecosystem also offers a ready-made version that does the same job in one function call.
Update to our outline: this chapter was planned around create_react_agent, but LangGraph v1 deprecated create_react_agent in favor of LangChain’s create_agent. The import path moved from langgraph.prebuilt to langchain.agents, so we teach the current function. You will still see the old name in older tutorials, so it helps to recognize it.
Setup
create_agent lives in the langchain package:
pip install -U langchain langgraph
The whole agent in one call
from dotenv import load_dotenv
from langchain.agents import create_agent
from langchain_anthropic import ChatAnthropic
from langchain_core.tools import tool
load_dotenv()
@tool
def multiply(a: int, b: int) -> int:
"""Multiply two numbers."""
return a * b
@tool
def get_weather(city: str) -> str:
"""Get the current weather for a city."""
data = {"delhi": "34°C, sunny", "london": "15°C, cloudy"}
return data.get(city.lower(), "Weather data not available")
llm = ChatAnthropic(model="claude-sonnet-5-5")
agent = create_agent(
llm,
tools=[multiply, get_weather],
system_prompt="You are a helpful assistant. Use tools when they help.",
)
result = agent.invoke({"messages": [("human", "What is 6 times 7?")]})
print(result["messages"][-1].content)
Sample output:
6 times 7 is 42.
That one call replaces everything from Chapter 11: the agent node, ToolNode, tools_condition, and the loop edge.
What you get back
create_agent returns a compiled graph, the same kind of object as builder.compile(). That means everything you already know still works:
# Stream each step
for step in agent.stream(
{"messages": [("human", "What's the weather in Delhi?")]},
stream_mode="updates",
):
print(step)
# Draw the diagram
print(agent.get_graph().draw_mermaid())
The diagram shows the same agent-and-tools loop you built by hand.
Adding memory
The prebuilt agent accepts a checkpointer (covered fully in Chapter 13):
from langgraph.checkpoint.memory import InMemorySaver
agent = create_agent(
llm,
tools=[multiply, get_weather],
system_prompt="You are a helpful assistant.",
checkpointer=InMemorySaver(),
)
config = {"configurable": {"thread_id": "chat-1"}}
agent.invoke({"messages": [("human", "My name is Asha.")]}, config)
result = agent.invoke({"messages": [("human", "What's my name?")]}, config)
print(result["messages"][-1].content)
Sample output:
Your name is Asha.
Here, the thread_id groups messages into one conversation. Chapter 13 explains how it works.
Migrating old code
If you meet older tutorials, the change is small. The main differences:
- Import: from langgraph.prebuilt import create_react_agent becomes from langchain.agents import create_agent
- Prompt argument: prompt=”…” becomes system_prompt=”…”
- Tools argument: create_react_agent(llm, tools) becomes create_agent(llm, tools=tools)
Migration guides note that the prompt parameter was renamed to system_prompt.
When to use which
- Standard “model + tools” agent: create_agent
- Quick prototype or demo: create_agent
- Custom routing (classify, then pick a path): custom graph
- Extra steps before or after the model (validation, logging): custom graph
- Several models or agents with different roles: custom graph
- You want to understand or teach what happens inside: custom graph
create_agent also supports middleware, which lets you customize the loop without rebuilding the graph. It is a good next step once the basics feel comfortable.
A good rule of thumb: start with create_agent, and move to a custom graph when you need control it doesn’t give you. Since you now understand the graph underneath, you can do either.
The best of both: an agent inside a custom graph
Because create_agent returns a compiled graph, you can use it as a node in a bigger graph. Chapter 17 (subgraphs) covers this in depth. Here is a preview:
from langgraph.graph import StateGraph, MessagesState, START, END
builder = StateGraph(MessagesState)
builder.add_node("helper_agent", agent) # the prebuilt agent as one node
builder.add_edge(START, "helper_agent")
builder.add_edge("helper_agent", END)
graph = builder.compile()
You get a quick agent inside a workflow you control.
Common mistakes
- Using the old import: from langgraph.prebuilt import create_react_agent may still work but is deprecated, so prefer create_agent
- Forgetting pip install langchain: create_agent isn’t in the langgraph package alone
- Using prompt= instead of system_prompt=
- Skipping the thread_id when using a checkpointer: without it, memory won’t work
- Choosing the prebuilt agent when you need branching logic: switch to a custom graph
- Keeping tool docstrings vague: the model still chooses tools by reading them
Summary
- create_agent builds a complete tool-using agent in one call
- It returns a compiled graph, so invoke(), stream(), and draw_mermaid() all work
- create_react_agent is deprecated, and create_agent (with system_prompt) replaces it
- Use the prebuilt agent for standard cases, and a custom graph when you need control
Practice
- Rebuild your Chapter 11 agent with create_agent and compare the two diagrams
- Add the InMemorySaver and test that the agent remembers your name across two calls
- Wrap the agent inside a two-node custom graph, where the first node cleans the user’s question (trim and lowercase) before the agent sees it
If you liked the tutorial, spread the word and share the link and our website, Studyopedia, with others.
For Videos, Join Our YouTube Channel:Â Join Now
Read More:
- Generative AI Tutorial
- AI Ethics
- Machine Learning Tutorial
- Deep Learning Tutorial
- Ollama Tutorial
- Retrieval Augmented Generation (RAG) Tutorial
- ChatGPT Tutorial
- Microsoft Copilot Tutorial
No Comments