diff --git a/auto-configurations/models/tool/spring-ai-autoconfigure-model-tool/src/test/java/org/springframework/ai/model/tool/autoconfigure/ToolCallingAutoConfigurationTests.java b/auto-configurations/models/tool/spring-ai-autoconfigure-model-tool/src/test/java/org/springframework/ai/model/tool/autoconfigure/ToolCallingAutoConfigurationTests.java index 497c3e7870..9bbcf9f3f6 100644 --- a/auto-configurations/models/tool/spring-ai-autoconfigure-model-tool/src/test/java/org/springframework/ai/model/tool/autoconfigure/ToolCallingAutoConfigurationTests.java +++ b/auto-configurations/models/tool/spring-ai-autoconfigure-model-tool/src/test/java/org/springframework/ai/model/tool/autoconfigure/ToolCallingAutoConfigurationTests.java @@ -99,6 +99,18 @@ void resolveMultipleFunctionAndToolCallbacks() { }); } + @Test + void resolveMissingToolCallbacks() { + new ApplicationContextRunner().withConfiguration(AutoConfigurations.of(ToolCallingAutoConfiguration.class)) + .withUserConfiguration(Config.class) + .run(context -> { + var toolCallbackResolver = context.getBean(ToolCallbackResolver.class); + assertThat(toolCallbackResolver).isInstanceOf(DelegatingToolCallbackResolver.class); + + assertThat(toolCallbackResolver.resolve("NonExisting")).isNull(); + }); + } + static class WeatherService { @Tool(description = "Get the weather in location. Return temperature in 36°F or 36°C format.") diff --git a/spring-ai-model/src/main/java/org/springframework/ai/tool/resolution/SpringBeanToolCallbackResolver.java b/spring-ai-model/src/main/java/org/springframework/ai/tool/resolution/SpringBeanToolCallbackResolver.java index 7f9bf83e96..945300a60a 100644 --- a/spring-ai-model/src/main/java/org/springframework/ai/tool/resolution/SpringBeanToolCallbackResolver.java +++ b/spring-ai-model/src/main/java/org/springframework/ai/tool/resolution/SpringBeanToolCallbackResolver.java @@ -88,18 +88,24 @@ public ToolCallback resolve(String toolName) { return resolvedToolCallback; } - ResolvableType toolType = TypeResolverHelper.resolveBeanType(this.applicationContext, toolName); - ResolvableType toolInputType = (ResolvableType.forType(Supplier.class).isAssignableFrom(toolType)) - ? ResolvableType.forType(Void.class) : TypeResolverHelper.getFunctionArgumentType(toolType, 0); + try { + ResolvableType toolType = TypeResolverHelper.resolveBeanType(this.applicationContext, toolName); + ResolvableType toolInputType = (ResolvableType.forType(Supplier.class).isAssignableFrom(toolType)) + ? ResolvableType.forType(Void.class) : TypeResolverHelper.getFunctionArgumentType(toolType, 0); - String toolDescription = resolveToolDescription(toolName, toolInputType.toClass()); - Object bean = this.applicationContext.getBean(toolName); + String toolDescription = resolveToolDescription(toolName, toolInputType.toClass()); + Object bean = this.applicationContext.getBean(toolName); - resolvedToolCallback = buildToolCallback(toolName, toolType, toolInputType, toolDescription, bean); + resolvedToolCallback = buildToolCallback(toolName, toolType, toolInputType, toolDescription, bean); - toolCallbacksCache.put(toolName, resolvedToolCallback); + toolCallbacksCache.put(toolName, resolvedToolCallback); - return resolvedToolCallback; + return resolvedToolCallback; + } + catch (Exception e) { + logger.debug("ToolCallback resolution failed from Spring application context", e); + return null; + } } public SchemaType getSchemaType() {