liveBook · Manning

Chapter 4: Implementing a basic ReAct agent

What you will learn in chapter 4 of Build an AI Agent (From Scratch)

This introduction presents ReAct as the repeating reasoning-and-action pattern that combines an LLM with tools to solve problems.

After this chapter you will be able to

What it builds on

Section by section

Introduction

This introduction presents ReAct as the repeating reasoning-and-action pattern that combines an LLM with tools to solve problems.

Key terms: ReAct, reasoning and acting, agent loop

4.1 How ReAct agents work

Introduces ReAct as a pattern in which an agent reasons about what it needs, then acts to obtain it, rather than answering immediately.

Key terms: ReAct, thinking and acting

4.1.1 The think-act cycle

This section explains how a ReAct agent repeats a think-act-observe cycle and adapts its next step to what it discovers.

Key terms: ReAct agent, think-act cycle, LLM, tools, fixed script

4.1.2 From text parsing to tool calling

This section explains how API-supported tool calling replaces fragile text parsing in ReAct agents while preserving their reasoning-and-action cycle.

Key terms: text parsing, tool calling, structured outputs, arguments, ReAct, thought, reasoning, tool selection, observe

4.2 Agent architecture overview

This section introduces the upcoming overview of the agent architecture before its components are explained.

4.2.1 The completed agent

A simple agent interface hides the work of deciding whether a question needs a tool, using one if necessary, and returning an answer.

Key terms: agent, tools, final answer, calculator tool

4.2.2 Information flow: The core design

This section explains how an agent’s execution state flows through an ExecutionContext-centered design and why LLM requests contain only a selected part of that state.

Key terms: LLM, tools, final answer, ExecutionContext, events, current_step, execution_id, state, final_result, LlmRequest

4.2.3 Components we have to build

This section outlines the order in which the agent’s components will be implemented.

4.3 ExecutionContext: The agent’s central storage

This section explains why an agent needs ExecutionContext as central storage for shared state.

Key terms: ExecutionContext, state

4.3.1 What happens during agent execution

The section turns an agent’s sequence of messages and tool use into identifiable content types and events that can be traced during debugging.

Key terms: Messages, Tool calls, Tool results, type field, discriminator, tool_call_id, ToolResult, ToolCall, Event, metadata

4.3.2 ExecutionContext implementation

This section identifies the data stored in ExecutionContext and explains how tools may use it to access execution state.

Key terms: ExecutionContext, execution_id, events, current_step, max_steps, final_result, state

4.4 Tool abstraction

This introduction explains why the function-based tools used to learn tool calling are not sufficient for a complete agent framework.

Key terms: Python functions, tool definitions, tool calling, agent framework

4.4.1 Why we need a unified tool interface

This section explains why an agent needs a unified tool interface instead of managing tool functions and their metadata separately.

Key terms: tool abstraction, tool definitions, metadata

4.4.2 BaseTool: The foundation

This section defines the BaseTool contract: the information every tool exposes, how it executes with shared context, and a few conveniences for implementing tools.

Key terms: BaseTool, name, description, tool_definition, execute, ExecutionContext, context propagation, Agent, class name, docstring

4.4.3 FunctionTool: Wrapping functions

This section explains how FunctionTool wraps ordinary functions as agent tools, handles context only when a function accepts it, generates tool definitions, and offers @tool as a convenient wrapper.

Key terms: FunctionTool, BaseTool, ExecutionContext, context propagation, execute, _generate_definition, function_to_input_schema, tool schema, type hints, @tool

4.4.4 Integrating MCP tools

This section shows how to adapt remote MCP tools to the agent’s existing tool interface and notes a connection overhead in the simple implementation.

Key terms: MCP tools, load_mcp_tools, FunctionTool, BaseTool, session.call_tool(), tool_definition, mcp_tool.inputSchema, new connection, persistent session, connection setup

4.5 LLM communication layer

Introduces the LLM communication layer as the bridge between the agent’s internal data structures and the LLM API.

Key terms: ExecutionContext, BaseTool, LLM communication layer

4.5.1 Reasons for adding a communication layer

The section explains why an agent needs a communication layer between its execution data and LLM APIs, and divides that layer into request, client, and response components.

Key terms: ExecutionContext, Events, ContentItems, LiteLLM, communication layer, LlmRequest, LlmClient, LlmResponse

4.5.2 LlmRequest: Selecting what to send

This section defines what LlmRequest sends in a single LLM call and explains why the agent, rather than the request object, selects that information.

Key terms: LlmRequest, instructions, contents, ContentItem, ToolCalls, ToolResults, ExecutionContext, Events, context engineering

4.5.3 LlmResponse: Standardizing what we receive

This section explains how LlmResponse gives the agent a consistent way to receive LLM output, failures, and token-usage information.

Key terms: LlmResponse, content, ContentItem, Message, ToolCalls, error_message, usage_metadata, input and output tokens

4.5.4 LlmClient: The provider adapter

This section explains how LlmClient translates between the agent’s request and response formats and LLM APIs, including tool calls and results.

Key terms: LlmClient, LlmRequest, LlmResponse, LiteLLM, generate, acompletion, _build_messages, ContentItems, Message, ToolCall

4.5.5 Putting it together

This section shows how the three LLM communication-layer components work together and what each is responsible for.

Key terms: LlmRequest, LlmClient, generate(), LlmResponse, ContentItem, content list

4.6 Implementing the agent

Introduces how the Agent class connects state, tools, and LLM communication in a repeated think–act cycle.

Key terms: Agent, ExecutionContext, BaseTool, LlmClient, think–act cycle

4.6.1 Agent class structure

This subsection defines the Agent class’s constructor inputs and its initial tool-setup method.

Key terms: Agent, LlmClient, BaseTool, instructions, max_steps, _setup_tools(), tools list

4.6.2 The run() method

This section explains how run() starts and controls agent execution, detects a final answer, and returns both the answer and its execution trace.

Key terms: run(), ExecutionContext, Event, step(), maximum step limit, _is_final_response(), _extract_final_result(), tool calls, tool results, assistant's message

4.6.3 The step() method

This section explains how step() runs one think–act cycle and how it turns stored execution history into an LLM request.

Key terms: step(), think(), act(), Event, step counter, _prepare_llm_request(), ExecutionContext, LlmRequest, content items, tool choice

4.6.4 The think() and act() methods

This section explains how an agent step obtains an LLM decision, executes requested tools, and turns tool failures into feedback for the next step.

Key terms: think(), LlmRequest, LlmClient, _prepare_llm_request(), act(), ToolCall, ExecutionContext, try-except, error results, conversation history

4.7 Adding structured output

This section contrasts structured output from standalone LLM calls with the agent’s free-form final answers and explains why some applications need structured agent results.

Key terms: structured output, GaiaOutput, response_format, _extract_final_result(), free-form text, structured data, downstream systems, fragile parsing logic

4.7.1 The approach: Tools as output formatters

This section explains how an agent can produce structured final answers by using its existing tool-calling mechanism as an output formatter.

Key terms: tool-calling infrastructure, structured outputs, output schema, type safety, format compliance

4.7.2 Modifying the agent

This section modifies the agent to produce schema-validated structured output through a dynamically created final-answer tool.

Key terms: output_type, Pydantic model, final_answer, @tool, output_tool_name, _prepare_llm_request(), tool_choice, required, output tool, _is_final_response()

4.7.3 Using structured output in practice

This subsection shows how an agent returns a typed sentiment-analysis result and why the same structured-output pattern works for other applications.

Key terms: final_answer tool, SentimentAnalysis, Pydantic model, result.output, output schemas

4.8 Testing with the GAIA benchmark

This section recalls why direct LLM testing on GAIA produced low accuracy before introducing a test of the tool-equipped agent.

Key terms: GAIA, LLM, low accuracy

4.8.1 From LLM to agent

This section adapts the earlier GAIA evaluation from direct LLM calls to a tool-equipped agent while keeping most of the evaluation pipeline intact.

Key terms: GAIA, GaiaOutput, Tavily MCP server, solve_problem, agent.run(), AgentResult, semaphore, Agent executions, internal LLM calls

4.8.2 Results

This section uses execution traces and a controlled GAIA comparison to show the value of web search tools and the limits of an agent that cannot process attached files.

Key terms: AgentResult, ExecutionContext, display_trace(), execution traces, GAIA level-1, web search tools, GPT-5, 50 percentage-point improvement, is_solvable=False, attached files

4.9 Summary

This section summarizes how the ReAct loop, shared execution state, tool and LLM interfaces, and structured output fit into the chapter’s agent implementation.

Where this is used later

Concepts explained in this chapter

← Chapter 3: Enabling actions: Tool use Chapter 5: Building knowledge bases with RAG →

These guides are generated from the text of Manning books by Manning's knowledge graph and link to the sections they draw on. The full books are available on liveBook and at manning.com.