Command Palette

Search for a command to run...

Hectal
PHASE 7Intermediate ~22 min· topic 3 of 9

Topic 7.3

Describing Tools Well

In one line

The model chooses and fills in tools using only their names, descriptions and JSON Schema parameters. Clear names, descriptions that say when to use the tool, and tight schemas (types, enums, required fields) are the main way to make tool use reliable.

Think of it like this

The labels on a drawer of kitchen tools. A drawer labelled 'stuff' makes everyone guess. Labels reading 'tin opener: for cans only' and 'bottle opener: for caps' make nobody guess wrong. The model cannot see your code. It sees the labels you wrote, and nothing else.

Words you'll meet

New words in this topic, in plain English. Come back here whenever one feels fuzzy.

JSON Schema
A standard way to describe the shape of JSON: types, required fields, allowed values and ranges.
Description
The plain-English text that tells the model what a tool does and when to use it.
required
The list of argument names the model must always supply.
enum
A fixed list of allowed values for an argument, such as celsius or fahrenheit.
Strict mode
A provider option that forces a tool's arguments to match its schema exactly. Support varies by provider.
Tool list
The tools array in the request. It is sent, and billed as input, on every call.

Step by step

01Step 1: the model sees only text

The model gets the tool's name, description and schema as part of its input. Nothing else about your function reaches it. Write them as if for a new colleague who cannot read your code.

02Step 2: build the definition

The helper tool(name, description, properties, required) returns the exact shape the API expects. The first example prints it compactly so you can see every field and its size.

tool.jsonwhole filejson
{
  "type": "function",
  "function": {
    "name": "get_weather",
    "description": "Get the current weather for a city. Use it for questions about temperature or sky today.",
    "parameters": {
      "type": "object",
      "properties": {
        "city": { "type": "string", "description": "City name, for example Pune" },
        "unit": { "type": "string", "enum": ["celsius", "fahrenheit"] }
      },
      "required": ["city"]
    }
  }
}

03Step 3: vague versus clear

The second example scores each tool by words shared with the request. With descriptions like 'Converts things.' nothing matches. With descriptions that name what the tool does, the right tool wins. A real model is cleverer, but it also needs something to go on.

04Step 4: narrow the arguments

Use enum where the choices are fixed, required for what you cannot default, and describe formats ('ISO date, for example 2026-10-10'). Each constraint removes a way to be wrong.

05Step 5: test with a real model

In the lab, run the request, then replace the description with 'Does stuff.' and run again. Then try a different wording. Note which wordings still work: those are the ones you can trust a little more.

Step 5: test with a real modeldiagram
Rendering diagram…

Try it yourself

  1. 1

    Estimate the cost of ten tools

    In the first example, copy the get_weather definition nine times (different names) and print the total characters. Divide by 4. How many tokens does a 10-tool list add to every request, and what does that cost at 10,000 requests a day with an example price of 0.10 dollars per million input tokens?

  2. 2

    Add a third tool to the toy chooser

    Add get_weather with the description 'Get the weather for a city today.' to the CLEAR list and add the request 'Weather in Pune today' to the loop. Predict the scores before you run.

  3. 3

    Make the lab fail

    In the lab, give both tools the same description and send. What does the model do? When two tools look the same to you, they look the same to the model.

Code & diagrams

A tool definition and what it costs New tab

The characters-per-token rule is a rough estimate (Topic 1.2). Your provider's usage field gives the real count.

Sign in to run this example in your browser.

Expected output

{"type":"function","function":{"name":"get_weather","description":"Get the current weather for a city. Use it for questions about temperature or sky today.","parameters":{"type":"object","properties":{"city":{"type":"string","description":"City name, for example Pune"},"unit":{"type":"string","enum":["celsius","fahrenheit"],"description":"Temperature unit. Default celsius."}},"required":["city"]}}}
required: city
characters: 401
about 100 tokens, sent with every request
Why descriptions decide the choice New tab

A toy chooser that counts shared words. Real models compare meaning, but they depend on the description in the same way.

Sign in to run this example in your browser.

Expected output

vague descriptions:
  'What is 250 euros in rupees today?' -> no clear choice (score 0)
  'Find news about the Pune metro' -> no clear choice (score 0)
clear descriptions:
  'What is 250 euros in rupees today?' -> convert_currency (score 2)
  'Find news about the Pune metro' -> search_web (score 2)
Edit a description, watch the choicereal model

Try: Send as it is: the model should call convert_currency. Then edit the tool list (use the request editor) so convert_currency has the description 'Does stuff.' and send again. Does it still pick the right tool? Try renaming it to 'tool1'. What do you learn about how much the model relies on names and descriptions?

user

Goals

  • The model calls convert_currency

Sign in to send this request to a real model (free).

Break it on purpose

Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.

Break #1

Empty descriptions

In the second example, change every description in the CLEAR list to an empty string "" and run the Python version.

terminal
$ Run
── what you'll see ──
vague descriptions:
'What is 250 euros in rupees today?' -> no clear choice (score 0)
'Find news about the Pune metro' -> no clear choice (score 0)
clear descriptions:
'What is 250 euros in rupees today?' -> no clear choice (score 0)
'Find news about the Pune metro' -> no clear choice (score 0)

Myth vs fact

Myth

The model reads my function's code or docstring.

Fact

It sees only what you put in the request: the name, description and schema. A docstring helps only if you copy it into the description.

Myth

A longer description is always better.

Fact

Length costs tokens on every request. Say what it does, when to use it and the limits, then stop.

Myth

If the schema says integer, the model will always send an integer.

Fact

Models usually follow schemas but can send a string or an out-of-range value. Always validate (Topic 7.4).

Pro corner

Extra depth for experienced readers. New to this? Skip it for now and come back later.

  • ▸

    Put the most important sentence first and avoid ambiguity between tools: if two tools overlap, say which to prefer. Many 'wrong tool' bugs are two tools whose descriptions both claim the same job.

  • ▸

    Keep tool lists stable between requests. Providers that cache a repeated prompt prefix (Topic 6.6) can reuse the tool list only if it is identical, so reordering or regenerating it per request costs money.

  • ▸

    Model the user's task, not your API: one create_ticket tool with clear arguments beats five thin wrappers around endpoints. Fewer, richer tools mean fewer chances to pick wrongly.

Remember this

  1. 1

    Why this exists. When the model decides whether to call a tool and with what arguments, it reads three things you supplied in the request: the tool's name, its description and its parameters (a JSON Schema). It has never seen your function body. So the quality of tool use is mostly the quality of this text. Most 'the model keeps choosing the wrong tool' bugs are description bugs.

  2. 2

    Names. Use a verb and a noun, get_weather, search_orders, create_ticket. Be specific: search and lookup collide with each other. Stick to letters, digits, underscores and hyphens, up to 64 characters: OpenAI-style APIs restrict function names to that pattern (^[a-zA-Z0-9_-]{1,64}$), so a dot or space can make the request fail. Name by what the tool does for the user, not by your internal class name.

  3. 3

    Descriptions say when to use the tool, and when not to. One or two sentences: what it does, what it returns, when to prefer it, and any limit ('only covers the last 30 days'). Mention neighbours: 'Use search_orders to find an order id first; this tool needs the id.' Include units and formats. The first example prints a real tool definition and counts its size.

  4. 4

    Parameters are a JSON Schema. An object with properties (each with a type and a short description), a required list, and extras that narrow the choices: enum for a fixed set of values, minimum and maximum for ranges, maxLength for text. The tighter the schema, the fewer wrong arguments the model will produce, and the easier your validation (Topic 7.4). Phase 4 covers JSON Schema in depth. Some providers also offer a strict mode that forces arguments to match the schema. OpenAI's, for example, asks for "strict": true on the function, additionalProperties: false on every object and every property listed in required. Support and rules differ by provider, so read yours.

  5. 5

    Every tool costs tokens, every request. The tool list is sent as input on each call, so long descriptions and many tools add cost and latency, and dilute the model's attention. Keep the list to the tools the task needs (pick them per request if you have many), and keep each description tight. The first example estimates the size with the 4-characters-per-token rule of thumb from Topic 1.2.

  6. 6

    You can only measure by trying. Treat tool descriptions like prompts (Topic 3.8): write a small set of requests with the tool you expect, run them against a real model, and re-run after every change. The second example is a toy that picks a tool by word overlap with the description. Real models match meaning, not words, but the lesson transfers: vague descriptions give them nothing to match. The lab lets you edit a real description and see whether the choice changes.

Explain it without notes

01

What does the model actually see of a tool, and what follows for how you write them?

02

How do enum, required and description on a parameter each reduce errors?

03

What is the cost of a long tool list and how do you keep it under control?

Practice

01

Write make_tool(name, description, properties, required) that returns the tool definition dict in the API shape, and print its function name.

02

Write tokens_estimate(tools) that returns the estimated tokens of a list of tool dicts as the length of their compact JSON divided by 4 (integer division).

Trade-offs

  • ↔

    Detailed descriptions improve choices and cost input tokens on every request.

  • ↔

    Tight schemas (enums, ranges) prevent bad arguments and make the tool less flexible when the real world has more cases.

  • ↔

    Many small tools are easy to describe and hard to choose between; a few richer tools are the reverse.

Done when you can

  • Done when you can write a tool definition (name, description, parameters) from memory.

  • Done when each of your descriptions says when to use the tool and what it returns.

  • Done when parameters use enum, required and descriptions with formats where they apply.

  • Done when you can estimate the token cost of a tool list.

  • Done when you have tested a description change against a real model.