The tool in part 2 took no arguments. Now it does. And it does not trust what it gets.
The schema
inputSchema: const {
'type': 'object',
'properties': {
'count': {'type': 'integer', 'description': 'How many to admit, 1 or more'},
},
'required': ['count'],
},
With this the caller knows what to send. A model shapes its arguments to it.
But a schema is not a guarantee
Writing 'type': 'integer' does not make an integer arrive. A schema is guidance to the caller, and the caller may not follow it, or may not be able to.
So the handler looks again.
handler: (args) async {
final n = args['count'];
// The schema says integer; the caller may still send anything.
if (n is! int || n < 1) {
return CallToolResult(
content: [TextContent(text: 'desk.admit: count must be 1 or more')],
isError: true,
);
}
// And the desk cannot admit people who are not there.
if (n > waiting) {
return CallToolResult(
content: [TextContent(text: 'only $waiting waiting')],
isError: true,
);
}
waiting -= n;
return CallToolResult(
content: [TextContent(text: jsonEncode({'waiting': waiting}))],
);
},
The two refusals differ in kind
There are two checks, for different reasons.
n < 1 — the value itself makes no sense. Admitting zero people is always wrong. A problem with the input.
n > waiting — the value is fine but impossible right now. You cannot admit 99 from a queue of 3. With 100 waiting, 99 is normal. A problem with the state.
The distinction matters because of the message.
count must be 1 or more ← sending it again is wrong the same way
only 3 waiting ← send 3 or fewer and it works
Collapse both into isError: true and the caller cannot tell whether to retry or give up.
This content requires Developer or above
Sign in and upgrade your plan to continue reading.
View Plans