BD Brain Drip
Building Your First Agent

Prebuilt ReAct Agent

create_react_agent from langgraph.prebuilt is the highest-level abstraction for building a fully functional tool-calling agent in under 10 lines of code.

Prerequisites | tool-calling-loop.md langgraph-overview.md

What Is the Prebuilt ReAct Agent?

Imagine you want to drive somewhere. You could build a car from raw steel and rubber, or you could walk into a dealership and drive one off the lot. create_react_agent is the dealership option. It gives you a complete, production-ready agent with a built-in reason-act-observe loop, automatic tool execution, and message management – all wired together and ready to go.

Under the hood, it constructs a full StateGraph with a model node, a tool-execution node, and conditional routing between them. But you never have to touch any of that. You hand it a model, a list of tools, and optionally a system prompt, and it returns a compiled graph that handles the entire ReAct cycle automatically.

This is the recommended starting point for most agent projects. You get the same architecture you would build manually (see Manual React Agent), but without the boilerplate. When you eventually need custom routing, state, or control flow, you can graduate to the manual approach.

How It Works

Minimal Example

from langgraph.prebuilt import create_react_agent
from langchain_anthropic import ChatAnthropic

model = ChatAnthropic(model="claude-sonnet-4-5-20250929")

agent = create_react_agent(
    model=model,
    tools=[search, calculate],
    prompt="You are a helpful research assistant.",
)

result = agent.invoke({
    "messages": [{"role": "user", "content": "What is 25 * 4?"}]
})

print(result["messages"][-1].content)

Using a Model String

You can pass a model identifier string instead of an instance. LangGraph resolves it using the init_chat_model interface:

agent = create_react_agent(
    model="anthropic:claude-sonnet-4-5-20250929",
    tools=[search, calculate],
)

Adding Memory with a Checkpointer

To make the agent remember previous turns across invocations, pass a checkpointer and a thread_id in the config:

from langgraph.checkpoint.memory import MemorySaver

agent = create_react_agent(
    model=model,
    tools=[search, calculate],
    checkpointer=MemorySaver(),
)

config = {"configurable": {"thread_id": "user-session-42"}}
result = agent.invoke(
    {"messages": [{"role": "user", "content": "Remember my name is Amit."}]},
    config=config,
)

What the Function Builds Internally

When you call create_react_agent, it constructs a StateGraph equivalent to:

  1. An agent node that calls the LLM with the current messages and available tool schemas.
  2. A tools node (ToolNode) that executes any tool calls the LLM requested.
  3. A conditional edge using tools_condition – if the LLM response contains tool calls, route to the tools node; otherwise, route to END.
  4. An edge from the tools node back to the agent node, completing the loop.

This is the exact same graph described in Manual React Agent, assembled for you automatically.

Why It Matters

  1. Rapid prototyping – go from zero to a working agent in under 10 lines, letting you validate ideas before investing in custom architecture.
  2. Best-practice defaults – the prebuilt agent encodes the standard ReAct loop correctly, eliminating an entire class of wiring bugs.
  3. Smooth upgrade path – since the prebuilt agent produces a normal compiled StateGraph, you can inspect it, stream from it, and eventually replace it with a manual graph when your needs grow.
  4. Checkpointer compatibility – passing a checkpointer gives you multi-turn memory with zero additional code, which is critical for conversational agents.

Key Technical Details

  • Returns a compiled CompiledStateGraph, not a special agent class – all standard LangGraph APIs (.invoke(), .stream(), .astream()) work on it.
  • The prompt parameter accepts a string (converted to a system message) or a list of messages prepended to every invocation.
  • The tools parameter accepts any mix of LangChain BaseTool instances and plain Python functions decorated with @tool.
  • The model must support tool calling (OpenAI, Anthropic, Google models all do).
  • If no checkpointer is provided, the agent is stateless – each .invoke() call is independent.
  • The agent automatically handles the message format conversion between user messages, AI messages with tool calls, and ToolMessage results.
  • You can pass state_schema to extend the default AgentState with custom fields if needed.

Common Misconceptions

  • “The prebuilt agent is a toy that cannot be used in production.” It produces the same compiled graph you would build manually. Many production systems start and stay with it.
  • “You cannot customize the prebuilt agent at all.” You can pass a custom state_schema, custom prompt, and even a state_modifier callable for dynamic prompt injection.
  • “The prebuilt agent only works with OpenAI models.” It works with any LangChain chat model that supports tool calling, including Anthropic, Google, Mistral, and others.
  • create_react_agent and AgentExecutor are the same thing.” AgentExecutor is the legacy LangChain abstraction. create_react_agent is the LangGraph replacement with better streaming, persistence, and human-in-the-loop support.

Connections to Other Concepts

  • Tool Calling Loop – the fundamental cycle that this function automates end to end.
  • Manual React Agent – the manual equivalent, for when you need full control over every node and edge.
  • Structured Output – often used alongside the agent for parsing or evaluating the agent’s final output.
  • state-and-message-management.md – how the add_messages reducer accumulates the conversation history inside the graph.
  • checkpointing-and-memory.md – deep dive on the checkpointer that enables multi-turn memory.

Further Reading