Function calling / tool use
How the model actually 'uses' a tool: it doesn't — it proposes a JSON call, the harness executes it. Plus the three classic ways it goes wrong.
The phrase “the model calls a function” is a little lie. The model never calls anything — it has no hands. What it does is emit text that happens to be a well-formed function call. The harness runs it.
The protocol in three steps
- The harness advertises tools — names, descriptions and argument schemas — in the prompt, alongside the conversation.
- The model proposes a call — instead of a plain answer, it outputs structured JSON: which tool, with which arguments.
- The harness executes it and feeds the result back into the conversation, where the model reasons on.
A real call looks like this:
{
"name": "calculator",
"arguments": { "expression": "2 ** 100" }
}
The model “knows” it should use calculator because the harness told it: “calculator — evaluates a mathematical expression. Use it instead of doing the math in your head.” That one sentence is doing more work than you’d think.
The three classic failure modes
| Failure | What the model does | Why it happens | Fix |
|---|---|---|---|
| 🎯 Wrong tool | Calls the wrong function | Two tools with overlapping descriptions | Sharper, contrasting descriptions |
| 🧩 Wrong arguments | Right tool, garbage args (typos, wrong units, missing fields) | The schema is loose or the input was ambiguous | Strict JSON schema + validation + one retry |
| ⏸️ Wrong timing | Keeps calling tools when it should answer — or answers when it should call | The model can’t always see the whole task | Clear “stop conditions” in the system prompt, step budgets |
Why MCP fits here
Function calling needs a channel: how do tool definitions get from one side to the other? Every vendor had its own wire format — the N×M integration mess. MCP is the shared plug: one tool server, many agents. The protocol above is the same; only the plumbing is standardized.