Σ 0:00▸ 0:00

Module 3 · Agent Tools, Knowledge, Memory & Research Design · scripted

Tool Design Case Studies

35 minoutcomes: tool-design

Overview

A language is judged by the conversations it produces. So we test tool languages the only honest way: one goal, two rival vocabularies, and the two trajectories they generate — watched side by side. Four cases in this lesson, each ending in a reusable law: design out accidental complexity; prefer reversible actions; be as coarse-grained as the task allows; give the agent a pressure-relief valve. Underneath all four is one sentence: the tools condition the conversation before the LLM ever speaks.

Four cases, one method

Everything so far — names as pointers, descriptions as paid definitions, the tool set as a language — becomes concrete the same way: take one goal, design two tool sets for it, and watch what happens to the trajectory. Four cases. Each ends in a principle you can reuse.

Case 1 · Editing a book

The goal: revise a 300-page manuscript. Two languages for it:

Two tool sets for one manuscript

Design A · positional Design B · structural
read_page(n) read_toc()
edit_page(n, line, text) read_section(id)
insert_on_page(n, line, text) edit_section(id, old, new)
delete_from_page(n, line) append_to_section(id, text)
Example 1a · The page numbers move
user

Delete the duplicated paragraph in chapter 2, then fix the typo "Mlde" in the chapter about the fjord crossing — I saw it around page 87.

assistant
read_page(n = 41)
user
[page 41 text: …the duplicated paragraph appears here…]
assistant
delete_from_page(n = 41, line = 12)
user
OK. Document is now 299 pages.
✎ noteQuietly, the world just shifted. Everything after page 41 moved up — but the conversation still says the typo is "around page 87."
assistant
edit_page(n = 87, line = 4, text = "Molde")
user
No match for "Mlde" on page 87.
assistant

The text may have shifted when we deleted the paragraph — page 87 is no longer the page the user saw. I'll re-search pages 84–90 to relocate the typo before editing… and I should re-verify every page number mentioned earlier in this conversation the same way.

✎ noteNothing malfunctioned. But the agent now maintains a mental map of page numbers in the conversation, and every edit invalidates it. The bookkeeping — re-reading, re-locating, re-verifying — is spent tokens and new chances to be wrong.
Example 1b · The sections hold still
user

Same tasks.

assistant
read_toc()
user
ch1: Arrival · ch2: The Harbor · ch3: The Fjord Crossing · …
assistant
edit_section(id = "ch2", old = "[duplicated paragraph]", new = "")
user
OK.
assistant
edit_section(id = "ch3", old = "Mlde", new = "Molde")
user
OK. 1 replacement in ch3.
✎ noteTwo moves. Pages renumbered themselves somewhere behind the tool — the agent never knew and never needed to. "ch3" meant the same thing before and after every edit.

The structural design absorbed an invariant — sections keep their identity across edits; pages don't — behind the interface. But be honest about the price: Design B assumes a table of contents and section structure. Hand it a flat manuscript with no headings and it cannot work at all. It is a better language and a smaller one.

Principle 1

Watch for ACCIDENTAL COMPLEXITY: a tool design can quietly create
a new challenge the task itself never had.

Design A's tools look good — but they burden the agent with
tracking page and line numbers, and redoing the numbering math
every time an edit moves the text. Design B removes that burden by
design: sections are named by identity, and numbers never enter
the reasoning at all.

Design tools to take cognitive burden OFF the agent — and be
careful they don't add it.

Case 2 · Reversible actions

Agents make mistakes. Context gets left out of the conversation, and the reasoning built on what's missing comes out wrong. We want the agent to be able to undo its mistakes — to correct itself when a problem surfaces. For that to be possible, the tools' actions have to be reversible:

One action, two designs

Design A Design B
remove_file(path) archive_file(path)
deletes the file, permanently moves the file to a store, recoverable for 30 days
Example 2a · remove_file
user

Tidy up my project folder — it's a mess.

assistant
remove_file(path = "notes_old.md")
user
Removed.
assistant
remove_file(path = "draft_v1.md")
user
Removed.
assistant
remove_file(path = "data_backup_2024.csv")
user
Removed.
assistant

Cleaned up. I removed the old notes, an early draft, and a stale backup — they're gone, so the folder only contains current files now.

✎ noteThe agent reasoned from the names it saw: "old", "draft", "backup." What the conversation never contained: data_backup_2024.csv is the only copy of last year's measurements. The reasoning was understandable — and remove_file made the mistake permanent.
Example 2b · archive_file
user

Tidy up my project folder — it's a mess.

assistant
archive_file(path = "notes_old.md")
user
Archived — recoverable for 30 days.
assistant

I've archived the old notes. Before I continue: draft_v1.md might still be referenced in your revision history, and the 2024 backup may be worth keeping — shall I archive those too? Everything I archive stays recoverable.

✎ noteThe same mistake is now correctable. If the 2024 backup turns out to matter, it comes back with one call. A wrong action against a reversible tool costs a correction; against an irreversible one it costs the data.

Principle 2

Prefer tools whose actions are REVERSIBLE.
Agents make mistakes — missing context produces wrong reasoning —
and reversible actions let the agent undo its mistakes and correct
itself when problems surface. Archive, not delete.

Case 3 · One call, or five?

The goal: monthly operations reports. Two languages:

The mega-tool vs. the parts

Design A · one call Design B · the parts
make_monthly_report(month) query(dataset, filter)
summarize(rows, focus)
format_report(sections)
Example 3a · The anticipated task
user

August report, please.

assistant
make_monthly_report(month = "2026-08")
user
Report generated: august-2026.pdf
✎ noteOne step. Minimal tokens, nothing to get wrong, trivially auditable. For the task it was built for, the mega-tool is unbeatable — the whole sequence runs inside one call, and runs the same way every time.
user

Great — now the same report, but only the Ålesund sites, compared against last August.

assistant

make_monthly_report takes only a month. It cannot filter by site or compare periods — there is no way to say your request in the tools I have.

✎ noteThe neighboring task is one step away for a human and inexpressible here. The single tool covers exactly one path.

Design B says both requests — the August report takes eight steps instead of one (query, summarize, format, with more tokens and more places to err), and the Ålesund comparison takes ten. Slower on the anticipated path; alive on all the neighbors.

Principle 3

If the intermediate steps need no reasoning, put them all in ONE
tool — one call, not five. An agent repeating the same five actions
in the same order is an opportunity: collapse the sequence into a
single tool. What runs inside a tool is exactly repeatable, costs
no tokens, and is cheaper than reasoning in the loop.

The price: a baked tool is the granularity the agent works at. It
cannot reach inside to reason about intermediate results. Fine-
grained tools are flexible but less efficient.

Be as coarse-grained as the task set allows — no finer than needed.

Case 4 · The pressure-relief valve

The goal: an agent for a support inbox. Some requests will arrive that the agent can't easily handle — cases the tool set was never designed for. When that happens, we do not want the agent getting creative with the tools it has. An agent instructed to complete its task will complete it with whatever it's got — especially when one of its tools is open-ended, like executing code:

Design A · the open-ended tool

"Requests could be anything."

Tools:execute_code(script) — and therefore: anything

Then someone spends a week logging what actually arrives:

Design B · after one week of logging

1,204 requests logged. 92% are six operations —

reset_password(user)

change_address(user, addr)

resend_invoice(id)

update_payment(user)

cancel_subscription(user)

refund_order(id) — max 500 kr

…and for everything else, the pressure-relief valve —

request_human_review(description)

The last tool is the design move. request_human_review stops the agent's work: it writes a description of the case, the run ends, and a human picks it up from there. It gives the agent a legitimate way to be done with a task it shouldn't attempt.

Example 4 · The odd request hits both designs
user

"Please merge my two accounts into one, and move the subscription credit from the old one over."

assistant

Design A — writes a script: edits the account tables directly to merge the two records, invents a rule for converting the old credit, and deletes the old account. All executed. Nobody reviewed any of it.

assistant

Design B — request_human_review(description = "Customer asks to merge two accounts and transfer subscription credit. Account merging is outside my operations — needs a human.")

✎ noteDesign B recognized the boundary and stopped. The description hands a human a well-formed version of the case — and the agent never improvised on data it shouldn't touch.

Principle 4

Give the agent a pressure-relief valve.
A request_human_review(description) tool sets the boundary
explicitly: anything the tool set wasn't designed for gets
described and handed to a human. Without the valve, an agent told
to complete its task will get creative with the tools it has.

The four principles, one idea

The case-study laws

1. Tool design can add accidental complexity — design it out.
2. Prefer reversible actions — the agent can undo its mistakes.
3. Be as coarse-grained as the task set allows — collapse repeated
   sequences into one tool.
4. Give the agent a pressure-relief valve for everything else.

Every case is the same sentence wearing different clothes: the tools condition the trajectory before the LLM ever speaks. Design A and Design B never differed in what was possible for the underlying system — they differed in what the language made sayable, cheap, stable, and safe.

Your turn

Take the tool set of an agent you're designing and run one of these cases on it as an A/B: write the rival design, give both the same three tasks (one anticipated, one neighbor, one weird), and record where each trajectory bent, stalled, or became unsafe. Bring the comparison table.