validateToolCalls function
Checks each call's arguments against its function's JSON Schema.
Returns human-readable errors, empty when everything fits. Recursive: nested objects, arrays of objects and enums are all checked, because the measured structural reliability (42 of 42 schema-valid extractions over three levels of nesting) is only meaningful if the check goes that deep.
This is a deliberate subset of JSON Schema — type, required, enum,
properties, items, additionalProperties: false. It exists to catch a
model that misread a schema, not to be a conformant validator. A keyword it
does not know is ignored rather than treated as a failure: rejecting a valid
call is worse here than passing an unusual one through.
Implementation
List<String> validateToolCalls(
List<ToolCall> calls,
List<FunctionTool> functions,
) {
final byName = {for (final f in functions) f.name: f};
final errors = <String>[];
for (final call in calls) {
final fn = byName[call.name];
if (fn == null) {
errors.add('unknown function "${call.name}"');
continue;
}
errors.addAll(
_walk(call.arguments, fn.parameters).map((e) => '${fn.name}: $e'),
);
}
return errors;
}