Agents, MCP and skillsLoading progress…

Tools as contracts

Trace a model-requested tool call through schema validation, execution and a returned observation.

A tool is a contract

A tool is a function the application offers to the model. The model never sees your code. It sees a name, a description and an input schema, and it decides when to ask for a call. Everything else (what the tool really does, which arguments are acceptable, what happens on failure) is enforced by your code, the host. A good contract states the purpose, the inputs, the outputs and the errors, and stays narrow: get_weather(city, unit) is easy to validate, while run(anything) is not.

The model sees only a tool's name, description and schema. The host decides what the schema allows and checks every call against it before running anything.

call: get_weather({"town":"Oslo"}) validator: missing:city, unexpected:town host: REJECT. Return the problems to the model as an error; nothing is executed

A narrow contract (one city, two units) is easy to validate and to evaluate. An execute-anything tool such as run(command) has no useful schema: almost every string would be "valid".

Toggle the rules and see which calls the validator accepts.

Predict first. Is a descriptive tool name sufficient to validate arguments?

Chapter context

A tool call is a structured request for the application to perform an operation. The model proposes arguments; the surrounding application decides whether the operation is valid and permitted and is responsible for executing it.

Chapter reference: math, worked example & code

This section belongs to the whole chapter, so it is the same on every lesson in it and may cover a different lesson's topic. The code for the experiment you just ran is inside the experiment itself.

Math and notation

A useful execution model is: requested operation + validated arguments + permission decision → execution result. Schema validation establishes a data-shape contract; authorization establishes whether this caller may perform this operation. Neither implies the other.

Worked example

A calculator tool requires numeric a and b and returns a+b. For a=2,b=3, its result is 5. If the request instead asks for an unknown field or omits b, reject or repair the request according to the contract before executing. A retry of this pure calculation is harmless; that does not establish the same property for a side-effecting tool.

Reference code

The following example uses the Python standard library and does not call a remote service.

def add(a,b):
    if type(a) not in (int,float) or type(b) not in (int,float):
        raise ValueError('numeric inputs required')
    return a+b
assert add(2,3) == 5
try:
    add('2',3)
except ValueError:
    pass
else:
    raise AssertionError('invalid input accepted')

Python examples are provided for study and local execution; this page does not execute Python.

Common mistakes

A model proposal is not permission. JSON schema shape validation is not business-rule validation. Tool outputs must not silently become trusted instructions.