Chapter 5: The toolbox
Chapter 4 ended with the machine able to act and its character undecided. A read tool makes a researcher, a write tool makes an editor, a shell makes an operator. This chapter builds the bench those sentences promised, and the build is smaller than the word toolbox suggests. The single tool block fans out into three plain tools, and every one of them is ordinary code behind the contract from chapter 4.
One small bug carries the chapter, the way the failing test carried the last one. The login route locks an account after five failed attempts. The security policy says three. The test enforces the policy, so the test fails, and the whole fix is one character, a 5 that should be a 3. Working that bug calls for every tool on the bench, which is why it is the specimen.
Read tools
The bench starts with eyes. A list tool answers one question: what files are here. A read tool answers the other: what is inside this one. They are the cheapest tools you can hand a machine, and they change everything, because an agent that cannot look cannot decide.
Watch the first moves on the lockout bug. The agent lists the project and sees src and tests. It reads the test file to learn what the policy demands. It reads the login route and finds the five. Nothing clever has happened yet. It is doing what you do on the first day at a new job: look around, then read the page that matters.
The machine's change this chapter is sitting under those moves. One tool was never the plan. The single block from chapter 4 fans out into a bench:
Notice what read tools actually are. Chapter 3 slid knowledge into the loop by retrieving pages from your documents. Read tools retrieve pages from your codebase. The corpus changed, and the door did not: everything the agent reads comes home as content blocks in the array, priced like everything else in it.
The flaw arrives with the first long file. The login route is four hundred lines, and the agent reads all of them to find one character. Every line lands in the array and stays, billed again on every turn, exactly like the forty-page master agreement in chapter 3. The fix is the same fix: read selectively, and keep only what the model needs. An agent that reads everything is not thorough. It is flooding its own context.
The write idiom
The fix for the bug is one character, and the write tool is shaped for exactly that. The standard design, used by nearly every coding agent, is a pair of strings. Oldstring is the exact text to be replaced. Newstring is what replaces it. Some tools also take a line offset to narrow the search, but the pair is the heart of it.
The lockout fix, as a write request, is smaller than the sentence you are reading:
{
"tool": "write",
"file": "src/login_route.py",
"oldstring": "if attempts > 5: lock(account)",
"newstring": "if attempts > 3: lock(account)"
}
The file never travels. The obvious alternative, sending back the whole corrected file, loses three ways. It costs tokens proportional to the file, so a one-character fix in a four-hundred-line file is billed as four hundred lines. It is unreviewable, because a one-line diff is checked at a glance and a four-hundred-line diff hides the change you actually care about. And it can corrupt untouched code, because the model retypes the whole file, and a slip can land anywhere. The surgical edit costs tokens proportional to the change, shows the human exactly the change, and touches nothing else.
Oldstring has a second job: it is a safety check. To replace text, the model must first quote it exactly, which means it must prove what is there. Say a colleague edits the file between the agent's read and the agent's write. The quote no longer matches, the tool refuses, and the edit fails instead of landing in the wrong place. The failure is the feature.
The failure mode left over is aim. The model quotes text that appears twice, or text it half-remembers, and the tool cannot guess which occurrence to replace. The fix is built into the idiom: when oldstring matches nothing, or matches more than once, the edit fails safely, the refusal comes home as a block, and the model reads its own miss and aims again.
The shell
The third tool on the bench is labeled bash, and it is the strange one, because it is not one tool. It takes a string, runs it in a shell, and returns the output. Behind that little contract sits the unix bench: fifty years of composed tools, grep, ls, awk, sed, and the rest.
Watch it find the five. The read tools found it honestly, one file at a time: list, read, read. The shell finds it in one step:
$ grep -rn "attempts" src/
src/login_route.py:41: if attempts > 5: lock(account)
Then, after the edit, the same tool proves the fix: run the test suite, and three passed comes home as a block. One tool searched and one tool verified, and neither was custom code you had to write.
That is the economics. Without a shell, every act needs a bespoke tool you write and maintain: a search tool, a file finder, a test runner. With one, the whole unix toolbox arrives pre-assembled, and your host stays the size it was. Chapter 4's heartbeat runs through all of it. One sentence about a lockout bug hid a grep, two reads, an edit, and a test run: five round trips, each a request from the model and a result home as a block. The agent seemed to think for a while. It was running errands.
The flaw is the largest in the book: a tool that runs arbitrary commands is arbitrary code execution. The standard fix is permissioning, a human approving tool calls before they run, and that is all this book will say about it.
Try it
- Watch the bench. Give your coding agent a small bug in code it has never seen, then read the transcript instead of the answer. Count the tools it touched: a listing, some reads, a search, an edit, a test run. One instruction, a dozen errands.
- Read the edit. In the same transcript, find the edit request. It quotes the exact text being replaced and provides the replacement, two strings. The diff you review is proportional to the change, not to the file.
- Watch the transcript grow. Keep scrolling. Every file read and every command output is still in the array, and all of it travels on every turn that follows. The weight you are scrolling through is the next chapter's subject.
The problem with this
Look at the diagram again. The bench is built, and the machine can now find a bug, fix it, and prove the fix. Now look at the box beside the bench. Every tool call left a request in the memory, and every result came home to stay. The lockout session ends with three files read, one search, one edit, two test runs, and every word of every output sitting in the array, billed again on each turn that follows.
Chapter 2 noticed the flaw and filed it away: the loop only appends. The toolbox turned the trickle into a river. The next chapter teaches the machine to forget.