# How to Build a Coding Agent with Seven Core Tools

> Build a coding agent that reads writes and executes code with seven core Python tools. Learn how to orchestrate LLM code execution autonomously.

- Repository: [Bojie Li/ai-agent-book](https://github.com/bojieli/ai-agent-book)
- Tags: how-to-guide
- Published: 2026-08-05

---

**A Coding Agent autonomously reads, writes, and executes code using seven pure-Python tools—Read, Write, Edit, Grep, Glob, LS, and Bash—registered in a central registry and orchestrated through a planning loop that isolates the LLM from direct side effects.**

The Coding Agent architecture from the `bojieli/ai-agent-book` repository demonstrates how to build a general-purpose autonomous agent that manipulates codebases safely. By isolating the inference engine from file system side effects through a curated toolbox, the design ensures robust, testable, and extensible automation. This guide explains how to implement the seven core tools that power this agent using the source code provided in Chapter 5.

## Architectural Overview

The agent follows a deterministic loop that separates planning from execution. Three primary components manage this workflow: the inference engine (LLM), the **Tool Registry**, and the **System State** manager.

### The Core Loop

The agent receives a user request, formats a system prompt listing available tools, and iterates through three steps: planning the next action, executing the selected tool, and observing the result. This cycle continues until the objective is satisfied or a stop condition triggers. The system prompt construction and loop orchestration are implemented in [`chapter5/coding-agent/main.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter5/coding-agent/main.py).

### Tool Registry and System State

All available tools are registered in [`chapter5/coding-agent/tool_registry.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter5/coding-agent/tool_registry.py), which maps tool names like `"read"` or `"edit"` to concrete class implementations. The `SystemState` object, instantiated in the main execution flow and passed to each tool, tracks the current working directory, open shell sessions, and tool usage history to ensure reproducibility across iterations.

## The Seven Core Tools

The agent's capabilities derive from seven pure-Python utilities defined in `chapter5/coding-agent/tools/`. These tools operate without external binary dependencies, enabling safe sandboxing in restricted environments.

### ReadTool

Located in [`chapter5/coding-agent/tools/read_tool.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter5/coding-agent/tools/read_tool.py), the **ReadTool** handles file reading for plain text, images, PDFs, and Jupyter notebooks. It enforces a critical safety constraint: the agent must read a file before editing it, preventing blind modifications.

### WriteTool

The **WriteTool** in [`chapter5/coding-agent/tools/write_tool.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter5/coding-agent/tools/write_tool.py) creates new files or overwrites existing ones. It includes automatic lint checking to validate code quality immediately upon writing.

### EditTool

Implemented in [`chapter5/coding-agent/tools/edit_tool.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter5/coding-agent/tools/edit_tool.py), the **EditTool** performs search-and-replace edits. It strictly requires a prior `ReadTool` call on the target file, ensuring the agent operates with current context before modifying content.

### GrepTool

The **GrepTool** in [`chapter5/coding-agent/tools/grep_tool.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter5/coding-agent/tools/grep_tool.py) provides pure-Python regular expression search across entire codebases without relying on external `rg` or `grep` binaries. This ensures portability and sandbox compatibility.

### GlobTool

Located in [`chapter5/coding-agent/tools/glob_tool.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter5/coding-agent/tools/glob_tool.py), the **GlobTool** performs fast, recursive file-pattern matching. It scales efficiently to handle codebases of any size without external dependencies.

### LSTool

The **LSTool** in [`chapter5/coding-agent/tools/ls_tool.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter5/coding-agent/tools/ls_tool.py) lists directory contents, enabling the agent to discover available files and folder structures before attempting file operations.

### BashTool

The **BashTool** in [`chapter5/coding-agent/tools/bash_tool.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter5/coding-agent/tools/bash_tool.py) executes arbitrary shell commands in persistent sessions. It allows the agent to run scripts, install dependencies, or query the operating system while maintaining session state across calls.

## Implementing the Tool Interface

Each tool inherits from the `BaseTool` class defined in [`chapter5/coding-agent/tools/base.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter5/coding-agent/tools/base.py). This abstract base handles argument validation, call counting, and JSON result formatting. The registry pattern in [`chapter5/coding-agent/tool_registry.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter5/coding-agent/tool_registry.py) instantiates tools on demand, injecting the current `SystemState` to maintain context.

The tool execution flow follows this sequence:
1. The LLM generates a JSON-encoded tool request containing the tool name and arguments.
2. The registry retrieves the tool class and calls `execute()` with the provided arguments.
3. The tool performs the operation and returns a structured dictionary with `status`, `output`, and optional metadata.
4. The agent observes the result and feeds it back into the next planning iteration.

## Programmatic Usage Example

To drive the agent programmatically, initialize the system state and registry, then execute tools by name. The following example demonstrates reading a file, editing it, and running a shell command:

```python
from chapter5.coding_agent.system_state import SystemState
from chapter5.coding_agent.tool_registry import ToolRegistry

# Initialize state and registry

state = SystemState()
registry = ToolRegistry()

# 1. Read a file (required before editing)

read_tool = registry.get_tool("read", state)
result = read_tool.execute({"path": "chapter5/coding-agent/main.py"})
print(result["content"][:200])

# 2. Edit the file using search and replace

edit_tool = registry.get_tool("edit", state)
edit_result = edit_tool.execute({
    "path": "chapter5/coding-agent/main.py",
    "search": "def main(",
    "replace": "def main(args):"
})
print(edit_result["status"])

# 3. Execute a shell command in persistent session

bash_tool = registry.get_tool("bash", state)
bash_result = bash_tool.execute({"command": "pip install -r requirements.txt"})
print(bash_result["stdout"])

```

## Safety Mechanisms and Validation

The architecture enforces safety through precondition checks implemented in individual tools. For example, `EditTool` validates that the target file exists in the read history stored in `SystemState` before applying changes. Each tool returns structured JSON containing status codes, output content, and metadata, allowing the LLM to interpret failures and adjust its plan without entering undefined states.

The pure-Python implementation of tools like `GrepTool` and `GlobTool` eliminates external binary dependencies, reducing attack surface and ensuring the agent operates correctly in sandboxed containers where system utilities may be unavailable.

## Summary

- The Coding Agent architecture isolates the LLM from side effects through seven pure-Python tools registered in [`chapter5/coding-agent/tool_registry.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter5/coding-agent/tool_registry.py).
- **ReadTool**, **WriteTool**, **EditTool**, **GrepTool**, **GlobTool**, **LSTool**, and **BashTool** provide comprehensive filesystem and shell interaction capabilities.
- The `BaseTool` class in [`chapter5/coding-agent/tools/base.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter5/coding-agent/tools/base.py) standardizes argument validation and result formatting across all implementations.
- Safety constraints, such as requiring prior reads before edits, prevent blind modifications and ensure reproducible execution.
- The agent operates through a planning loop that selects tools by name, executes them via the registry, and feeds structured observations back to the LLM.

## Frequently Asked Questions

### What programming language are the seven core tools written in?

The seven core tools are implemented in pure Python without external binary dependencies. This design choice, evident in files like [`chapter5/coding-agent/tools/grep_tool.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter5/coding-agent/tools/grep_tool.py), enables safe sandboxing and ensures the agent runs in restricted environments without requiring system utilities like `grep` or `ripgrep`.

### Why does the EditTool require a prior ReadTool call?

The **EditTool** enforces a read-before-edit policy to prevent the LLM from modifying files blindly. By checking the read history in the `SystemState` object, the tool ensures the agent has current context about the file's contents before attempting search-and-replace operations, reducing the risk of corrupted code or incorrect substitutions.

### How does the Tool Registry manage tool execution?

The **ToolRegistry** in [`chapter5/coding-agent/tool_registry.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter5/coding-agent/tool_registry.py) acts as a central dispatcher that maps string names (e.g., `"bash"`, `"grep"`) to tool classes. When the LLM requests a tool, the registry instantiates the appropriate class, injects the current `SystemState`, and routes the JSON arguments to the `execute` method defined in the `BaseTool` abstract class.

### Can the BashTool maintain state between commands?

Yes, the **BashTool** implemented in [`chapter5/coding-agent/tools/bash_tool.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter5/coding-agent/tools/bash_tool.py) executes commands in persistent shell sessions. This allows the agent to change directories, set environment variables, or install packages in one call and reference those changes in subsequent commands, maintaining context across the agent's execution loop.