fix(agents): harden Cloud Code Assist compatibility

- Expand schema scrubber to strip additional constraint keywords rejected
  by Cloud Code Assist (examples, minLength, maxLength, minimum, maximum,
  multipleOf, pattern, format, minItems, maxItems, uniqueItems,
  minProperties, maxProperties)
- Extend tool call ID sanitization to cover toolUse and toolCall block
  types (previously only functionCall was sanitized)
- Update pi-tools test to include 'examples' in unsupported keywords

Fixes 400 errors when using google-antigravity/claude-opus-4-5-thinking:
- tools.N.custom.input_schema: JSON schema is invalid
- messages.N.content.N.tool_use.id: String should match pattern
This commit is contained in:
Sebastian Barrios
2026-01-10 11:02:06 -05:00
committed by Peter Steinberger
parent ef08c3f038
commit 64babcac7a
3 changed files with 33 additions and 13 deletions

View File

@@ -10,6 +10,23 @@ const UNSUPPORTED_SCHEMA_KEYWORDS = new Set([
"$ref",
"$defs",
"definitions",
// Non-standard (OpenAPI) keyword; Claude validators reject it.
"examples",
// Cloud Code Assist appears to validate tool schemas more strictly/quirkily than
// draft 2020-12 in practice; these constraints frequently trigger 400s.
"minLength",
"maxLength",
"minimum",
"maximum",
"multipleOf",
"pattern",
"format",
"minItems",
"maxItems",
"uniqueItems",
"minProperties",
"maxProperties",
]);
// Check if an anyOf/oneOf array contains only literal values that can be flattened.
@@ -134,14 +151,14 @@ function cleanSchemaForGeminiWithDefs(
const result: Record<string, unknown> = {
...(cleaned as Record<string, unknown>),
};
for (const key of ["description", "title", "default", "examples"]) {
for (const key of ["description", "title", "default"]) {
if (key in obj && obj[key] !== undefined) result[key] = obj[key];
}
return result;
}
const result: Record<string, unknown> = {};
for (const key of ["description", "title", "default", "examples"]) {
for (const key of ["description", "title", "default"]) {
if (key in obj && obj[key] !== undefined) result[key] = obj[key];
}
return result;
@@ -157,7 +174,7 @@ function cleanSchemaForGeminiWithDefs(
type: flattened.type,
enum: flattened.enum,
};
for (const key of ["description", "title", "default", "examples"]) {
for (const key of ["description", "title", "default"]) {
if (key in obj && obj[key] !== undefined) result[key] = obj[key];
}
return result;
@@ -171,7 +188,7 @@ function cleanSchemaForGeminiWithDefs(
type: flattened.type,
enum: flattened.enum,
};
for (const key of ["description", "title", "default", "examples"]) {
for (const key of ["description", "title", "default"]) {
if (key in obj && obj[key] !== undefined) result[key] = obj[key];
}
return result;