Monday AI Insight. When an agent calls the wrong tool, most of us start rewriting the system prompt. But the model also reads something else on every turn: your tool names, descriptions and parameter schemas.

Anthropic's docs say it directly: when you call the API with tools, it builds a special system prompt from your tool definitions. OpenAI's docs say the same thing in different words: function definitions are injected into the system message and billed as input tokens.

So your tool definitions are prompts. Anthropic's Building effective agents puts it this way: tool definitions "should be given just as much prompt engineering attention as your overall prompts." Here's what that looks like in practice.

Why it matters

Two examples from Anthropic's own work:

  • While building their SWE-bench agent, they "spent more time optimizing our tools than the overall prompt." The model kept making mistakes with relative file paths after moving out of the root directory. They changed the tool to always require absolute paths, and the model "used this method flawlessly."
  • In Writing effective tools for agents (Sep 2025), they note that Claude Sonnet 3.5 reached state-of-the-art on SWE-bench Verified after "precise refinements to tool descriptions." They also found Claude needlessly adding 2025 to its web search query parameter, and fixed it by improving the tool description.

Neither fix touched the model. Both changed the interface the model was given.

Before and after

A tool definition I've seen many versions of:

{ "name": "search", "description": "Search orders.", "input_schema": { "type": "object", "properties": { "user": { "type": "string" }, "status": { "type": "string" }, "date": { "type": "string" } }, "required": ["user"] } } 

The model has to guess everything. Search what: orders, tickets, docs? Is user a name, an email or an ID? Which statuses exist? What date format?

Rewritten:

{ "name": "orders_search", "description": "Finds a customer's orders by customer ID, optionally filtered by status and date range. Use it when the user asks about the status, contents or history of their orders. Do NOT use it for refunds (use orders_refund) or for questions about products not yet ordered (use catalog_search). Returns at most 10 orders, newest first, with order number, status, total and order date. If more than 10 match, narrow the date range.", "input_schema": { "type": "object", "properties": { "customer_id": { "type": "string", "description": "The customer's ID, e.g. CUST-10482. Not the name or email." }, "status": { "type": "string", "enum": ["pending", "shipped", "delivered", "cancelled"], "description": "Only return orders in this status. Omit to return all." }, "placed_after": { "type": "string", "description": "ISO 8601 date (YYYY-MM-DD), e.g. 2026-10-01." } }, "required": ["customer_id"] } } 

Same function underneath. Very different prompt.

The rules, with sources

1. Name tools like a new teammate would. Anthropic suggests describing a tool the way you'd explain it to a new hire, making implicit context explicit. Parameters should be unambiguous: their example is user_id instead of user. When you have many tools, namespace them by service or resource (asana_search, jira_search). Anthropic adds that prefix vs suffix naming had "non-trivial effects" in their evals, and the best choice varied by model.

2. Say when to use it, and when NOT to. Anthropic's tool-use docs call extremely detailed descriptions "by far the most important factor in tool performance," and list what to cover: what the tool does, when it should (and shouldn't) be used, what each parameter means, and caveats. They suggest at least 3–4 sentences per description. Building effective agents adds example usage, edge cases, input format requirements and "clear boundaries from other tools."

3. Describe formats and give examples. OpenAI's best practices: describe the purpose of the function and each parameter (and its format), and what the output represents. Anthropic also supports an optional input_examples field for complex or format-sensitive inputs. Examples must match the schema, and they cost extra prompt tokens.

4. Use enums and structure, not free strings. OpenAI: "Use enums and object structure to prevent invalid states." Their counterexample is toggle_light(on: bool, off: bool), which allows invalid calls. Anthropic calls this poka-yoke: change the arguments so mistakes are harder. OpenAI also recommends strict mode so calls follow your schema reliably.

5. Fewer, non-overlapping tools. Anthropic: "More tools don't always lead to better outcomes," and overlapping or vague tools confuse agents. Prefer one search_logs over a read_logs that dumps everything, or a schedule_event over separate list_users, list_events and create_event. OpenAI says to combine functions that are always called in sequence, avoid making the model fill in arguments your code already knows, and aim for fewer than 20 functions available at the start of a turn (a soft suggestion).

6. Return errors the model can act on. Anthropic recommends prompt-engineering error responses to "clearly communicate specific and actionable improvements, rather than opaque error codes or tracebacks." 400 Bad Request teaches nothing. placed_after must be YYYY-MM-DD, e.g. 2026-10-01 gets fixed on the next call.

7. Keep outputs concise and meaningful. Return high-signal fields like name and file_type, not low-level IDs like uuid or mime_type. Anthropic found that resolving cryptic UUIDs to meaningful language "significantly improves" Claude's precision in retrieval tasks. They suggest a response_format enum ("concise" / "detailed"): in their Slack example, the concise response used 72 tokens vs 206 for the detailed one. Claude Code limits tool responses to 25,000 tokens by default.

8. Eval tool selection, not just final answers. Anthropic recommends realistic multi-step eval tasks. For each task you can optionally list the tools you expect the agent to call (without overfitting to one path). They also recommend tracking tool-call count, tokens, runtime and tool errors. In their words, lots of invalid-parameter errors "might suggest tools could use clearer descriptions or better examples." OpenAI's version is the "intern test": could a person use the function correctly with only what you gave the model?

Checklist

  • [ ] Specific name, namespaced by service or resource
  • [ ] Description: what it does, when to use it, when NOT to, what it returns
  • [ ] Every parameter has a description with format and an example
  • [ ] Enums for fixed sets of values; strict schemas on
  • [ ] No two tools that do almost the same thing
  • [ ] Arguments your code already knows are not asked from the model
  • [ ] Errors say what was wrong and how to fix it
  • [ ] Responses are short, readable and paginated or truncated
  • [ ] An eval set that checks which tool got called, not just the final answer

The one-line version

The model never sees your function's code. It only sees the name, description and schema. Write them like the prompt they are.

What's the worst tool description you've seen an agent struggle with?

References