Originally published on Loop & Retry — field notes on building LLM agents that survive production.
Most agent bugs I've chased weren't in the model. They were in the tools — specifically, in the gap between what a tool's schema implied it wanted and what it actually did with what it got. The model is a caller that reads your parameter names and descriptions, forms a plausible theory of how the tool works, and acts on that theory under uncertainty. When it misuses a tool, the usual cause is that the tool let it.
You can't make the caller deterministic. You can make the tool hard to misuse. Four properties do most of the work: a legible schema, a validating boundary, recoverable errors, and idempotency. Here's each, with the failing version and the fix.
1. A legible schema: write for a reader who can't ask questions
The schema is the entire spec the model gets. It can't read your code, your docstrings elsewhere, or the ticket that explains the edge case. If the contract isn't in the name, the type, and the description, it doesn't exist. Here's a tool that leaks its contract:







