Every tool-using system rests on one fact that is easy to forget once the wiring works: the model never runs anything. Claude Opus 5 (`claude-opus-5`) can decide that a database needs querying or a flight needs looking up, and it can describe exactly how it wants that done, but the query itself, the HTTP request, the disk read -- all of that happens in your process, in code you wrote, under permissions you granted. The function calling contract is the agreement that makes this division workable: you promise the model a name, a description, and a parameter schema for each capability you're willing to expose, and the model promises to emit calls that conform to that schema, or to not call at all when nothing fits.
Calling it a contract rather than an "interface" or a "function signature" is deliberate. A contract has two parties, each with obligations, and it can be broken from either side. Your side breaks when the schema you publish doesn't match what your handler actually expects -- a field marked optional that your code treats as required, a type your validator never checks. The model's side breaks when it emits a call that doesn't conform: a required field left out, a string where an integer belongs, a tool name that was never declared. Almost every production bug in a tool-using system is one of these two failures, and naming the contract explicitly is what makes it possible to ask, when something goes wrong, which side broke it.
This lesson stays entirely at the level of the contract itself: what each party promises, how a single exchange is structured across a conversation's history, and how to handle the moment either party fails to hold up its end. Later lessons in this course cover the anatomy of a tool declaration, JSON Schema for parameters, and the full request-execute-return lifecycle in depth. Here, the goal is to fix the mental model before any of the syntax: two parties, two promises, one shared history that has to stay internally consistent.