Introduction
Knowing how to design tool schemas that LLMs use correctly now separates agents that ship from agents that stall in testing. Every tool you expose is a small contract written in names, descriptions, and JSON Schema, and the model reads that contract before it reads anything else about your product. The cost of a careless contract is measurable, because a five-server setup with 58 tools consumed about 55K tokens before the conversation even started, according to Anthropic’s engineering team. Wasted context is only the first problem, since vague schemas also lead to wrong tool choices, invented arguments, and retries that inflate both latency and spend. This guide treats schema design as an engineering discipline with testable rules rather than a matter of personal taste. You will see how models read definitions, how to name and describe tools, how to constrain parameters, and how to measure whether a change helped. The walkthrough ends with a seven-step build process, redesigns from Anthropic, OpenAI, Vercel, and Block, and answers to the questions teams ask most.
Quick Answers on Designing Tool Schemas for LLMs
What is the fastest way to improve how an LLM uses a tool?
Rewrite the description first, covering what the tool does, when to use it, what each parameter means, and what it does not return, because detailed descriptions drive tool performance more than any other factor.
How do you learn how to design tool schemas that LLMs use correctly?
To learn how to design tool schemas that LLMs use correctly, use specific names, three to four sentence descriptions, enums for fixed choices, required fields, and strict validation, then test with realistic tasks.
How many tools should an LLM agent see at once?
OpenAI suggests fewer than 20 functions at the start of a turn, and Anthropic advises deferring large tool sets with tool search once definitions pass roughly 10K tokens.
Key Takeaways
- Treat every tool name, description, and parameter as a prompt, because the model sees nothing else about your system.
- Constrain inputs with enums, required fields, and strict mode so invalid calls become impossible rather than merely unlikely.
- Build fewer, outcome-oriented tools, and defer or consolidate large tool sets to protect the context window.
- Measure with realistic evaluation tasks, since tool definitions improve most when you iterate against real transcripts.
Table of contents
- Introduction
- Quick Answers on Designing Tool Schemas for LLMs
- Key Takeaways
- What Is a Tool Schema for an LLM?
- How Models Read Tool Definitions
- Naming Tools So the Model Picks the Right One
- Writing Descriptions That Carry the Decision
- Parameters, Types, and Enums That Prevent Invalid Calls
- Choosing Which Tools to Build, and How Many
- Designing Tool Responses and Error Messages
- Where Tool Schemas Fall Short: Risks and Failure Modes
- Security and Ethics of Giving Models Tools
- Putting Schema Design Into Practice With Evaluation Loops
- The Future of Tool Interfaces for LLM Agents
- How to Design a Tool Schema From Scratch in Seven Steps
- Step 1 – Define the job and the outcome
- Step 2 – Name the tool and write the description
- Step 3 – Define the input schema with types and enums
- Step 4 – Design the response and error format
- Step 5 – Add input examples and strict validation
- Step 6 – Wire the tool in and validate arguments in code
- Step 7 – Evaluate on realistic tasks and iterate
- Key Insights
- Real Tool Schema Designs in Practice
- Lessons From Three Production Tool Redesigns
- Common Questions About Designing Tool Schemas for LLMs
What Is a Tool Schema for an LLM?
Learning how to design tool schemas that LLMs use correctly means writing precise names, descriptions, and typed parameters so a model chooses the right tool and supplies valid arguments.
An Interactive From AIplusInfo
Tool Schema Cost and Reliability Lab
Adjust how many tools you expose and how carefully you define them to see the context cost and the risk of a bad call.
12 tools
3 sentences
Typed with enums
One or two examples
0
Definition tokens per request
0
Tool selection index (0 to 100)
0%
Estimated invalid-argument risk
Illustrative model, not a benchmark. For real figures, Anthropic measured about 55K tokens for 58 MCP tools in its advanced tool use post, and OpenAI suggests fewer than 20 functions per turn in its function calling guide.
How Models Read Tool Definitions
A language model never sees your code, your database, or your API gateway, and it sees only the definition you hand it. That definition usually arrives as a name, a natural language description, and a JSON Schema describing the arguments. The model reads these fields as ordinary text in its context window, so every word competes for attention with the user request and the conversation history. When a request arrives, the model predicts which tool, if any, fits and then generates arguments that match the schema. Nothing in that process executes code, which means your application must still validate the arguments before acting on them. Understanding this pipeline explains why small wording changes in a definition can swing behavior so dramatically.
Providers describe the same idea with slightly different fields and naming conventions. Anthropic's tool definition guide lists a name, a description, an input schema, and optional input examples. The Model Context Protocol adds an optional title, an optional output schema, and annotations that describe tool behavior. OpenAI's function definitions follow a similar pattern and add a strict flag that turns on constrained decoding. Across all three, the description and the parameter descriptions carry most of the meaning, because the model has no other source of truth. For a deeper look at the mechanics, see this explainer on how function calling works in LLMs. The practical lesson is that schema design is really context design, and context is always a scarce resource.
Models also treat tool definitions as instructions, so ambiguity in a definition becomes ambiguity in behavior. If two tools have overlapping descriptions, the model has to guess, and its guess will not always match your intent. If a parameter is named loosely, the model may fill it with whatever string seems plausible. Anthropic's engineers describe the right mental model as writing for a new hire who lacks your team's implicit context. Everything a colleague would absorb from hallway conversations must be written into the definition. Teams that adopt this view tend to find that their first drafts were missing exactly the details a newcomer would ask about.
Naming Tools So the Model Picks the Right One
Names are the first thing a model weighs, so they deserve the same care as a public API. A name like data or helper tells the model almost nothing, while a name like search_support_tickets states the verb and the object together. Prefer verbs that describe the outcome, and keep names stable across versions so cached prompts and evaluation sets stay valid. When tools span several services, namespacing prevents collisions and helps the model group related capabilities. Anthropic's guidance on writing tools offers examples such as asana_search and asana_projects_search, and notes that prefix or suffix choices can change results depending on the model. Treat naming conventions as something to test rather than something to assume.
Avoid synonyms that blur the boundaries between your different tools. If one tool is called get_customer and another is called fetch_account, the model cannot tell which one returns billing details. Parameter names deserve the same discipline, and Anthropic recommends unambiguous choices such as user_id instead of a bare user. A parameter called id is even riskier, because the model must infer which kind of identifier you mean. Long names also cost tokens, because the model regenerates them on every call, so aim for clear and compact rather than exhaustive. Block's engineering team makes the same point about long names in its MCP design playbook.
Writing Descriptions That Carry the Decision
Building on naming, the description is where most tool-use quality is won or lost. Anthropic's tool definition documentation calls detailed descriptions by far the most important factor in tool performance and recommends at least three to four sentences per tool. Those sentences should cover what the tool does, when it should be used and when it should not, what each parameter means, and what the tool deliberately does not return. Many teams write one cheerful sentence and stop, which leaves the model to infer every boundary. A useful test is to hand the description to a colleague and ask which ticket types it would handle. If the colleague hesitates before answering, the model will almost certainly hesitate too.
State the negative space explicitly, because models are far better at following a boundary than at inventing one. For example, a refund tool might say that it only handles orders under thirty days old and that disputes belong to a different tool. That single sentence prevents a whole category of wrong calls. OpenAI offers a related test it calls the intern test, which asks whether a newcomer could use the function correctly with only the information the model sees. If the answer is no, the missing facts belong in the description or the system prompt. Write for that intern and your model will benefit as well.
Descriptions also interact with everything else in the context window, which is why the discipline of context engineering for LLM agents applies directly. Put routing guidance, such as when to prefer one tool over another, in the tool description where the model reads it at decision time. Reserve the system prompt for cross-cutting policy, such as tone, escalation rules, and safety limits. Avoid duplicating the same instruction in both places, because the copies drift apart and the model sees conflicting text. Keep each description focused on one capability so it can be reused in other agents without edits. Short, specific, and complete beats long and rambling every time.
Description quirks can also correct subtle behavior problems that no amount of prompt tuning fixes. Anthropic reported that Claude was appending the year 2025 to web search queries, which biased results toward older content, and a clearer tool description corrected the habit. That example shows how a single ambiguous line can quietly degrade output across thousands of calls. It also shows why teams should read transcripts rather than only aggregate scores. Watching real calls exposes odd argument patterns that metrics hide. Each discovery becomes a sentence you can add to the description, so the definition improves as your understanding of failures deepens.
Parameters, Types, and Enums That Prevent Invalid Calls
Turning to parameters, the schema is where you convert fuzzy intent into a form your code can trust. Use the narrowest type that fits, such as an integer with a minimum and maximum instead of a free string. Mark truly required fields as required and give optional fields sensible defaults in your own code rather than hoping the model remembers them. Describe each parameter with its format and an example, such as an ISO date or a two-letter country code. Add descriptions even when a name seems obvious, because obvious to you is not obvious to a model. OpenAI's function calling guide asks developers to explicitly describe the purpose of the function and each parameter, including its format.
Enums are the strongest tool you have for eliminating impossible values. Instead of a free string for priority, list low, medium, and high, and the model can only choose among valid options. The same principle applies to structure, and OpenAI points out that a function with two booleans, on and off, permits the invalid state where both are true. A single enum with those two values removes the invalid combination entirely. Design schemas so that illegal states cannot be represented, and your validation code shrinks. Understanding how MCP and function calling differ also helps, because each runtime enforces a different slice of the schema.
Offload as much work from the model as you can. If your application already knows the order identifier, do not ask the model to supply it, and bind it in code when the tool runs instead. OpenAI gives the example of a submit_refund function that receives the order identifier from your code rather than from the model. Combine functions that are always called in sequence, so the model makes one decision instead of two. Every argument you remove is an argument that can no longer be hallucinated. Smaller schemas are also cheaper, since function definitions are billed as input tokens on every request.
Choosing Which Tools to Build, and How Many
Stepping back from single tools, the larger design question is which capabilities deserve a tool at all. A common mistake is wrapping every API endpoint one for one, which produces dozens of low-level tools that the model must chain correctly. Anthropic's advanced tool use post describes a five-server setup with 58 tools that consumed about 55K tokens before any work began, with GitHub alone contributing 35 tools. Consolidating workflows into fewer high-impact tools, such as a single schedule_event instead of separate list and create calls, shrinks the menu and the number of steps. Anthropic also suggests search tools that return relevant context rather than list tools that dump everything. OpenAI offers a soft guideline of fewer than 20 functions available at the start of a turn. Treat these numbers as starting points and measure your own agent.
When the tool count is large anyway, defer loading instead of paying for every definition up front. Anthropic's tool search feature kept definitions out of context until needed. Its published figures show roughly 72K tokens of definitions for 50 or more tools shrinking to about 8.7K in total. The approach adds a search step, so it works best when definitions exceed about 10K tokens or you expose ten or more tools. The same cost logic appears in guides on reducing LLM inference costs, where fewer input tokens directly lower spend. Discovery also depends on good names and descriptions, so the earlier sections of this guide become even more important. A small, well-described toolset almost always beats a large, vague one.
Designing Tool Responses and Error Messages
On top of inputs, the output of a tool shapes the next decision the model makes, so responses deserve their own design pass. Return only the fields the model needs for its next step, and prefer human-readable names over opaque identifiers. Anthropic's engineers found that resolving raw identifiers into meaningful names reduced hallucinations and improved retrieval precision. Where follow-up calls need identifiers, a response_format parameter with concise and detailed options lets the agent choose. In Anthropic's Slack example, a detailed response used about 206 tokens while the concise version used about 72. That difference compounds quickly across dozens of calls in a long task.
Pagination, filtering, and truncation with sensible defaults keep large results from flooding the context window. Claude Code, for example, caps tool responses at 25,000 tokens by default. When you truncate, tell the model how to narrow its next request, such as by adding a date filter or a more specific query. A message that says results were truncated and suggests adding a project filter teaches the agent to recover on its own. Without that guidance, the model often repeats the same broad query and hits the same wall. Good truncation messages are small prompts embedded inside your tool.
Errors are also part of the interface that the model reads. The MCP specification for tools separates protocol errors, such as unknown tools or invalid arguments, from tool execution errors that are reported inside the result with an error flag. That split lets the model see and react to business failures like rate limits, while protocol problems are handled by the client. Write execution errors as plain sentences that say what went wrong and what to try next. An opaque code such as E4127 gives the model nothing to reason with. A clear message saying that the start date must be earlier than the end date invites a correct retry on the next turn.
Structured output is worth adding whenever downstream code consumes the result. The same specification allows an optional output schema, and servers must return structured results that conform to it when one is declared. Clients should validate those results, which turns a loose contract into a checkable one. Cost tracking belongs here as well, since long outputs inflate every later turn. Teams that want to quantify the impact can follow the approach described in measuring agent cost per task. Measuring cost per completed task, rather than per call, shows whether a redesign really saved money.
Where Tool Schemas Fall Short: Risks and Failure Modes
Despite careful design, schemas cannot guarantee that a model will behave well, and it helps to name the common failure modes. The first is wrong tool selection, which happens when descriptions overlap or the menu grows too large. The second is argument hallucination, where the model fills a required field with a plausible but invented value. The third is schema drift, where the tool changes but its definition and evaluation set do not. Multi-turn tasks add a fourth, because earlier results must be remembered and reused correctly. The Berkeley Function Calling Leaderboard paper reports that state-of-the-art models excel at single-turn calls while memory, dynamic decision-making, and long-horizon reasoning remain open challenges.
Strict mode removes malformed arguments but cannot make a wrong value right. OpenAI notes that matching a schema does not guarantee correct values, so a math step inside valid JSON can still be wrong. Constrained decoding also supports only a subset of JSON Schema, which limits how expressive your types can be. The first request with a new schema pays a preprocessing delay, and complex schemas can take up to a minute. Structured outputs are not compatible with parallel function calls, which forces a trade-off between guaranteed shape and concurrency. Knowing these limits keeps you from treating the flag as a cure-all.
Hallucinated arguments deserve special attention because they look correct to a casual reader. A fabricated customer identifier passes type validation, and a plausible date can silently point at the wrong record. Validate every argument against your system of record before acting, and return a clear error when a value does not exist. Practices from reducing LLM hallucinations in production apply here, including grounding and verification steps. Logging every tool call with its arguments makes patterns visible when a particular field keeps going wrong. Over time, those logs become the best source of new evaluation cases.
Security and Ethics of Giving Models Tools
With tools, a model stops being a text generator and becomes an actor, which raises the security and ethical stakes. The MCP specification states that servers must validate all tool inputs, implement access controls, rate limit invocations, and sanitize outputs. It also recommends that clients keep a human in the loop for sensitive operations and show tool inputs to users before calling a server. Tool descriptions and annotations from untrusted servers should be treated as untrusted too, since they flow directly into the model's context. The security risks of MCP servers are worth reading about before you publish one of your own. Least privilege remains the safest default, so expose read-only tools first and require explicit confirmation for anything destructive.
Ethics enters through the questions of who can trigger an action, who is told, and who is accountable when it goes wrong. A schema can encode some answers, for example by requiring a confirmation flag for deletions or by splitting read and write tools. Prompt injection adds another layer, because instructions hidden in retrieved content can steer a model toward calling tools it should not. A broader treatment appears in this guide to defending against prompt injection attacks. Transparency matters as well, since users deserve to know which tools an assistant can use on their behalf. Document these decisions alongside the schema so reviewers can audit them later.
Putting Schema Design Into Practice With Evaluation Loops
Moving on to evaluation, the most reliable way to improve a schema is to test it against realistic tasks. Anthropic recommends a loop of building a prototype, running an evaluation, and iterating, with tasks drawn from real workflows rather than toy lookups. Strong tasks may require dozens of tool calls, while weak tasks are simple single lookups that every design passes. Pair each task with a verifier, such as an exact match or a judge model, but avoid verifiers so strict that they reject valid phrasings. Track accuracy, runtime, number of tool calls, token use, and tool errors for every run. Repeated calls to the same tool often reveal candidates for consolidation.
A judge model can score free-form results when exact matching is too brittle. This approach has its own pitfalls, so read the walkthrough on evaluating LLM outputs with LLM-as-a-judge before relying on it. Have the evaluation agent output its reasoning and feedback before each tool call, because those notes show why it chose a tool. Review full transcripts as well as scores, since a passing answer can hide wasteful detours. Change one thing at a time, such as a description or an enum, so you can attribute any gain. Keep a held-out set of tasks to confirm that improvements generalize.
Agent-specific evaluation frameworks can automate part of this loop for teams that already run on managed platforms. One example is the walkthrough on evaluating Amazon Bedrock agents with RAGAS, which covers applying RAGAS metrics to agents on that platform. Whatever framework you choose, keep your evaluation data under version control next to the schemas. When a schema changes, rerun the suite and compare results against the previous baseline. A regression in tool selection accuracy is a signal to inspect the new description before you ship. Over several cycles this discipline turns schema writing from guesswork into engineering.
The Future of Tool Interfaces for LLM Agents
Looking ahead, the trend is toward tools that are discovered on demand and composed rather than called one at a time. Anthropic's advanced tool use work pairs tool search with programmatic tool calling, where Claude writes code that invokes several tools and only the final output enters context. In its internal results, average tokens on complex research tasks fell from 43,588 to 27,297, a 37 percent reduction. Cloudflare's Code Mode pushes the same idea further by converting an MCP server's schema into a TypeScript API and giving the agent one tool that runs code in a sandbox. Its authors argue that models have seen far more real code than tool-calling examples, so they write code more reliably than they emit direct calls. These designs are still early, in beta or closed beta, and they trade simplicity for extra moving parts.
Standardization will likely matter as much as any single technique. The Model Context Protocol already gives servers a common way to publish names, schemas, and annotations, and the wider story of MCP and AI integration is still unfolding. Output schemas, behavior annotations, and list-changed notifications point toward richer contracts between tools and models. As models improve, some constraints in today's schemas may become unnecessary, a possibility Vercel's engineers raised about their own agent. Even so, knowing how to design tool schemas that LLMs use correctly will stay valuable, because clear names, explicit boundaries, and measured iteration transfer to every new runtime. Teams that master those habits now will adapt faster when the tooling changes.
Chart From AIplusInfo
What tool definitions cost in context tokens
Thousands of tokens consumed by tool definitions before any work begins.
Source: Anthropic, advanced tool use for token costs, tool search, and input examples; Vercel, removing agent tools for the d0 success rate. Vercel tested five queries only.
How to Design a Tool Schema From Scratch in Seven Steps
Step 1 - Define the job and the outcome
Building on the principles above, begin with the job the tool must do rather than the API you plan to call. Write one sentence that states the user outcome, such as finding the open support tickets for a customer and summarizing their status. List the 3 or 4 inputs a person would naturally provide and the output they would expect to see. Check whether the job really needs several low-level calls, because a workflow-shaped tool is usually easier for a model than a chain of endpoints. Block's playbook recommends designing top down from workflows instead of bottom up from endpoints. Decide early which actions only read data and which change it, since that split drives permissions later. For wider context on agent workflows, see this guide to building custom AI agents for workflow automation.
Step 2 - Name the tool and write the description
From there, choose a name that combines a verb and an object, such as search_support_tickets, and add a service prefix if you expose several systems. Write the description in four parts that cover what the tool does, when to use it, when not to use it, and what it returns. Keep each part to a sentence or two so the whole description stays between 3 and 6 sentences. Mention limits explicitly, such as the maximum number of results or the oldest record the tool can see. Avoid marketing language and internal jargon that a newcomer would not understand. Read the description aloud as if briefing a new colleague, and rewrite any sentence that prompts a follow-up question.
Step 3 - Define the input schema with types and enums
With that, translate the inputs into a JSON Schema using the narrowest types available. Give every property a description that states its format and an example, and mark only the genuinely required fields as required. Use enums for fixed choices, minimum and maximum values for numbers, and patterns for identifiers when the format is strict. Set additionalProperties to false so the model cannot invent extra fields. The example below defines a ticket search tool with a 3-value status enum and a limit capped at 20. Pro tip: if you catch yourself adding a free-text field for something with five known values, turn it into an enum instead.
{
"name": "search_support_tickets",
"description": "Search one customer's support tickets by status and keyword. Use this when the user asks about the state of a specific request. Do not use it for billing disputes, which belong to the billing tools. Returns at most 20 tickets, newest first, with ticket_id, subject, status, and last_updated.",
"input_schema": {
"type": "object",
"properties": {
"customer_id": {"type": "string", "description": "Customer identifier such as cus_8F2A91. Ask the user if unknown."},
"status": {"type": "string", "enum": ["open", "pending", "resolved"], "description": "Ticket status to filter by."},
"keyword": {"type": "string", "description": "Optional word or phrase to match in the ticket subject."},
"limit": {"type": "integer", "minimum": 1, "maximum": 20, "description": "Maximum tickets to return. Defaults to 10."}
},
"required": ["customer_id", "status"],
"additionalProperties": false
}
}
Step 4 - Design the response and error format
Next, decide exactly what the tool returns, because the response becomes the model's next piece of evidence. Return a compact list of 10 or so items with human-readable fields, and resolve internal identifiers into names wherever you can. Add a response_format option only if some callers genuinely need identifiers for follow-up calls. Truncate long results with a clear note that tells the model how to narrow the query. Write errors as short sentences that state the cause and the fix, such as an unsupported status and the allowed values. Test each error path by triggering it on purpose and reading the message as the model would.
ALLOWED_STATUS = {"open", "pending", "resolved"}
def search_support_tickets(customer_id, status, keyword=None, limit=10):
if status not in ALLOWED_STATUS:
return {"is_error": True,
"message": "status must be one of open, pending, or resolved."}
rows = db.query_tickets(customer_id, status, keyword, limit + 1)
truncated = len(rows) > limit
tickets = [
{"ticket": r.subject, "status": r.status, "updated": r.updated_at.isoformat()}
for r in rows[:limit]
]
result = {"tickets": tickets}
if truncated:
result["note"] = "More tickets exist. Add a keyword or a narrower status to refine."
return result
Step 5 - Add input examples and strict validation
Once the base schema works, add examples and turn on strict validation where your provider supports it. Anthropic's tool definitions accept an input_examples array, and each example must validate against the input schema or the API returns an error. The company's internal testing showed accuracy on complex parameter handling rising from 72 percent to 90 percent with examples. The cost is roughly 20 to 50 tokens for simple ones, as described in its advanced tool use engineering post. Include two or three examples that show the common case, an optional parameter being omitted, and an edge case. OpenAI's strict mode needs additionalProperties set to false and every property listed as required. Remember that strict mode guarantees shape rather than truth, so keep your semantic checks in code.
{
"input_examples": [
{"customer_id": "cus_8F2A91", "status": "open", "limit": 5},
{"customer_id": "cus_17B3C0", "status": "resolved", "keyword": "refund"},
{"customer_id": "cus_55D9E2", "status": "pending"}
]
}
Step 6 - Wire the tool in and validate arguments in code
Then connect the tool to your client and treat every model-supplied argument as untrusted input. Run 3 checks on the server: validate the arguments against the same JSON Schema, confirm that identifiers exist, and enforce the caller's permissions. Return execution failures as results the model can read rather than raising exceptions that end the turn. Keep live API documentation close to your coding workflow, a theme explored in AI coding agents and live API docs. Add guardrails that block destructive actions without confirmation, as described in deterministic guardrails for AI agents. Log the tool name, arguments, latency, and outcome for every call so you can debug failures later.
from jsonschema import validate, ValidationError
def run_tool(name, arguments, user):
schema = TOOL_SCHEMAS[name]["input_schema"]
try:
validate(instance=arguments, schema=schema)
except ValidationError as err:
return {"is_error": True, "message": f"Invalid arguments: {err.message}"}
if not user.can_read_customer(arguments["customer_id"]):
return {"is_error": True, "message": "You do not have access to this customer."}
return TOOLS[name](**arguments)
Step 7 - Evaluate on realistic tasks and iterate
Finally, run the tool against a realistic evaluation set and iterate on the definition rather than the prompt. Write 20 or more tasks drawn from real user requests, including ambiguous ones and ones that should trigger no tool at all. Record which tool the model chose, the arguments it produced, the number of calls, and the tokens consumed. Change one element at a time, such as a description sentence, an enum, or a parameter name, and rerun the suite. Keep state in mind for multi-step tasks, since agent memory architecture determines which earlier results the model can still use. When results plateau, invite a colleague to break the tool with confusing requests.
def score_run(task, transcript):
calls = [c for c in transcript.tool_calls]
return {
"chose_expected_tool": bool(calls) and calls[0].name == task["expected_tool"],
"valid_arguments": all(c.valid for c in calls),
"call_count": len(calls),
"tokens": transcript.total_tokens,
}
results = [score_run(t, run_agent(t["prompt"])) for t in EVAL_TASKS]
print(sum(r["chose_expected_tool"] for r in results) / len(results))
Recommended by AIplusInfo
Books to go deeper on LLM tooling
Two practitioner titles that map to the schema, evaluation, and agent topics covered above.
As an Amazon Associate, AIplusInfo earns from qualifying purchases.
Book
Hands-On Large Language Models: Language Understanding and Generation
A practical, illustrated tour of how language models process text, which helps explain why tool names and descriptions steer behavior.
Buy on AmazonBook
AI Engineering: Building Applications with Foundation Models
Covers evaluation, prompt design, and agent systems end to end, which supports the measure-and-iterate loop recommended for tool definitions.
Buy on AmazonKey Insights
- OpenAI reported that gpt-4o-2024-08-06 with strict Structured Outputs scored 100 percent on complex schema-following evaluations, while the earlier gpt-4-0613 model scored below 40 percent on the same test.
- Anthropic's internal testing showed that input examples raised accuracy on complex parameter handling from 72 percent to 90 percent, as its advanced tool use post documents.
- Loading 50 or more MCP tool definitions consumed about 72K tokens, while tool search cut the total to roughly 8.7K and lifted accuracy from 49 to 74 percent.
- A detailed Slack tool response used about 206 tokens against roughly 72 for the concise version, so a simple response format option cut that payload to about one third.
- Vercel cut its agent from 17 tools to 2, lifting success from 80 to 100 percent on five queries, while average execution time fell from 274.8 to 77.4 seconds.
- OpenAI suggests fewer than 20 functions at the start of a turn, a soft limit in its function calling guide that also notes definitions are billed as input tokens.
- Block's Linear MCP server began with more than 30 tools, and a question about one person's issues took four to six calls before the design collapsed into two GraphQL tools.
- Anthropic advises writing at least three to four sentences per tool description, calling detail by far the most important factor in tool performance, ahead of every other schema tweak.
Taken together, these figures describe a consistent pattern in which the cheapest improvements happen before the model is ever called. Strict schemas and input examples raise accuracy by narrowing what a valid call can look like. Smaller, outcome-oriented toolsets and deferred loading reduce the context burden and the number of decisions the model must make. Concise responses and clear errors keep each turn efficient and recoverable. None of these gains arrives automatically, because every one was found by measuring real tasks and iterating on transcripts. The practical takeaway is to treat the tool definition as a product surface with its own tests, metrics, and release cycle.
| Design element | Weak approach | Strong approach | Typical effect |
|---|---|---|---|
| Tool naming | Generic names such as data or helper | Verb and object names with a service prefix | Fewer wrong tool selections |
| Description depth | One sentence that says what the tool is | Three to four sentences covering use, limits, and returns | Clearer boundaries between tools |
| Parameter typing | Free-text strings for every field | Narrow types with minimum and maximum values | Fewer malformed arguments |
| Fixed choices | Open strings that accept any value | Enums that list only valid options | Invalid values become impossible |
| Toolset size | One tool per API endpoint | Workflow-shaped tools and deferred loading | Lower token cost and fewer steps |
| Response format | Full records with raw identifiers | Concise fields with readable names | Smaller payloads and fewer hallucinations |
| Error messages | Opaque numeric codes | Plain sentences that state cause and fix | Faster recovery on the next turn |
| Input examples | None provided | Two or three validated examples | Better handling of complex parameters |
| Validation | Trust the model output | Schema checks and permission checks in code | Safer execution of every call |
Real Tool Schema Designs in Practice
Anthropic's Concise and Detailed Slack Responses
Anthropic's engineers built a Slack tool for their agents and ran evaluations to see how response size affected results. They added a response_format enum with concise and detailed options, so an agent could request identifiers only when a follow-up call needed them. The detailed response used about 206 tokens in the team's measurement, while the concise version used about 72, which is roughly a two-thirds reduction. They also resolved raw identifiers into readable names, and the team reported in its writing tools for agents guide that this reduced hallucinations and improved retrieval precision. The limitation is that Anthropic published the token counts and charts without exact accuracy numbers for every variant. Teams still need to measure the trade-off on their own data, since the right default depends on how often follow-up calls are required. Even so, the example shows that a single enum can cut payload size without removing capability.
OpenAI's Strict Structured Outputs for Function Calling
OpenAI rolled out Structured Outputs so developers could set strict true on a function definition and have the model's arguments match the supplied schema. The company reported that gpt-4o-2024-08-06 with the feature scored 100 percent on its complex JSON schema-following evaluation, compared with under 40 percent for gpt-4-0613. Behind the scenes, the schema is converted into a grammar, and tokens that would break it are masked during generation. The published examples set additionalProperties to false and list every property as required. There are limits, because only a subset of JSON Schema is supported and the first request with a new schema adds latency of up to a minute for complex cases. Parallel function calls are not compatible with the feature, so teams must choose between concurrency and guaranteed shape. According to OpenAI's announcement of Structured Outputs, valid JSON still does not guarantee correct values.
Anthropic's Input Examples for Complex Parameters
Anthropic added an input_examples field to tool definitions so developers can show Claude concrete usage patterns, such as formats, identifier conventions, and when optional parameters apply. In internal testing on complex parameter handling, accuracy rose from 72 percent to 90 percent after the examples were used. The company recommends one to five examples per tool, and each example must validate against the tool's input schema or the request returns an error. The cost is extra tokens, roughly 20 to 50 for simple examples and 100 to 200 for complex nested objects. The feature is still in beta and requires a specific header, and it is less useful for simple tools or standard formats such as URLs and emails. Server tools and certain computer use toolsets do not support it at all. The advanced tool use post frames examples as a complement to JSON Schema rather than a replacement for it.
Lessons From Three Production Tool Redesigns
Case Study: Vercel's d0 Agent Drops Fifteen Tools
Vercel's text-to-SQL agent, called d0, faced a problem common to early agent projects, because it registered 17 specialized tools and complex questions sometimes spiraled into long, failing runs. In its worst case under the old design, the agent took 724 seconds, 100 steps, and 145,463 tokens before failing. Vercel's team adopted a radically smaller design that cut the registered tools from 17 to 2. The new design centered on a bash command tool running in a sandbox over a semantic layer stored as plain files. On five benchmark queries with Claude Opus 4.5, success rose from 80 percent to 100 percent.
Average execution time fell from 274.8 to 77.4 seconds, and average tokens dropped from about 102,000 to 61,000. Steps fell by roughly 42 percent, from about 12 to about 7 per query. The limitation is scale, because five queries is far too few to be statistically meaningful, and the author notes that results are tied to one model. The approach also depends on well-documented data, and the post warns that messy naming or undocumented joins would only produce faster bad queries. The Vercel write-up on removing agent tools is a useful reminder that fewer tools can mean better outcomes when the underlying data is clean.
Case Study: Block's Linear MCP Server Redesign
Block's engineers built an MCP server for Linear, and the first version had a familiar problem because it exposed more than 30 tools, mostly one per API operation. Because the design was bottom up, a simple question about one person's open issues took four to six tool calls, depending on how many teams they belonged to. The team responded with a workflow-first redesign, first consolidating read-only operations into category tools such as get_issue_info with an info_category parameter. They then moved toward two tools that accept GraphQL queries directly, one read-only and one for mutations, with the schema and examples placed in the model's instructions. The same question can now be answered with a single query, a reduction from four or more calls to one. The post is candid about limits, because it reports no measured token savings, latency, or success rates, and the call counts are anecdotal. It also acknowledges that language models struggle with strict grammars, so the reliability of generated GraphQL remains something teams must test themselves. The Block playbook for designing MCP servers therefore works better as a design pattern than as a benchmark.
Case Study: Anthropic's Tool Search for MCP-Heavy Agents
Anthropic faced a bottleneck as agents connected to many MCP servers. A five-server setup with 58 tools consumed about 55K tokens before the conversation started, and some internal setups reached 134K tokens. Loading all those definitions up front crowded out the work itself and made tool selection harder for the model. The company introduced a tool search feature, where deferred tools stay out of context until Claude searches for them. Search can use built-in regex or BM25 matching, or a custom embedding approach. The team treated this as a context management problem rather than a model capability problem, since the definitions themselves were accurate but simply too numerous to carry everywhere.
For a library of 50 or more MCP tools, the context cost fell from about 72K tokens to roughly 8.7K, which Anthropic describes as an 85 percent reduction. Accuracy on its MCP evaluations rose from 49 percent to 74 percent for Opus 4 and from 79.5 percent to 88.1 percent for Opus 4.5. The trade-off is an added search step with extra latency, and the feature is less useful with fewer than ten tools or when most tools are used every session. Discovery also depends on clear names and descriptions, which brings the design work back to the schema itself. Details appear in Anthropic's advanced tool use engineering post, and the features required a beta header at the time of writing.
Common Questions About Designing Tool Schemas for LLMs
A tool schema is the definition you give a model so it can call an external function. It normally includes a name, a natural language description, and a JSON Schema that describes each argument. The model reads this text, decides whether a tool fits the request, and generates arguments that match the schema. Your application then validates those arguments and runs the real code.
Anthropic recommends at least three to four sentences per tool, and more for complex tools. Those sentences should explain what the tool does, when to use it, what each parameter means, and what the tool does not return. Longer is not automatically better, because every sentence consumes context on every request. Aim for descriptions that are complete and focused rather than exhaustive.
Use enums whenever the valid values form a small fixed set, such as status, priority, or unit. An enum removes the possibility of an invented value and makes your validation code simpler. Free text is appropriate only for genuinely open input, such as a search phrase. Even then, describe the expected format and give an example.
There is no universal limit, and the answer depends on the model, the clarity of the descriptions, and how different the tools are. OpenAI suggests aiming for fewer than 20 functions at the start of a turn as a soft guideline. Anthropic notes that tool search becomes worthwhile when definitions exceed about 10K tokens or you expose ten or more tools. Test your own agent with different tool counts to find where selection quality drops.
Strict mode uses constrained decoding so the model's arguments match your JSON Schema exactly. It prevents missing fields, wrong types, and values outside an enum. It does not guarantee that a valid value is correct, so a plausible but wrong identifier can still pass. You still need semantic validation in your own application code.
Input examples show the model concrete patterns that a schema alone cannot express, such as identifier formats and when optional parameters apply. Anthropic reported accuracy on complex parameter handling rising from 72 percent to 90 percent in internal testing. Each example must validate against the schema, and examples add tokens to every request. Use one to five examples on tools with tricky parameters rather than on every simple tool.
The most common cause is overlapping or vague descriptions that make two tools look equally suitable. Very large toolsets also make selection harder because the model must compare many options. Ambiguous names, such as get_data, give the model no signal to separate one tool from another. Rewriting descriptions to state when not to use a tool often fixes the problem quickly.
Return errors as short, plain sentences inside the tool result so the model can read and react to them. State what went wrong and what the model should try next, such as a missing filter or an unsupported value. Avoid opaque numeric codes, because they give the model nothing to reason about. Reserve protocol-level errors for problems like unknown tools or malformed requests.
Both describe a callable function with a name, a description, and a JSON Schema for inputs. The Model Context Protocol adds fields such as a title, an optional output schema, and behavior annotations, and it standardizes how servers publish tools to many clients. OpenAI's definitions add a strict flag that enables constrained decoding. The design advice about names, descriptions, and parameters applies equally to both.
Remove arguments the model does not need to supply by binding known values, such as the current user or order, in your own code. Use enums and narrow types so invalid values cannot be expressed. Validate every remaining argument against your system of record and return a clear error when a value does not exist. Logging every call helps you spot the fields that fail repeatedly.
Fewer, workflow-shaped tools usually work better than one tool per API endpoint. Anthropic and Block both describe consolidating multi-step operations into single tools that return only relevant context. Very large catch-all tools can become hard to describe, so keep each tool focused on one coherent job. Evaluate both designs on realistic tasks before you commit to either.
Build an evaluation set of realistic tasks, including ambiguous requests and cases where no tool should be called. Record which tool the model chose, the arguments it produced, the number of calls, and the tokens used. Change one element at a time and rerun the suite so you can attribute any difference. Keep a held-out set of tasks to confirm that gains generalize.
Start with the official guidance from Anthropic, OpenAI, and the Model Context Protocol specification. Then build one small tool, write an evaluation set, and read the transcripts to see where the model hesitates. Each failure usually points to a missing sentence in a description or a missing constraint in the schema. Repeating that loop teaches you more than any single static checklist.