Talking is not doing
A raw model predicts text. Impressive, but inert: it cannot read a file, query a database, or call an API. An "agent" is just a model wrapped in a loop that lets it choose actions, run them, observe the result, and decide again. The loop is simple. The actions — the tools — are where the leverage lives.
A tool is an API designed for a reader, not a parser
The mistake teams make is exposing their existing internal API verbatim. Models do not read like your backend. A good tool has a name that states intent, parameters a model can fill from context, and a description that explains when to use it — not just what it does.
const searchOrders = {
name: "search_orders",
description: "Find a customer's orders by email. Use when the user asks about order status or history.",
parameters: { email: "string", limit: "number (default 10)" },
};
Errors are part of the interface
When a tool fails, the model reads the error and tries to recover. So the error message is not for your logs — it is an instruction. "Invalid input" teaches the model nothing. "email must be a valid address; received 'bob'" tells it exactly how to fix the next call.
Fewer, sharper tools
Give a model forty overlapping tools and it will hesitate, pick the wrong one, or loop. Give it six well-named ones with clear boundaries and it moves confidently. Tool design is a curation problem, not a coverage problem.
The real work
When an agent underperforms, the reflex is to blame the model or rewrite the system prompt. Usually the fix is upstream: clearer tool names, better parameter descriptions, error messages that teach, and a smaller, sharper toolset. Build the tools well and the agent gets smart almost for free.