Building AI agentsMiddleLesson 1977 min read

Designing good tools

The model can only use your tools as well as you describe them. Learn to name, describe and shape tools so the model picks the right one and recovers from mistakes.

Lesson in motion

In 60 seconds

Designing good tools

The model can only use your tools as well as you describe them. Learn to name, describe and shape tools so the model picks the right one and recovers from mistakes.

1/4
In simple words
Imagine a toolbox where every tool is wrapped in brown paper and labelled "thing". You would pick the wrong one all the time. Clear labels like "small screwdriver, for glasses" make the job easy. A model choosing tools has the same problem: it only sees the labels you write.
The model never sees your tool's code. It sees only the name, the description and the parameter schema. Those few lines are a user interface, and the user is the model. Good tool design is often the biggest single improvement you can make to an agent.

Five rules for good tools

RuleWeakBetter
Clear name, verb firstdata, helper2search_orders, get_order_status
Description says when to use it, and when not"Gets orders.""Look up one order by its id. Use when the user gives an order id. For searching by name or date use search_orders."
Narrow, one job per toolrun_sql(query)get_order_status(order_id)
Simple, typed parametersOne free-text input stringorder_id (string, pattern like ORD-123456), limit (integer, 1 to 20)
Results that are short and usefulThe full 300-field database rowOnly the fields the task needs, in a small JSON object

Narrow tools are safer and easier

A broad tool like run_sql or run_shell can do anything, so the model must write it perfectly, and an attacker who controls the model's input can make it do anything too. A narrow tool like get_order_status(order_id) can only do one thing. It is easier for the model to use and much easier for you to protect. This is least privilege applied to tools.

Errors the model can act on

When a tool fails, its error message goes to the model. Write errors for that reader: say what was wrong and what to try next.
Errors the model cannot use
  • Error 500
  • KeyError: 'id'
  • Invalid input
  • A 200-line stack trace
Errors the model can fix
  • No order ORD-12345. Order ids have 6 digits, like ORD-123456.
  • Missing order_id. Ask the user for it.
  • limit must be 1 to 20; you sent 500.
  • Service busy. Try again once; if it fails, tell the user.

Read tools and write tools

Split tools into two kinds. Read tools only look at data: search, get, list. Write tools change the world: send, pay, delete, book, update. Treat them differently.
  • Read tools can usually run without asking. They still need access limits (which user's data?).
  • Write tools should be few and narrow. Risky ones need a confirmation step from a person.
  • Make write tools idempotent where possible: calling them twice with the same request has the same effect as calling once. A common way is an idempotency key, a unique id for each request, so a retry does not send two refunds or two emails.
  • Never let a write tool do more than its name says. cancel_order should not also refund, email and close the account.
A well-described tool, as a JSON-schema style definitionpython
get_order_status = {
    "name": "get_order_status",
    "description": (
        "Look up the delivery status of ONE order by its id. "
        "Use when the user gives an order id like ORD-123456. "
        "Read-only: it never changes the order. "
        "To find orders by date or product, use search_orders instead."
    ),
    "parameters": {
        "type": "object",
        "properties": {
            "order_id": {
                "type": "string",
                "pattern": "^ORD-[0-9]{6}$",
                "description": "Order id, e.g. ORD-123456",
            }
        },
        "required": ["order_id"],
        "additionalProperties": False,
    },
}
Note
The exact wrapper around this (for example whether it is called parameters or input_schema) differs between providers. The ideas stay the same. Check your provider's current docs.

How many tools?

Every tool description takes space in the context and gives the model one more choice to get wrong. Start with the few tools the task really needs. If two tools are often confused, merge them, rename them, or make their descriptions say clearly when to use each.
Watch out
Tool descriptions are instructions the model follows. A description from a third-party server can be poisoned to mislead the model. See Tool poisoning and rug pulls, and review descriptions you did not write.
Try this. Look at one API you use at work. Pick one endpoint and rewrite it as a tool for a model: a name, a two-line description with "use when" and "do not use for", and typed parameters.

Watch and read more

Lab

Three tool definitions for a school library agent, with schemas, clear errors and a read/write split.

~30 min

The problem

A school library wants an agent that helps students find and reserve books. Design its tools on paper or in the starter file.

  1. Write definitions for search_books, get_book and reserve_book: name, description (with "use when" and "do not use for"), and a JSON schema for the parameters.
  2. Mark each tool as read or write. For the write tool, say how you make it idempotent.
  3. Write three error messages each tool might return, in words the model can act on.
  4. List one tool you decided not to give the agent, and why.
Starter codejson
{
  "name": "search_books",
  "description": "TODO: what it does. Use when ... Do not use for ...",
  "parameters": {
    "type": "object",
    "properties": {
      "query": { "type": "string", "description": "TODO" },
      "limit": { "type": "integer", "minimum": 1, "maximum": 10 }
    },
    "required": ["query"],
    "additionalProperties": false
  }
}

You are done when

Hard questions

Try to answer before you reveal. If you can answer these, you understood the lesson.

Q1The model keeps calling <code>search_books</code> when the student gives an exact book id. Name two fixes that do not involve changing the model.Reveal

First, improve the descriptions: say in search_books "if the user gives a book id, use get_book instead", and in get_book give an example id. Second, make the id format clear in the schema (a pattern), and possibly have search_books detect an id and return a hint like "This looks like a book id; use get_book". Then check traces again to confirm the fix.

Q2Why is "reserve_book" safer with a <code>request_id</code> parameter, even if the model never makes mistakes?Reveal

Networks fail. The tool may reserve the book but the reply may be lost, so your loop retries. Without a request id, the second call makes a second reservation. With it, the server sees the same id and returns the first result. The risk comes from retries and timeouts, not only from the model.

Please sign in to continue.

Questions people ask

Should the description be long or short?

Long enough to answer: what does it do, when should I use it, when should I not, what do the parameters mean, and what does it return? A few clear sentences usually beat both one word and a whole page.

Is it bad to give the model a general tool like run_python?

Not always, but it is powerful and risky. If you do, run it in a sandbox with no secrets, limited network and limits on time and memory. For most business tasks, a few narrow tools are safer and more reliable. See Sandboxing: the room with no windows.

What should a tool return when nothing is found?

A clear, normal result, such as {"orders": [], "note": "No orders in this date range"}. An empty string or an error can make the model think the tool broke and try again and again.

How do I know which tool descriptions confuse the model?

Look at traces of real runs. If the model often calls the wrong tool, or calls one tool with missing arguments, that description needs work. The lesson Evaluating and debugging agents shows how to collect these traces.

Lesson test

5 questions. Get 3 right (60%) to pass and complete this lesson.

Sign in to take the test and save your progress