Tool use is what separates a model that describes an action from one that takes it. The mechanism is simple enough to explain in a paragraph. The engineering around it is where production agents live or die.
Here is what actually breaks, roughly in the order you will meet it.
The Four Phases Where Tool Calls Break
Every tool call moves through four phases, and each has its own failure mode.
Definition is where you hand the model a name, a description, and a JSON schema for the parameters. Invocation is the model producing a structured call instead of text, and that call is its own message type in the response rather than something you parse out of prose. Execution is your code: mapping the name to a function, validating arguments before you trust them, applying a timeout, capturing failures as data with text the model can actually act on. Result handling is feeding the output back so the model can continue, and the shape of what you send matters, because a raw dump of a deeply nested object confuses a model the same way it confuses a new engineer.
Notice that three of the four phases are yours. The provider handles invocation. You own definition, execution, and the quality of what goes back in.
Schema Design Is The Highest Leverage Work
A well designed schema gets the call right on the first attempt in the large majority of cases. A vague one produces retries, latency, cost, and a worse experience for whoever is waiting.
The gap between careful and careless schema design is roughly the difference between a 95 percent and a 70 percent first attempt success rate, and that difference compounds hard across a multi step workflow. Five dependent calls at 95 percent each finish clean about 77 percent of the time. At 70 percent, it is 17 percent.
Four rules that move that number:
Name the tool as a verb phrase that says what it does. get_customer_profile and create_support_ticket tell the model when to reach for them. process, handle_request and utility_function force it to guess from the description alone.
Write the description for selection, not for documentation. Say what the tool returns and when to use it, and name the side effects. "Creates a support ticket and sends a confirmation email to the customer" tells the model the call is not idempotent, which changes whether it should confirm before firing.
Use the tightest types available. Enums instead of free-form strings, format hints for dates and emails, minimum and maximum on numbers with real ranges, and repeat the constraint in the parameter description where the model will read it.
Keep required parameters minimal. Every required field is a place the call can fail when the conversation simply did not contain that value. Require what you truly need and default the rest.
Routing Past Twenty Tools
Selection is trivial with three tools and a genuine engineering problem past fifteen or twenty. Every definition eats context, similar tools create ambiguity, and multi tool sequences grow combinatorially.
Under about ten clearly distinct tools, hand the model everything and let it choose. Past that, put a routing layer in front and select the five to ten tools plausibly relevant to this specific message, by keyword, by a small intent classifier, or by embedding similarity against the tool descriptions. For hundreds of tools, route hierarchically: category first, specific tool second, so no single call ever sees the whole set.
Routing also improves when the system remembers what worked. If a class of question has historically needed knowledge base search followed by ticket creation, that pairing is worth pre-selecting the next time something similar arrives.
Sequential Or Parallel, And Why Users Feel It
Sequential execution is unavoidable when calls depend on each other, and it costs you latency: three dependent calls at 500 ms each is 1.5 seconds of tool time plus model inference between every step.
Parallel execution collapses independent calls to the duration of the slowest one. Current models already generate several tool calls in a single response turn, so the capability is there. The work is on your side, dispatching concurrently and collecting the results before you hand them back.
The Takeaway
When an agent misbehaves, the instinct is to blame the model or reach for a bigger one. Most of the time the fix sits in the phases you own: a clearer schema, a router that narrows the choice, an error message written so the model can recover instead of retrying the identical call.
Those are ordinary engineering problems, which is the good news, because ordinary engineering problems stay fixed.
Full guide, including error recovery, validation and the security side: https://www.adaptiverecall.com/ai-tool-use/
Top comments (0)