Session 4. Bounded tools — Thu 17 Sep

What "contract" means, in plain words

Today you hear the word contract many times. This page says what it means, with no jargon.

The short version

A contract is the written promise a tool makes:

The model reads only that promise. It never reads your Python. So the promise has to be exact, and your code has to keep it.

A tool is a function with a promise written on it. The model reads the promise; your code keeps it.

The four parts of a contract

Part The question it answers Example: convert_currency
Inputs What may I pass? amount: a positive number. source and target: three uppercase letters
Output What do I get back? 100 USD = 86.66 EUR (rate 0.8666)
Limits How much, and where? One host only: api.frankfurter.dev
Refusals What happens when I break the rules? -5 is refused. usd is refused. XYZ is refused with the list of currencies that do exist

Why "contract", and not just "function"

A normal function trusts whoever calls it, because a programmer wrote the call.

A tool is called by a model, and a model guesses:

So the tool checks its contract itself, on every call:

A refusal like unknown tag leaves the model guessing again. A refusal like unknown tag 'nonsense'; valid tags: ['agents', 'mcp', ...] lets it correct itself on the next call.

Today's example: four clauses

Challenge ch04-e1 is a contract with four clauses. Two of them are refusals.

Call Must do
list_documents() return every document id
list_documents(tag="retrieval") return only the documents with that tag
list_documents(tag="nonsense") refuse, and name the valid tags
list_documents(tag="") refuse: an empty tag is not "no tag"

The check turns green only when the tool keeps all four promises.

The contract has two halves

Half Who reads it Where it lives
The description the model the tool's name, description and input schema
The enforcement nobody. It just runs the checks at the top of your function

If the description promises something the code does not check, the model trusts a promise nobody keeps. If the code refuses something the description never mentioned, the model cannot learn why it keeps failing. Write both, and make them say the same thing.

Where to go next