fix(tool): handle non-existing tool callbacks gracefully

- Add error handling to SpringBeanToolCallbackResolver to return null
  instead of throwing exceptions when resolving non-existing tools.
  This make is consitent with other tool resolver implementations
  and centralize the error handling in the tool calling manager.
- Add test to verify that the ToolCallbackResolver correctly
  returns null for non-existing tools.

Related to #2667

Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
This commit is contained in:
Christian Tzolov
2025-05-07 10:51:56 +02:00
committed by Ilayaperumal Gopinathan
parent e6fbc28a5b
commit e010899fbe
2 changed files with 26 additions and 8 deletions

View File

@@ -99,6 +99,18 @@ class ToolCallingAutoConfigurationTests {
});
}
@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.")

View File

@@ -88,18 +88,24 @@ public class SpringBeanToolCallbackResolver implements ToolCallbackResolver {
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() {