Hale
AgentsAugust 11, 202612 min read

Tool Use Is the Real Intelligence

The model is not the product. The tools are. Most “agent intelligence” is a well-named function with a strict schema and a boring implementation.

By Julian Hale · Portland, Oregon

Hand tools and a brass caliper arranged on a worn oak workbench.

Watch a competent agent for five minutes and you will be tempted to praise the model. Watch the trace for an hour and you will start praising the tools. The impressive part is rarely a clever plan. It is that `search_code`, `run_tests`, and `open_pr` exist, that they fail loudly, and that their outputs are small enough to read.

I used to think tool use was a feature you bolted on after the model got “smart enough.” That was backwards. The tools are how intelligence shows up in the world. A model that cannot touch anything is a monologue. A model that can touch three sharp tools is a worker.

Narrow tools beat poetic ones

The worst tool I ever shipped was called `do_work`. It took a string. It returned a string. Internally it decided whether to search, edit, or deploy. The model loved it. The model also could not recover from it. When `do_work` failed, the trace said “something went wrong,” which is the agent equivalent of a shrug.

The replacement was insultingly specific. `grep_repo`. `apply_patch`. `run_command` with an allowlist. `get_file` with a byte cap. Overnight the agent looked smarter, because failure became local. It could see that the patch did not apply. It could see that the test name was wrong. Intelligence, from the outside, is often just a better error.

If a tool can do more than one kind of thing, the model will pick the wrong kind at the worst time.

Schemas are the interface

People still hand models free-text arguments and then act surprised when the arguments are free-text. A tool schema is not bureaucracy. It is the type system of the loop. Required fields, enums, ranges, and examples do more for reliability than another paragraph of system prompt.

type ApplyPatchArgs = {
  path: string;          // repo-relative, no ..
  diff: string;          // unified diff only
  expectedSha?: string;  // refuse if the file moved
};

That `expectedSha` field looks fussy until the agent edits a file a teammate changed. Then it looks like the only adult in the room. Build tools as if a confident intern will call them in a hurry, because that is the actual user.

Side effects need receipts

Every tool that mutates the world should return a receipt: what changed, what did not, and how to undo it. Agents are terrible at reconstructing the past from vibes. They are decent at reading a receipt and trying again. I now treat “no receipt” as a production bug, even if the happy path works.

If you only have time to improve one part of your agent this month, do not touch the prompt. Inventory the tools. Split the vague ones. Cap the outputs. Add receipts. The model will seem to have gotten smarter, and you will not have to wait for a new checkpoint to feel it.

Letters on this piece

  • Leila Brooks · Infra · August 12, 2026

    The receipt idea migrated into our deploy tool this week. The agent used to claim a rollout finished. Now it prints the replica set. Humbling and better.