chapter four

4 Implementing a basic ReAct agent

 

This chapter covers

  • ReAct, the core pattern behind modern AI agents
  • Managing agent state with ExecutionContext
  • Unifying local functions and MCP tools
  • Building the LLM communication layer
  • Implementing a ToolCallingAgent with the think-act loop
  • Adding structured output with Pydantic models
  • Testing agent performance on the GAIA benchmark

We’ve explored how LLMs work and given them the ability to use tools. Now it's time to combine these pieces into something more powerful: an agent that can reason about what it needs, take actions to get it, and continue until it solves the problem.

As shown in figure 4.1, we’ll now complete the foundation of the basic agent loop by building an Agent using the ReAct pattern, chaining multi-step reasoning and actions to solve problems end-to-end, and adding robust error handling. ReAct (Reasoning + Acting) is not a framework but a way of designing agents that mirrors how humans solve problems: assess the situation, decide what information or action is needed, execute that action, observe the results, and repeat

Figure 4.1 Book structure overview - Chapter 4 in focus.

4.1 How ReAct agents work

4.1.1 The think-act cycle

4.1.2 From text parsing to tool calling

4.2 Agent architecture overview

4.2.1 The completed agent

4.2.2 Information flow: The core design

4.2.3 Components we need to build

4.3 ExecutionContext: The agent's central storage

4.3.1 What happens during agent execution?

4.3.2 Implementing ExecutionContext

4.4 Tool abstraction

4.4.1 Why we need a unified tool interface

4.4.2 BaseTool: The foundation

4.4.3 FunctionTool: Wrapping functions

4.4.4 Integrating MCP Tools

4.5 LLM Communication layer

4.5.1 Why a communication layer?

4.5.2 LlmRequest: Selecting what to send

4.5.3 LlmResponse: Standardizing what we receive

4.5.4 LlmClient: The provider adapter

4.5.5 Putting it together

4.6 Implementing the agent

4.6.1 Agent class structure

4.6.2 The run() Method

4.6.3 The step() method

4.6.4 The think() and act() methods

4.7 Adding structured output