amount=15 for a fifteen-dollar refund is tuning the wrong variable.
Three mechanisms sit between a model and a wrong call, and they are not equally
strong. Reach for them in this order.
1. A constraint, because it is checked
Anything expressible as a bound belongs in the schema, where it is enforced rather than suggested.ge, le, pattern, an enum, a required field — all of
it is checked before the request is
built, so a wrong value never reaches
the network and never spends a round trip.
ConflictsWith covers the rule APIs state in
prose and answer with a 400. Google Calendar’s events.list refuses syncToken
beside eight other parameters, because an incremental sync continues the query
its token came from. Declared on the field, that fact travels with the field
instead of living in a validator’s list that the next edit forgets to update.
2. A gloss, for what no constraint can express
Some mistakes are valid. Stripe’sPOST /v1/refunds documents amount as “a
positive integer in the smallest currency unit”, which is correct and complete.
A model reading 15.00 off a spreadsheet sent amount=15 and refunded fifteen
cents. Nothing rejects that — the units are the caller’s to get right, the
request is well-formed, and the API answers 200.
No constraint catches it. Gloss is the sentence
that does:
gloss.py
3. A rejection the model can act on
The third case is the mistake you did not anticipate. Here the goal is not to prevent the call but to make the failure cost one turn instead of three. Two things the runtime does without being asked. Mistakes that are unambiguous are absorbed rather than bounced — a nested object serialised as a JSON string is parsed, anddateTime, DateTime and date_time are all declared aliases for the same
field, so a model matching the API’s own docs is not punished for it. Mistakes
that are real are refused with a message
written to be handed back verbatim,
naming the field and what it wanted.
An argument the schema does not declare is refused rather than dropped, which is
the deliberate exception. Silently discarding it would produce a successful call
that did not do what was asked — the one failure mode an agent cannot recover
from, because nothing tells it anything went wrong.
What it was worth
Tool errors per run, from the measured results:Related
- LLM input auto-corrections — the three mistakes absorbed, and the one refused
- Tool validation and error handling — where validation runs and how to catch it
- Markers —
Gloss,ConflictsWith, and the rest of the declarative vocabulary - Latency — why the retry loop is usually the wall-clock story