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.