diff --git a/spring-ai-model/src/main/java/org/springframework/ai/tool/augment/ToolInputSchemaAugmenter.java b/spring-ai-model/src/main/java/org/springframework/ai/tool/augment/ToolInputSchemaAugmenter.java index 2cd91fff3f..0965207c63 100644 --- a/spring-ai-model/src/main/java/org/springframework/ai/tool/augment/ToolInputSchemaAugmenter.java +++ b/spring-ai-model/src/main/java/org/springframework/ai/tool/augment/ToolInputSchemaAugmenter.java @@ -43,7 +43,8 @@ private ToolInputSchemaAugmenter() { /** * Extracts the tool argument types from a record class annotated with * {@link ToolParam}. It retrieves the field names, types, descriptions, and required - * status from the record components. + * status from the record components. Components are required by default and have no + * description unless specified with {@link ToolParam}. * @param recordClass The record class to extract argument types from. * @return A list of {@link AugmentedArgumentType} representing the tool input * argument types. @@ -64,8 +65,7 @@ public static List toAugmentedArgument } return new AugmentedArgumentType(c.getName(), c.getGenericType(), - toolParam != null ? toolParam.description() : "no description", - toolParam != null ? toolParam.required() : false); + toolParam != null ? toolParam.description() : "", toolParam == null || toolParam.required()); }).toList(); } diff --git a/spring-ai-model/src/test/java/org/springframework/ai/tool/augment/ToolInputSchemaAugmenterTest.java b/spring-ai-model/src/test/java/org/springframework/ai/tool/augment/ToolInputSchemaAugmenterTest.java index f151901dcf..04aac81792 100644 --- a/spring-ai-model/src/test/java/org/springframework/ai/tool/augment/ToolInputSchemaAugmenterTest.java +++ b/spring-ai-model/src/test/java/org/springframework/ai/tool/augment/ToolInputSchemaAugmenterTest.java @@ -25,6 +25,7 @@ import org.junit.jupiter.api.Test; import org.springframework.ai.tool.annotation.ToolParam; +import org.springframework.ai.util.json.schema.JsonSchemaGenerator; import org.springframework.ai.tool.augment.ToolInputSchemaAugmenter.AugmentedArgumentType; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -60,6 +61,25 @@ public record MixedAnnotationsRecord(@ToolParam(description = "Annotated field", String notAnnotated) { } + public record DefaultPolicyRecord(String plain, @ToolParam(description = "Annotated field") String annotated, + @ToolParam(required = false) String optional) { + } + + @Test + void generatedAndAugmentedSchemasUseTheSameDefaults() { + JsonMapper mapper = new JsonMapper(); + JsonNode generated = mapper.readTree(JsonSchemaGenerator.generateForType(DefaultPolicyRecord.class)); + JsonNode augmented = mapper.readTree(ToolInputSchemaAugmenter.augmentToolInputSchema("{}", + ToolInputSchemaAugmenter.toAugmentedArgumentTypes(DefaultPolicyRecord.class))); + + for (String field : List.of("plain", "annotated", "optional")) { + assertEquals(generated.path("properties").path(field).get("description"), + augmented.path("properties").path(field).get("description")); + assertEquals(generated.path("required").valueStream().anyMatch(node -> field.equals(node.asString())), + augmented.path("required").valueStream().anyMatch(node -> field.equals(node.asString()))); + } + } + @Nested @DisplayName("AugmentedArgumentType Tests") class AugmentedArgumentTypeTests { @@ -150,8 +170,8 @@ void shouldHandleRecordWithoutAnnotations() { assertEquals(2, argumentTypes.size()); for (AugmentedArgumentType argType : argumentTypes) { - assertEquals("no description", argType.description()); - assertFalse(argType.required()); + assertEquals("", argType.description()); + assertTrue(argType.required()); } } @@ -174,8 +194,8 @@ void shouldHandleMixedAnnotationsRecord() { .filter(arg -> "notAnnotated".equals(arg.name())) .findFirst() .orElseThrow(); - assertEquals("no description", notAnnotatedArg.description()); - assertFalse(notAnnotatedArg.required()); + assertEquals("", notAnnotatedArg.description()); + assertTrue(notAnnotatedArg.required()); } @Test