A tool has two separate testable surfaces, and this lesson is only about one of them. The first is whether the tool does the right thing given valid input — a `search_orders` tool called with `{"order_id": "ord-1001"}` returns the right order, a malformed payload gets rejected with a clear reason, and a downstream outage produces a labeled, recoverable error instead of a stack trace. That is ordinary software testing, and it needs nothing from a model at all. The second surface is whether, given a user's actual request, a model such as Claude Opus 5 chooses to call this tool, with these arguments, at the right moment — a reasoning and selection question that lesson 25 covers in full.
Conflating the two makes both harder to debug and slower to fix. If a `close_account` handler silently returns the wrong shape on a locked account, that defect shows up first — if it shows up at all — as a confusing failure in a model-driven eval, where it looks like a selection problem: "the model didn't handle the locked-account case correctly." It is not a selection problem. The model called the right tool with the right arguments and received a broken answer back. No amount of prompt or description tuning fixes a broken handler, and diagnosing a handler bug through eval transcripts, one model call at a time, is a slow way to find a bug that a five-line test would catch in milliseconds.
This is why testing without a model in the loop is the higher-leverage half of the work, not a lesser one. It is deterministic — the same input produces the same output every time, with no sampling variance to explain away. It is fast and free — no API key, no network round trip, no per-run cost, which means it runs on every commit rather than "when someone remembers." And it catches the majority of what actually breaks tools in production: schema bugs, unhandled error paths, results shaped in ways the agent can't parse, and handlers that quietly do something other than what they claim. A test suite that requires a model and a live API key for every single run is a test suite that gets run less, run later under deadline pressure, and eventually not run at all — the tests that only exist when it's convenient don't really exist.