← Journal
Agentic AI··4 min read·By North Foundry

Tool calling is an API design problem

When an agent behaves badly, the first instinct is to blame the model and rewrite the prompt. In our experience the prompt is usually fine and the tools are the problem.

An agent reads your tool definitions the way a new engineer reads an unfamiliar SDK, except it has no colleague to ask and it will not admit confusion. Every ambiguity in your schema becomes a guess.

Names are instructions

A tool called update will get called for things that are not updates. A tool called set_deployment_replica_count will not.

The name is the highest-signal part of the definition because it is what the model matches against intent. Verbose, specific, boring names outperform clean ones. This is the opposite of how you would name an internal function, and that is fine, because the audience is different.

The same applies to arguments. target: string invites the model to put a hostname, an ID, a friendly name, or a URL in that field depending on the phase of the moon. service_id: string (UUID, from list_services) gets you a UUID.

Return structure, not prose

A tool that returns "Successfully updated 3 records" forces the model to parse English to determine what happened. It will parse it wrong eventually.

Return structured results with an explicit success flag, the affected entities, and, where relevant, the new state. Then the agent can verify its own work instead of trusting its own summary. The difference between an agent that says it completed a task and one that confirmed it completed a task is entirely in this return shape.

Errors should say what to do next

The worst possible tool error is 500 Internal Server Error. The agent has no idea whether to retry, change arguments, or stop, so it will pick one at random and often pick retry.

Good tool errors tell the agent three things: what went wrong, whether retrying could plausibly help, and what a valid alternative would look like. An error that reads "service_id not found; call list_services to get valid IDs" gets recovered from on the next turn. An opaque failure gets retried nine times.

Fewer tools, better tools

There is a strong pull toward exposing everything, because exposure is cheap and you cannot predict what the agent will need. Resist it. Past roughly twenty tools, selection accuracy drops noticeably, and the tools that get mis-selected are usually the ones with overlapping responsibilities.

If two tools could reasonably answer the same request, merge them or make the boundary explicit in both descriptions. If a tool exists because it might be useful someday, remove it until someday arrives.

The test that actually works

Hand your tool definitions, and nothing else, to an engineer who has never seen the system. Ask them to describe what each tool does and when they would use it. Anywhere they hesitate is where the agent will guess.

That test takes ten minutes and it has caught more real problems for us than any amount of prompt iteration.

Building something this applies to?

Book a discovery call→