Every agent tool call is a small contract: a name, an input schema, an output schema, and a promise about what happens when the host cannot honour it. A model has none of those things. It has weights, a runtime, and a shape of conversation.
tool-mode exists in the gap between the two. Models are mounted as packages that declare capabilities once; the registry turns each capability into a named tool the agent can plan against.
The contract is the boundary
When the agent asks for lang_detect, it is not asking for Tongue. It is asking for the capability — and the deployment decides which package implements it today.
A schema is a promise the host can check before the model is ever loaded.
That indirection is what makes a swap cheap. A better language model next quarter costs a package upgrade, not a rewrite of every agent that already calls the tool.
What a receipt contains
- Which implementation ran, and which model it resolved to.
- The argument and result shape — never the payload itself.
- Whether the call fell back, and the exact reason if it did not run.