Tools 28 January 2026 · 7 min read
Tools that fail well
The model will pass your tool something absurd — reliably, on a long enough timeline. Whether that becomes a corrected second attempt or a support ticket is entirely down to how the tool is written.
Stop writing the loop by hand
Pilot gives you the durable loop, typed tools, and the trace — so you write the agent, not the plumbing.
Get startedThe model will pass your tool something absurd. Not maybe — reliably, on a long enough timeline. A tool that fails well turns that into a corrected second attempt; a tool that fails badly turns it into a support ticket.
Make bad arguments impossible before they are handled
The cheapest validation is a type. If a tool takes an enum, the model cannot invent a fourth option. If it takes a value object with a constructor that rejects negatives, no negative ever reaches your logic.
Push as much correctness as you can into the signature, because the signature is also the schema the model sees. Every constraint you express there is a constraint the model is told about up front, rather than one it discovers by failing.
Return errors the model can act on
Compare two failures:
Error: invalid argumentchargeId "ch_9f2" was not found. Charge IDs look like "ch_" followed by 24 characters. Use search_charges to find one by email.
The first ends the run. The second is a hint, and the model will usually take it and succeed on the next attempt. Write tool errors as if you were leaving a note for a capable colleague who cannot see your codebase.
Be idempotent, then say so
Retries are a fact of agent systems, so every tool that changes something needs an idempotency key. Take one as an argument, make repeats safe, and document that in the description — the model then knows a retry is cheap, and so do you.
Keep tools narrow
A tool called manage_customer that takes an action string is four tools wearing a trench coat. Split it. Narrow tools have clearer schemas, better error messages, and the model picks between them far more reliably than it picks between modes of one overloaded call.
Log the arguments, always
When something strange happens, the first question is always "what did it actually pass?" Record the arguments to every call as part of the trace. It costs nothing and it is the difference between a five-minute diagnosis and an afternoon.