Skip to content
Forward Deployed

Forward Deployed
Lessons and contents
Learn

ReAct Agents & LangChain create_agent: overview

Source
From the RAG & Agents Engineering course
By
Sourav Banerjee
Last updated
8 Nov 2026

Report an issue

A Larkspur handbook search misses the refund-timing passage. The agent needs to read the result, rephrase the search and leave enough call budget to answer. You will trace that feedback loop, inspect the graph built by create_agent, return validated fields and add middleware for limits and approval. The tutorials cover reason, act and observe, the agent factory, structured output and middleware.

The running example is a support agent for the Larkspur Cloud handbook from T5.1 to T5.3. Its one tool, search_handbook, is the T5.1 lab's TF-IDF retriever over twelve chunks, and its questions are the T5.1 golden set: Can I export my data after I cancel my plan?, How long does a refund take? and What happens if my server goes down? The interview questions add the tools a real support agent would have, such as an account lookup and a refund action.

In short

  • ReAct interleaves reasoning and tool calls, and reads every observation before choosing the next step. The difference from a single-shot tool call is one edge, tools → model.
  • In the lab, the loop lifts mean evidence recall on the T5.1 golden set from 0.50 (one search, the T5.1 baseline) to 1.00 by rewording failed searches, for 9 model calls instead of 3. Every call rereads the whole message list, so cost grows each round.
  • create_agent(model, tools, system_prompt=...) returns that loop as a compiled LangGraph graph (model ⇄ tools) on native tool calls, so there is no text to parse.
  • response_format=Schema on an agent, or with_structured_output(Schema) on a model, returns structured data for the next system to validate; Pydantic is the style that validates it.
  • Middleware hooks run before and after each model call: ModelCallLimitMiddleware bounds the loop, HumanInTheLoopMiddleware pauses irreversible tool calls for approve, edit or reject, PIIMiddleware redacts, SummarizationMiddleware compresses history.

Mental model

The ReAct loop with middleware hooks A question enters the loop. Before each model call a before_model hook checks the call cap; after it an after_model hook can pause for approval. While the model asks for a tool, the tools run and their ToolMessage goes back to the model. For the lab’s outage question the first two searches return reboot and sizing, the third returns incidents and sla, and the fourth model call answers: four calls, about 451 tokens. With run_limit set to 3 the before_model hook would end the run before call 4. Questionserver goes down before_modelcall cap Modelreason after_modelapproval Toolsact: search Answer4 calls, 451 tokens tool call ToolMessage no tool call model calls run_limit=3: stops before call 4 Observations 1 reboot, sizing 2 reboot, sizing 3 incidents, sla
  1. The question enters as a HumanMessage. Before every model call, the before_model hooks run; the call cap is one of them.
  2. Model call 1 reads the message list and asks for search_handbook with the question’s own words.
  3. The tool returns reboot and sizing, which share the word “server” but say nothing about outages. The ToolMessage goes back to the model.
  4. Call 2 rewords the search to “server outage”. TF-IDF still ranks reboot and sizing first.
  5. Call 3 searches “what happens during an outage incident” and gets both evidence chunks, incidents and sla.
  6. Call 4 has the evidence and asks for no tool, so the run ends with an answer: four calls, about 451 tokens of context read.
  7. With run_limit=3 the before_model hook ends the run before call 4, and the user receives the limit message instead.

The model is the only part that decides; the graph executes and the middleware guards. A run is as long as the model's decisions make it, so every production agent pairs the loop with a cap, and every irreversible tool with a checkpoint where a person can stop it.

Interactive lab

The ReAct loop and its call cap: open the file in a browser. Pick What happens if my server goes down? and switch between single shot and ReAct: one search returns reboot and sizing, the loop rewords twice and finds incidents and sla. Then drag the call cap down to 3 and watch the run stop with both evidence chunks already in the message list, one call short of the answer.

How it connects

  • Before: T7.1 introduces the agent loop and tool calling this module names ReAct. T4.3 and T4.4 teach the LangGraph state, persistence and interrupts that create_agent and its middleware compile to. The lab's tool is the T5.1 baseline retriever, and its rewording does by hand what query rewriting (T6.2) does on purpose.
  • Next: T7.3 sets fixed workflows beside this loop, T8.1 adds planning and reflection, and T8.3 uses human approval in applied single-agent builds. T9.1 to T9.5 build agentic RAG on these pieces; T9.4 makes the retriever an agent tool.

Key Takeaways

  • Use ReAct when the next step depends on what a tool returns; use a planned pipeline when the steps are known.
  • Read the ToolMessages before you blame the model. A loop that keeps searching usually has a tool that returns the wrong thing.
  • Give every loop a call cap sized from your golden set, and gate every irreversible tool with human approval.
  • When code consumes the answer, ask for a schema, validate it with Pydantic, and make fields optional when the source may not contain them.

Rate your confidence and keep notes on the module page.