Tool design for LLM agents

GuideLast reviewed Oct 16, 2026By Himanshu Ramchandani
Short answer

An agent is only as good as its tools. The model chooses tools by reading their names and descriptions, fills their arguments from a schema, and decides what to do next from what they return, so each of those is part of the interface you design. Give each tool one clear job, a name and description that say exactly when to use it, strict typed arguments, results that are short and structured, error messages the model can act on, and the smallest permissions possible, with a person approving anything risky.

Tools are an interface for a model

When you design an API for other developers, you think about names, parameters, documentation and errors. Tools for agents need the same care, with one difference: the user of the interface is a model that reads your descriptions literally, can't ask you questions, and will try something even when it's unsure.

The function calling page explains the mechanism. This page is about designing the tools themselves.

One tool, one job

Agents work best when each tool does one well-defined thing. A search_web tool searches and returns a few results. A calculator tool calculates. A tool called do_customer_action(action, data) that can refund, cancel, update or email depending on its arguments is hard for a model to use correctly and dangerous when it gets it wrong.

At the same time, don't split one logical action into many tiny calls that the model must chain correctly every time. Design tools around the tasks the agent actually performs: get_customer_orders(customer_id) is better than separate tools to fetch a customer, then their order IDs, then each order.

Names and descriptions

The description is the most important part of a tool. Write it for a capable colleague who has never seen your system.

  • Say what the tool does and what it returns.
  • Say when to use it, and when not to.
  • Describe each argument: its meaning, format and valid values, with an example.
  • Mention important limits, like "returns at most 20 results" or "only orders from the last 12 months".

A weak description:

search: searches stuff

A strong one:

search_help_center(query: str, product: str | None)
Search the official help centre articles. Use this for questions about how products work,
setup, troubleshooting and policies. Do not use it for questions about a specific order,
use get_order for that. Returns up to 5 articles with title, url and a short excerpt.
product: optional, one of "X200", "X300", "Buds".

Strict arguments

Define arguments with types, formats and allowed values, and validate them in your code before the tool runs, because the model wrote them and they are untrusted input.

from typing import Literal

from pydantic import BaseModel, Field


class SearchHelpCenter(BaseModel):
    query: str = Field(min_length=3, max_length=200)
    product: Literal["X200", "X300", "Buds"] | None = None
    limit: int = Field(default=5, ge=1, le=10)

Use enums for fixed choices, patterns for IDs, ranges for numbers, and sensible defaults so the model needs to fill in as little as possible. See Pydantic and structured data.

Results the model can use

Whatever a tool returns goes into the context window, and the model has to read it.

  • Return only the fields the agent needs, not the whole database row or web page.
  • Limit the number of results, and say when there are more ("showing 5 of 128").
  • Use consistent, structured formats, like JSON with clear field names.
  • Use human-readable values where the model has to reason about them, like names instead of internal IDs, or both.
  • Include IDs the agent will need for the next tool call.

Errors the model can act on

Tools fail: timeouts, missing records, invalid arguments, permission denied. Return errors as messages that tell the model what went wrong and what to do, instead of crashing the loop or returning a raw stack trace.

{"error": "order_not_found", "message": "No order ORD-123457 for this customer. Check the ID or call list_orders to see recent orders."}

The model can then correct the argument, try another tool, or tell the user. Decide in your design what the agent should do when a tool keeps failing: retry, try an alternative, or stop and explain.

Read tools and write tools

Separate tools that only read information from tools that change things.

Read tools, like search, lookups and calculations, are low risk. Write tools, like refunds, cancellations, emails, payments, deleting data or running code, can cause real damage if the model calls them wrongly or is manipulated into calling them.

For write tools:

  • Check permissions inside the tool, using the real user's identity, not something the model says.
  • Enforce business rules in code, like a maximum refund amount.
  • Require confirmation from a person for actions that are expensive, irreversible or sensitive. See human in the loop.
  • Make them idempotent where possible, so a retried call doesn't refund twice.
  • Log every call with its arguments, result and the user it was for.

Code execution

Tools that run code, like a Python interpreter for calculations or a shell for a coding agent, are among the most powerful and the most dangerous. Run that code in a sandbox: an isolated container with no access to your secrets, limited CPU and memory, restricted or no network, and a time limit. Never execute model-written code directly in your application process with something like eval. See Docker for AI apps.

How many tools

Every tool definition is sent to the model on every call, costing tokens and giving the model more chances to choose wrong. A focused agent with 3 to 10 well-designed tools is usually more reliable than one with 50. If you need many tools, group them, give different agents different tool sets, or select relevant tools per request.

Test your tools with the model

Tools that look clear to you can be confusing to a model. Run your agent on realistic tasks, read the traces, and look for wrong tool choices, wrong arguments and repeated failures. Each one usually points to a description, an argument or an error message to improve.

From the floor

In the bootcamp, the calculator tool had a docstring describing what it does, which operations it handles and examples like calculator("2 + 2"), because the model reads that description to decide when and how to use it. In the next session, we moved from that simple tool to structured tools with defined arguments for a research agent that searches the web with DuckDuckGo and pulls four or five results, one specific job for one agent.

The first calculator used Python's eval, which is fine for a demo on your own machine and unsafe anywhere else, because it will run whatever code the model sends. The safe version is on the function calling page.

Sources