Read the registry, what the model gets back on a bad call
RolesAgent Systems EngineeringDeveloper Experience and Education
The question
A tool is registered with this schema, and the model sends the four argument sets below. For each one, say what the registry returns and why the shape of the answer matters to the model.
registry.register(
name="db.get_user",
schema={
"type": "object",
"required": ["id"],
"properties": {
"id": {"type": "integer"},
"fields": {"type": "array", "items": {"type": "string", "enum": ["id", "name", "email"]}},
},
},
handler=get_user,
)
cases = [
{"id": 42, "fields": ["id", "name"]},
{"id": "forty-two"},
{"fields": ["id"]},
{"id": 1, "fields": ["id", "phone"]},
]Answer it first, aloud or on paper. Then open the answer.
The answer
Show short answer
The first case passes validation and returns an Ok result. The second returns one error at /id with keyword type, because a string is not an integer and the validator never coerces. The third returns one error at /id with keyword required, because the property is missing. The fourth returns one error at /fields/1 with keyword enum, because phone is not an allowed value, and the path points at the exact element so the model can fix that one value in the next call.
Show full answer
The walk
The validator dispatches on type. For an object it checks required first, then walks each property that has a schema. For an array it walks each element with the items schema and appends the index to the path. A type mismatch stops the walk at that node and reports one error, so a wrong type does not produce a cascade of nested errors underneath it.
| Case | Result | Path | Keyword |
|---|---|---|---|
{"id": 42, "fields": ["id", "name"]} | Ok | ||
{"id": "forty-two"} | one error | /id | type |
{"fields": ["id"]} | one error | /id | required |
{"id": 1, "fields": ["id", "phone"]} | one error | /fields/1 | enum |
Why the path is the product
The model reads a pointer better than a sentence. An error that says the email field expected a string, with the path /user/email, is fixed in one round trip. A prose message that says the arguments were invalid costs a turn of guessing. Paths follow the JSON pointer form: slash-separated property names and array indices, with ~ and / escaped inside a segment.
What the validator refuses to do
- It does not coerce. The string
"42"fails an integer or number schema. A model that learns that strings are accepted sends strings everywhere. - It does not call the handler. The schema is data and the handler is code, and mixing them puts validation inside handlers where it drifts.
- It is not a security boundary. A handler can misbehave after validation passes. The dispatcher adds timeouts and sandboxing. The registry adds shape.
Registration hygiene
register rejects a name that is already in the table unless the caller passes override=True. Two parts of a codebase registering the same name is a bug that takes a week to find in production, so the default is to raise.
Follow-ups
L2WorkingThe model sends
{"id": true}. What happens?Show expected answer
a type error at
/id, because the validator treats a boolean as not an integer even though the language would accept it.L2WorkingWhy does a type mismatch stop the walk at that node?
Show expected answer
the children have no meaning when the parent is the wrong type, and one clear error beats a list of errors caused by the same mistake.
L3SeniorThe schema uses
oneOf. What doesregisterdo?Show expected answer
it raises, because the registry supports eight keywords and rejects anything outside the subset at registration time.
L3SeniorThe catalog passes fifty tools and schemas start to repeat. What two extensions do you add first?
Show expected answer
$refagainst a local definitions block, andadditionalProperties: falsefor a strict shape.
Wrong answers
Show the wrong answers that interviewers hear
“Return one message that says invalid arguments and let the model retry.”
A retry without a path is a guess, and a path fixes the call in one round trip.
“Coerce the string to a number, because the intent is clear.”
Coercion teaches the model that the schema is advice, and the next call sends a string where no coercion exists.
“Validation makes the tool safe to call.”
Validation checks shape, and the handler can still misbehave, so timeouts and sandboxing belong in the dispatcher.
Taught in
The tool registry lesson builds the registry, the eight-keyword validator and the pointer paths.