Chapter 97 min read

Chapter 9: Agent Loops and ReAct Workflows

In Chapter 8, we built an Agent. We successfully passed a HumanMessage to the LLM, the LLM requested a tool, the ToolNode executed it, and the graph looped back to generate a final answer.

But why did it loop back? Why is a cycle superior to a straight line?

In this chapter, we will explore the actual execution patterns of AI Agents. We will look at multi-step reasoning, self-correction, infinite loop prevention, and the foundational framework of modern agents: ReAct.


9.1 What Makes an Agent an Agent?

A traditional workflow or pipeline (a DAG) executes a fixed sequence of steps. If you build a pipeline to write a blog post, it might always: Fetch Topic -> Generate Outline -> Write Draft -> Return.

An Agent, however, does not follow a fixed sequence. An agent dynamically decides its own sequence of actions based on the observations it makes along the way. It executes a sequence of decisions, not just one final answer.

Imagine asking: "Who is the CEO of the company that created Laravel?"

A simple LLM call might hallucinate. But an Agent thinks:

  1. Need creator of Laravel ➔ Execute Search Web.
  2. Observation: Taylor Otwell.
  3. Need company Taylor Otwell founded ➔ Execute Search Web.
  4. Observation: Laravel LLC.
  5. Need CEO of Laravel LLC ➔ Execute Search Web.
  6. Observation: Taylor Otwell.
  7. Final Answer: Taylor Otwell.

9.2 Understanding ReAct

The reasoning process shown above is formalizing a pattern known as ReAct (Reason + Act).

ReAct is a looping execution model that alternates between thinking and interacting with the environment.

Reason (I need to find the creator)
  ↓
Act (Call Search Tool)
  ↓
Observe (Read Tool Result)
  ↓
Reason (Now I need the company name)
  ↓
Act (Call Search Tool)
  ↓
Observe (Read Tool Result)

Note: Reasoning Is Often Hidden: Modern LLM APIs do not always expose the model's internal chain of thought as raw text. When we say "Reason", we are describing the conceptual process happening inside the model's neural network, which culminates in an Action (Tool Call) or a Final Answer.

In LangGraph, the ReAct pattern translates perfectly to our MessagesState array expanding over time:

HumanMessage: 
"What is Nepal's population times 2?"

AIMessage: 
[Tool Call -> search_web("population of nepal")]

ToolMessage: 
"30,500,000"

AIMessage: 
[Tool Call -> multiply(30500000, 2)]

ToolMessage: 
"61,000,000"

AIMessage: 
"The answer is 61,000,000."

9.3 Building a Minimal ReAct Graph

Let's look at the foundational topology of a ReAct Agent in LangGraph.

  START
    ↓
┌→ Agent ──(Answers Question)──→ END
│   │
│ (Requests Tool)
│   ↓
└─ Tool Node

This simple graph is infinitely powerful because of the cycle.

  • START ➔ Agent: The LLM reads the user's prompt.
  • Agent ➔ Tool Node: The LLM cannot answer yet, so it takes an Action.
  • Tool Node ➔ Agent: The tool executes, and the observation is handed back to the Agent.
  • Agent ➔ ...: The Agent now has the observation. It re-evaluates the State. Does it have enough information to answer? If yes, it routes to END. If no, it routes back to the Tool Node for step two.

9.4 Multi-Step Tool Usage

To prove the Agent is capable of dynamic planning, we don't have to change the graph structure at all. We just provide a harder question that requires chaining different tools together, like the Nepal population example above.

The Agent automatically figures out the plan:

  1. Reason: I need the population first.
  2. Act: search_web(query="Population of Nepal")
  3. Observe: ToolMessage("The population is 30,500,000")
  4. Reason: Now I need to multiply that by 2.
  5. Act: calculator(a=30500000, b=2)
  6. Observe: ToolMessage("61000000")
  7. Reason: I have the final answer.
  8. Act: AIMessage(content="The answer is 61,000,000.") ➔ Routes to END.

9.5 Self-Correction Loops

What happens if a tool fails? In a traditional pipeline, a failure crashes the application. In an Agent Loop, a failure is just another observation!

If search_web() throws a 500 server error, the ToolNode can be configured to return a ToolMessage containing the error string.

Agent ➔ Calls Tool
Tool ➔ Returns "Error: Service Unavailable"
Agent ➔ Observes Error
Agent ➔ Reasons: "The primary search failed. I will try the fallback database tool."
Agent ➔ Calls Fallback Tool

The Agent literally debugs its own execution and tries again.


9.6 Loop Termination (The Failsafe)

Because the Agent controls its own routing, there is a massive danger: Infinite Loops.

If the LLM gets confused, or a tool constantly returns vague data, the Agent might just keep calling the tool forever. while True: in an LLM application will bankrupt you in API costs.

You must implement a MAX_ITERATIONS failsafe in your conditional routing using an iteration_count state variable.

class AgentState(TypedDict):
    messages: Annotated[list[AnyMessage], add_messages]
    iteration_count: int # Add a counter!

def should_continue(state: AgentState):
    # Failsafe!
    if state.get("iteration_count", 0) >= 5:
        return END
        
    last_message = state["messages"][-1]
    if last_message.tool_calls:
        return "tools"
        
    return END

(Ensure your LLM node increments the iteration_count on every pass).


9.6.5 Deterministic vs Agentic Loops

It is important to understand that LangGraph supports two vastly different types of loops:

1. Deterministic Loops

Try API ➔ If Error ➔ Retry ➔ Max 3 Times

In a deterministic loop, the Python developer writes strict if/else logic that controls exactly how the loop executes. The LLM has no say in the routing.

2. Agentic Loops

Tool Result ➔ LLM Decides ➔ Next Action

In an agentic loop, the LLM evaluates the state and dynamically decides whether to loop back to the tools, or exit the graph.

LangGraph's superpower is that it allows you to blend both: using Agentic loops for reasoning, but wrapping them in Deterministic failsafes (like iteration_count >= 5) to guarantee safety.


9.7 Building a Research Agent

Let's put this together into a mini-project: An autonomous Research Agent.

  1. Question: User asks for an in-depth summary of a recent event.
  2. Research: Agent uses search_web() to gather facts.
  3. Evaluate: Agent looks at the facts. Are these facts sufficient?
  4. Loop: If the facts are missing details, the Agent queries search_web() again with a new, more specific query.
  5. Finalize: If the facts are sufficient, it compiles the final report.

This works using the exact same ReAct topology. The only difference is the system prompt guiding the LLM to be highly critical of its own research before providing a final answer.


9.8 Common Agent Failures

When engineering ReAct loops, monitor your traces for these common failure modes:

  1. Tool Addiction: The Agent gets stuck calling search_web over and over with slightly different queries, never deciding it has enough information. (Solved via prompt engineering or MAX_ITERATIONS).
  2. Hallucinated Plans: The Agent invents a tool that doesn't exist to solve a problem it doesn't know how to handle.
  3. Infinite Error Loops: A tool returns a syntax error, the Agent tries to fix it, fails, gets the same error, and repeats forever.
  4. Context Explosion: The Agent loops 10 times, pulling in massive ToolMessages each time. The MessagesState array grows so large it exceeds the LLM's token limit and crashes.

9.9 Summary

An Agent is not defined by the tools it has, but by its ability to Reason, Act, and Observe dynamically within a Control Flow cycle.

You now understand:

  • LLM + Tool ≠ Agent
  • LLM + Tools + Memory + Loop + Control Flow = Agent

At this point, we have built highly capable, intelligent systems. However, they are entirely ephemeral. When the Python script finishes executing, the Agent's memory disappears.

If we want to build true enterprise applications with crash recovery, pausing, human-in-the-loop approvals, and thread-based persistence, we must finally introduce the database layer.

In the next chapter, we will master Checkpointing and Durable Execution.

    Chapter 9: Agent Loops and ReAct Workflows — Mastering LangGraph: From State Machines to Production AI Agents | Krishna Tiwari