Tool Calling and Function Calling, Explained Without Code
If foundation models are the engine of an agent, tool calling is the steering wheel. It is also the place 70-80% of production agent failures originate โ not because the model is dumb, but because the tool definitions are sloppy, the names overlap, or the schemas hide the fields the model needs. This lesson teaches you to read a tool definition, predict which call the LLM will make, and catch the 80% of tool-pick errors that fail in production before they reach production.
Why Tool Calling Matters More Than the Model
In 2024, the dominant agent failure mode was the model itself โ hallucinations, refusals, confused outputs. By 2026, models are good enough that the dominant failure mode has shifted. Production teams report that 60-75% of agent incidents trace back to tool-pick errors: the model picked the wrong tool, called the right tool with wrong arguments, or skipped a tool it should have called. The model is rarely the culprit. The tool surface is.
A B2B SaaS support team I helped audit in late 2025 had an agent with a 94% accuracy benchmark and a 67% real-world deflection rate. The gap? Twelve of their fifteen failure traces involved the same pattern: the agent called a generic search_knowledge_base tool when it should have called a specific lookup_account_status tool, because both tool descriptions started with "search for information about." Three days of rewriting tool descriptions raised real-world deflection to 89%. No model change. No prompt edit. Just better tool surface design.
Your tool definitions are the prompt that runs ten thousand times a day silently. Treat them like prompts you actually edit.
What a Tool Definition Actually Is
Strip away the framework jargon. A tool definition is three things the model sees before it decides to call:
- A name โ a short identifier the model uses to reference the tool.
- A description โ the natural-language explanation of what the tool does, when to use it, and (sometimes) when not to use it.
- A parameter schema โ a structured list of the fields the model must provide, with types, required/optional markers, and per-field descriptions.
Here is a tool definition in JSON Schema, the format every major 2026 platform accepts (Anthropic, OpenAI, Google, MCP):
{
"name": "lookup_account_status",
"description": "Retrieve current subscription status, plan, and billing state for a specific customer account by account ID. Use when the user asks 'is my account active?', 'what plan am I on?', or 'why was I billed $X?'. Do NOT use for general product information โ use search_knowledge_base for that.",
"parameters": {
"type": "object",
"properties": {
"account_id": {
"type": "string",
"description": "The customer account ID, format ACC-XXXXXX. Required."
},
"include_billing_history": {
"type": "boolean",
"description": "If true, returns last 12 billing events. Default false."
}
},
"required": ["account_id"]
}
}
That is the entire tool surface. The model sees only this โ not the implementation, not the API behind it. Everything that goes right or wrong in tool calling traces back to this definition.
JSON Schema Without Code
JSON Schema scares people who do not write code. It should not. It is a structured grammar for describing what fields a payload must contain.
- type โ what kind of value (string, number, boolean, array, object).
- description โ the per-field explanation the model reads to decide what to put there.
- required โ the list of fields that must always be filled. Optional fields can be omitted.
- enum โ a fixed list of allowed values. Use this whenever the legal values are a closed set.
- format โ a hint like "date-time", "email", "uri". The model usually respects these.
- properties โ the named fields inside an object.
You do not need to write JSON Schema by hand. Every major platform โ Lindy, Relevance AI, n8n, Zapier Agents, Copilot Studio, Agentforce โ ships a UI that emits the schema for you. But you must be able to read it, because the schema is where most tool-pick errors are seeded.
The Three Reasons Models Pick Wrong Tools
Almost every tool-pick error I have audited reduces to one of three causes. Memorize them.
Cause 1: Overlapping Descriptions
When two tools describe overlapping use cases, the model has no principled way to choose. It picks based on whatever shallow signal looks closest โ often the first sentence. search_knowledge_base and lookup_account_status both starting with "search for information about" is overlap. send_email and send_notification both saying "deliver a message" is overlap. The model will pick wrong roughly half the time.
Fix: Write tool descriptions that begin with what makes the tool distinct. The first sentence should make it impossible to mistake for any other tool. Use explicit "Do NOT use for X" clauses where two tools could be confused.
Cause 2: Missing or Ambiguous Required Fields
If the model needs to call create_ticket but the schema does not say what priority means, the model will hallucinate something plausible โ often a string like "medium" when the schema actually expected an integer. If the schema marks customer_id as required but the user's question does not contain a customer ID, the model will either invent one or refuse. Both are failures.
Fix: Every required field needs a description that tells the model where to get the value. "Required. Extract from the user's message; if not present, do not call this tool and instead ask a clarifying question." Use enum for closed-set fields. Use format for typed strings.
Cause 3: Ambiguous Names
Tool names are the first thing the model sees. A tool named get_data tells the model nothing. A tool named get_user_by_email tells the model exactly when to call it. In a 12-tool agent, the names alone often determine 60-70% of the tool-pick decision before the model even reads the descriptions.
Fix: Names should be verb_object at minimum. Better: verb_specificObject_byQualifier. list_overdue_invoices_by_customer beats get_invoices. schedule_meeting_with_calendar_check beats book.
The Tool-Call Dry-Run Worksheet
The single highest-leverage practice in agent building is the tool-call dry-run. Before deploying any agent, walk it through 8-12 representative user inputs on paper (or in a doc). For each input, predict:
- Which tool will the model call first?
- What arguments will it pass?
- What does the tool return?
- Will the model call a second tool? Which one?
If you cannot confidently predict the answer, the model probably cannot either, and that is a tool-pick error waiting to happen. Here is the worksheet template you can use immediately:
USER INPUT: [paste verbatim]
PREDICTED TOOL #1: [name]
PREDICTED ARGS: [field: value, field: value]
EXPECTED OUTPUT: [shape]
PREDICTED TOOL #2 (if any): [name]
RATIONALE: [one sentence why this tool over alternatives]
RISK: [low/medium/high; if high, what fix]
I have run this worksheet on dozens of pre-production agents. It catches roughly 80% of tool-pick errors in 30-60 minutes of work, before the agent goes anywhere near a customer. It is one of the highest-ROI activities in operator-builder practice.
A Dry-Run, Worked Out Loud
Take a fictional support agent with three tools: lookup_account_status, search_knowledge_base, create_support_ticket.
Input: "I was charged $89 but I think my plan is supposed to be $69. What's going on?"
Predicted Tool #1: lookup_account_status โ the user is asking about a specific billing event on their account, which the description explicitly cites.
Predicted Args: account_id (extracted from session context, not the user message), include_billing_history: true.
Risk: Medium. If the session does not have account_id in context, the model may either ask for it (good) or hallucinate one (bad). Mitigation: enforce session context injection at the platform level.
Predicted Tool #2: If the lookup reveals a plan-pricing mismatch, possibly create_support_ticket. If it reveals user-driven plan change, no second tool โ explain to user.
Now compare that prediction against actual agent behavior on the same input. Mismatches are bugs. This is your debugging method.
The Fewer, Better-Named Tools Principle
One of the most counterintuitive 2026 findings: adding tools makes agents worse. Each additional tool increases the model's decision space, the probability of overlap with an existing tool, and the per-call latency from the model evaluating which tool fits. Several teams have measured the trade and found a sharp drop in reliability past 8-10 tools per agent.
The principle: fewer, better-named, more clearly described tools beat more, vaguer tools every time. If you have 15 tools and three of them rarely fire, consider folding them into adjacent tools or removing them. If two tools are called in sequence 90% of the time, consider combining them into one composite tool.
The Tool Budget
Set a tool budget per agent. A reasonable 2026 starting budget: 5-8 tools for a fast-tier model agent, 8-12 for a mid-tier model agent. Beyond that, split the agent into a primary agent and one or more sub-agents that each have their own bounded tool surface. This is also a security win โ smaller tool surfaces are smaller attack surfaces.
Tool Results and How the Model Reads Them
Tool calling has a return half that operators often skip. After the tool runs, its output goes back to the model. How that output is shaped determines whether the model uses it correctly.
Two common pitfalls:
- Returning raw API responses โ if your tool returns a 4KB JSON blob with 38 fields, the model has to find the 2 fields that matter. It frequently picks wrong ones. Better: shape the response server-side to just the fields the model needs, with clear field names.
- Returning error codes without explanation โ "Error: 422" tells the model nothing. The model often retries with the same args. Return "Error: account_id format invalid; expected ACC-XXXXXX, got '[email protected]'." The model now knows what to fix.
The tool output is part of your prompt surface. Shape it.
Schemas That Fail Quietly
The reasoning-vs-tool-restraint finding from the previous lesson (arXiv 2602.00994) interacts dangerously with sloppy schemas. A reasoning-heavy model presented with an ambiguous schema will often fabricate a plausible argument rather than decline the call. The fabrication looks like a real call. The downstream API rejects it. The agent retries. Token budget spirals.
The defense is in the schema. For every field:
- Is the type the tightest possible? (Prefer enum over open string; prefer date over string; prefer integer over number.)
- Is the description specific about where the value comes from?
- Is the required/optional marker accurate?
- Are there examples in the description?
Schemas with examples in their descriptions outperform schemas without by a noticeable margin. The examples are 2-3 extra tokens per field that the model reads when deciding what to pass. Cheap insurance.
When Tools Overlap On Purpose
Sometimes two tools should overlap โ one is a precise tool and the other is a fallback. lookup_account_by_id is precise. search_accounts_by_name is fallback. The model should prefer the precise tool when the ID is known and fall back when only a name is available.
The way to encode this without confusing the model is in the descriptions themselves:
- lookup_account_by_id: "Preferred. Use this whenever you have the account ID. Never call this tool with a name; use search_accounts_by_name instead."
- search_accounts_by_name: "Fallback. Use only when lookup_account_by_id is not possible because the account ID is unknown."
The cross-references make the model's decision explicit. Without them, the model picks based on word overlap with the user message, which is unreliable.
Naming Conventions That Scale
Names are cheap to fix early and expensive to fix late. By the time an agent has been in production for six months with five integrations referencing tool names, renaming becomes coordinated migration work. So set naming conventions on day one. Three patterns that have held up across dozens of production agent deployments:
- verb_object_byQualifier โ the gold standard. get_account_by_id, search_accounts_by_name, list_invoices_by_customer. Each name reveals what the tool does, what it operates on, and how the caller addresses it.
- action_noun_specificity โ for create/update/delete operations. create_support_ticket, update_invoice_due_date, delete_user_session. Avoid generic verbs like do, handle, process.
- service_object_action โ when integrating multiple services with overlapping concepts. salesforce_account_lookup, hubspot_account_lookup. The service prefix disambiguates two CRMs at once, which matters when an agent is reading from both.
One under-appreciated 2026 finding: naming consistency across an agent's tool surface matters as much as naming quality of individual tools. If five tools follow verb_object_byQualifier and one follows get_data, the model treats the inconsistent tool as suspicious and avoids it. Consistency is a signal.
Description Structure That Actually Works
The descriptions in the example earlier in this lesson were not just full sentences strung together. They followed a structure that emerged from auditing what works:
- First sentence: what the tool does, in one specific phrase. Not "search for information" but "Retrieve current subscription status, plan, and billing state for a specific customer account by account ID." Specific. Concrete. Distinct.
- Trigger phrases: 2-4 example user phrasings that should cause the tool to fire. "Use when the user asks 'is my account active?', 'what plan am I on?', or 'why was I billed $X?'." This is where descriptions earn their tokens.
- Do-not-use clause: explicit guidance against confusable tools. "Do NOT use for general product information โ use search_knowledge_base for that." Cross-references are the highest-leverage disambiguation move available.
- Parameter notes: any special instructions about parameters that do not belong in field-level descriptions. Rarely needed but useful for cross-field invariants.
This structure is cheap to apply and dramatically improves tool-pick accuracy. Treat it as your description template.
Testing a Tool Surface
The minimum viable tool-surface test, runnable today on any platform:
- List your agent's tools.
- For each tool, write 3 user inputs that should call it and 3 that should NOT.
- Run the agent against all inputs (3 ร N positive + 3 ร N negative).
- Measure: did the right tool get called? Were the args correct?
- Pass criteria: 95%+ on positive, 90%+ on negative (correct refusal or alternative tool).
This costs 1-2 hours per agent. It catches tool-pick errors that integration tests will miss. Once the tool surface is stable, automate the test in your evals harness (Vellum, LangSmith, Braintrust).
Key Takeaways
- By 2026, 60-75% of agent incidents trace to tool-pick errors, not model errors.
- A tool definition is three things: name, description, parameter schema. The model sees nothing else.
- Three causes of tool-pick errors dominate: overlapping descriptions, missing or ambiguous required fields, ambiguous names.
- The tool-call dry-run worksheet catches roughly 80% of tool-pick errors in 30-60 minutes before deploy.
- Fewer, better-named tools beat more vague tools. Set a tool budget: 5-8 for fast tier, 8-12 for mid tier.
- Shape tool outputs: clean responses with descriptive errors outperform raw API dumps.
- Reasoning models with sloppy schemas hallucinate plausible arguments. Tighten the schema, do not blame the model.
- Use explicit "preferred" and "fallback" cross-references in descriptions when tools must overlap.
- The minimum viable tool-surface test (3 positive + 3 negative per tool) catches most tool-pick regressions in 1-2 hours.
Skill.re