Coursify

Retrieval-Augmented Generation (RAG) — From Fundamentals to Production-Ready Agentic RAG Systems

ReAct Agent with Retrieval

Build a ReAct agent pattern using LangGraph with a retriever tool. Implement the observe-think-act loop: retrieve relevant docs, reason about the context, and generate answers.

Learning Goals

  • Build a ReAct agent with retrieval as a tool
  • Implement observe-think-act loop in LangGraph

ReAct Agent with Retrieval

The ReAct pattern (Reason + Act) is the foundation of modern AI agents. In this pattern, the LLM follows a loop: it Reasons about the current state, decides to take an Action (like calling a retriever tool), and then Observes the result. This cycle continues until the agent has enough information to provide a final answer.

In this lesson, we will implement a ReAct agent using LangGraph that can dynamically decide when to retrieve information from our vector store.

Learning Goals

  • Define the ReAct reasoning loop.
  • Build a stateful graph that connects an LLM with a retriever tool.
  • Implement conditional routing to stop the loop when an answer is found.

Core Concepts

1. The Observe-Think-Act Loop

Unlike a chain, the ReAct agent is non-linear.

  • Think: "I need to know the price of gold in 2023 to answer this."
  • Act: Call search_finance_data tool.
  • Observe: "The tool returned $1,940/oz."
  • Think: "Now I have the data. I can generate the final answer."

2. StateGraph: The Agent's Map

In LangGraph, we define the agent as a StateGraph. This graph has:

  • State: A shared object that tracks the list of messages (conversation history).
  • Nodes: agent (thinking) and action (tool execution).
  • Edges: Logic that flows from agent to tools and back.

Agent State Machine

Building the ReAct Graph

  1. 1
    Step 1

    Use a simple dictionary or a TypedDict to track messages:

    1from typing import Annotated, TypedDict 2from langgraph.graph.message import add_messages 3 4class State(TypedDict): 5 messages: Annotated[list, add_messages]
  2. 2
    Step 2

    Create a StateGraph and define the nodes:

    1from langgraph.graph import StateGraph, START, END 2 3workflow = StateGraph(State) 4 5# Define the nodes 6workflow.add_node("agent", call_model) 7workflow.add_node("tools", tool_node)
  3. 3
    Step 3

    Use conditional logic to decide if tools are needed:

    1workflow.add_edge(START, "agent") 2workflow.add_conditional_edges( 3 "agent", 4 should_continue, # Logic gate function 5) 6workflow.add_edge("tools", "agent")
  4. 4
    Step 4
    1app = workflow.compile() 2for chunk in app.stream({"messages": [("user", "What is RAG?")]}): 3 print(chunk)

Example: The Multi-Step Researcher

Imagine you ask an agent: "Compare the weather in Tokyo today with the average weather in 1990." The agent will:

  1. Call a live_weather tool for Tokyo.
  2. Call a historical_weather_retriever tool for 1990 data.
  3. Think about the difference.
  4. Finalize the response. A standard RAG chain would struggle to coordinate these two separate data sources sequentially.

Common Mistakes

  • Infinite Loops: If the agent doesn't realize it has the answer, it might keep calling the tool. Ensure your prompt clearly says: "If you have the information, provide the final answer."
  • Forgetting Tool Nodes: Tools must be executed in a separate node, not inside the LLM node. This keeps the architecture clean and allows for "Human-in-the-loop" approval if needed.

Recap

  • ReAct combines reasoning with tool execution.
  • LangGraph's StateGraph is the standard way to build these loops.
  • Conditional edges are the "Decision Gates" of the agent.

Knowledge Check

Question 1 of 3
Q1Single choice

What does the 'Observe' step in the ReAct loop represent?

ReAct Agent with Retrieval | Retrieval-Augmented Generation (RAG) — From Fundamentals to Production-Ready Agentic RAG Systems | Coursify