Room 42, home

Give your agent tools it can call

What a tool is for an agent, how to describe one clearly, and why the description decides whether the agent picks the right tool.

Agentsadvanced9 min readUpdated 14 Jun 2026

In short

  1. 01A tool is one named action your agent can take, defined by a name, a plain-language description, and a small input schema.
  2. 02The model only reads that card, never your code, so a clear description is what makes it pick the right tool at the right moment.
  3. 03Name tools as a clear verb plus object, say when and when not to use each, and describe every input with a type and an example.
  4. 04Keep tools single-purpose, flag destructive ones plainly, and return plain result text the model can reason over, even on failure.
Contents · 11 sections
  1. 1What is a tool for an agent?
  2. 2The loop a tool plugs into
  3. 3Why does the tool description matter so much?
  4. 4How do I name a tool?
  5. 5How do I write a good tool description?
  6. 6How do I describe a tool's inputs?
  7. 7Keep tools small and single-purpose
  8. 8Make destructive tools obvious
  9. 9Write good result text
  10. 10A checklist before you ship a tool
  11. 11Try it from the CLI

A tool is one named action your agent can take in the world: read a file, query a database, send an email, look up an order. You describe the tool in plain language and a small input schema, and the agent reads that description to decide when to call it and what to pass.

The model does not run your code or see your function body. It sees a short card: a name, a sentence about what the tool does, and the shape of the inputs. That card is the entire interface between the agent and your action. If the card is clear, the agent uses the tool at the right moment with the right values. If the card is vague, the agent guesses, and guessing is where agents go wrong.

This guide is about writing that card well. It stays at the config and schema level. For the wiring that delivers tools to an agent, see MCP fundamentals. For the agent loop that calls them, see the Claude Agent SDK.

What is a tool for an agent?

To the model, a tool is three pieces of text and structure:

  • name: a unique identifier the agent uses to call the tool, like get_order_status.
  • description: a human-readable sentence about what the tool does and when to use it.
  • input schema: a JSON SchemaA small contract written in JSON Schema that names each input, gives it a type, and marks which are required that names each input, gives it a type, and marks which ones are required.

That is the whole contract. The agent never sees your implementation. It reads the name, the description, and the input shape, then decides whether this tool fits the current step. When it calls the tool, it fills in the inputs and reads back the result as text it can reason over.

Here is a single tool described as config. This is the shape an MCP server reports when an agent asks what tools exist:

{
  "name": "get_order_status",
  "description": "Get the current status of a customer order by its order ID. Use this when a customer asks where their order is or whether it has shipped.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "orderId": {
        "type": "string",
        "description": "The order ID, formatted like ORD-12345"
      }
    },
    "required": ["orderId"]
  }
}

Read it the way the agent does. The name says what action this is. The description says when to reach for it. The schema says it needs one input, orderId, a string, and gives an example of the format. Nothing here is code. It is a description of an action.

The loop a tool plugs into

A tool only matters inside the agent loop. The model picks a tool, the runtime runs it, the result comes back, and the model decides what to do next. Your description is what the model reads at the "pick a tool" step.

Notice the second step. The agent reads the available tool cards and chooses. It is not running your logic to decide. It is reading your words. This is why the description does so much work: it is the only thing standing between the user's request and the right tool firing.

Why does the tool description matter so much?

When an agent has more than one tool, it matches the user's intent against each description and picks the closest fit. Vague or overlapping descriptions cause three failures you will see again and again.

FailureWhat the agent doesCause
Wrong toolCalls search_orders when it needed get_order_statusTwo descriptions sound the same
Skipped toolAnswers from memory instead of calling the toolDescription does not say when to use it
Bad inputsPasses a customer name where an ID was neededInput description is missing or unclear

Every one of these is fixed in text, not code. You are writing for a reader who decides in one pass and cannot ask you a follow-up question. Treat the description as that reader's only briefing.Common gotchaThe sharpest trap is letting the description drift from what the code does: you tighten the function later but leave the old sentence, so the card now promises behaviour the tool no longer has.The agent trusts the words, not the body, and will keep calling it for cases it can no longer handle. Update the description in the same change as the logic, and treat a wording edit as a behaviour change, not a comment tweak.

How do I name a tool?

The name is the first thing the agent matches against. Make it a clear verb plus object.

  • Use a verb and a noun: create_invoice, cancel_subscription, list_open_tickets.
  • Be specific. get_order_status beats lookup, which beats do_thing.
  • Keep names distinct from each other. If you have search_orders and find_orders, the agent cannot tell them apart, and neither can you.
  • Stay consistent. If one tool is get_user, do not name the next one fetchAccount. Pick one style and hold it.

A good name is often enough on its own for the agent to make the right first guess. The description then confirms and narrows it.

How do I write a good tool description?

The description is the most important field. Write it for the agent, not for a changelog. A strong description answers three questions in order: what the tool does, when to use it, and what it does not do.

  • What it does: one plain sentence. "Get the current status of a customer order by its order ID."
  • When to use it: name the trigger. "Use this when a customer asks where their order is or whether it has shipped." This is the line that turns a skipped tool into a used one.
  • When not to use it: draw the boundary against neighbours. "Do not use this to change an order. Use cancel_order for that." This is what stops the wrong-tool failure.

Keep it concrete and short. A description is not documentation; it is a routing signal. Compare these two for the same tool:

WeakStrong
"Order tool.""Get the current status of a customer order by its order ID. Use when a customer asks where their order is."
"Handles refunds and stuff.""Issue a full refund for a paid order. Use only after the customer confirms they want a refund. Does not cancel future billing."

The strong versions read like instructions to a careful new teammate. That is the right mental model: you are onboarding the agent to one task, in two or three sentences.

How do I describe a tool's inputs?

Inputs are where good intentions break. The agent fills them in from the conversation, so each one needs a clear name, a type, and a one-line description with an example when the format matters.

{
  "name": "schedule_callback",
  "description": "Schedule a phone callback for a customer at a specific time. Use when a customer asks to be called back.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "phone": {
        "type": "string",
        "description": "Customer phone number in E.164 format, like +14155550123"
      },
      "callAt": {
        "type": "string",
        "description": "Requested time in ISO 8601, like 2026-06-20T15:00:00Z"
      },
      "reason": {
        "type": "string",
        "description": "Short reason for the callback"
      }
    },
    "required": ["phone", "callAt"]
  }
}

A few rules keep input handling reliable:

  • Name each input for what it holds, not how it is stored: customerEmail, not arg1.
  • Give the format in the description when there is one. "ISO 8601, like 2026-06-20T15:00:00Z" prevents the agent from inventing a date format.
  • Mark only the required inputs as required. Everything else is optional, and the agent will omit it when it has nothing to pass.
  • Use enums for fixed choices. If a status can only be open, pending, or closed, say so in the schema. The agent then cannot pass a value the tool will reject.
  • Prefer a few clear inputs over one large blob. A single data object with undocumented keys gives the agent nothing to aim at.

Keep tools small and single-purpose

One tool should do one thing. A tool that "manages orders" by branching on a mode input forces the agent to reason about your internal modes instead of about the task. Split it.

Three named tools give the agent three clear choices it can match against intent. One overloaded tool gives it a puzzle. Smaller tools also produce clearer permission decisions: a person approving refund_order knows exactly what is about to happen, in a way that approving manage_orders never allows.

Make destructive tools obvious

The agent treats a tool the way you describe it, so a tool that deletes or charges should say so. State the effect in the description, and lean on annotations where your tool host supports them.

MCP defines optional tool annotations that hint at behaviour, such as a read-only hint for tools that only fetch data and a destructive hint for tools that can remove or overwrite. Treat these as advisory signals to the client and the person reviewing calls, and confirm the exact field names against the Model Context Protocol spec before relying on them, since clients may treat annotations from untrusted servers as unverified.

{
  "name": "delete_account",
  "description": "Permanently delete a customer account and all of its data. This cannot be undone. Use only after the customer explicitly confirms deletion.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "customerId": { "type": "string", "description": "The customer ID to delete" }
    },
    "required": ["customerId"]
  }
}

The words "permanently" and "cannot be undone" are not decoration. They are part of the contract the agent reads, and part of what a human sees when asked to approve the call.

Write good result text

The tool's output is also read by the model, so return text it can act on. A status code alone is hard to reason over; a short, plain-text summary is easy.Common gotchaThe opposite mistake hurts as much: dumping the entire raw API response back as the result.That floods the context window with fields the model does not need and buries the one fact it does. Return only the part that answers the call, and summarise the rest. An MCP tool returns content the agent reads back, for example:

{
  "content": [
    { "type": "text", "text": "Order ORD-771 shipped on 2026-06-12 and is out for delivery." }
  ]
}

When a tool fails, say why in the result rather than throwing silently. A clear failure message like "No order found for ORD-771" lets the agent recover, ask the user, or try a different tool. An empty or cryptic result leaves it stuck.

A checklist before you ship a tool

Read each tool the way the agent will, with no access to the code behind it.

  • The name is a clear verb plus object, and distinct from every other tool.
  • The description says what it does, when to use it, and when not to.
  • Each input has a name, a type, a one-line description, and an example when format matters.
  • Only the required inputs are marked required; fixed choices use enums.
  • The tool does one thing. If it branches on a mode, split it.
  • Destructive effects are stated plainly in the description.
  • The result is plain text the model can reason over, including on failure.

If you want a second opinion before shipping, hand the tool cards to Claude and ask it to find the gaps:

Try this prompt
Here are the tool definitions for my agent (name, description, input schema for each). Review them as if you were the agent deciding which to call: - Which two descriptions are easy to confuse, and why? - Which tool would you skip because its description never says when to use it? - Which inputs are missing a format or an example? - Which tool does more than one thing and should be split? Rewrite the weakest description and the weakest input so they are unambiguous.

Try it from the CLI

You do not need a running agent to feel this. Open the Claude Code CLI in a project and ask it to design a tool surface for a small feature. It will produce the names, descriptions, and input schemas as config, which is exactly the artifact this guide is about.

claude

Then describe the feature in plain language and ask for the tool definitions:

Try this prompt
I am building an agent for an online store's support inbox. Propose the set of tools it needs as config only: for each tool give a name, a one-sentence description that says when to use it, and a JSON input schema with typed, described inputs. Keep each tool single-purpose, mark destructive ones clearly, and avoid two tools whose descriptions could be confused.

Review what comes back against the checklist above. The names should read as clear actions, the descriptions should tell the agent when to reach for each one, and the inputs should leave no room to guess. Once those three cards are clear, the agent will pick the right tool far more often than not, and that, more than any clever wiring, is what makes an agent feel like it knows what it is doing.

When you are ready to deliver these tools to a real agent, the transport and discovery are covered in MCP fundamentals, and the loop that calls them is covered in the Claude Agent SDK.