Skip to content

Commit c891e1c

Browse files
committed
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 <[email protected]>
1 parent 10ff11d commit c891e1c

File tree

2 files changed

+26
-8
lines changed

2 files changed

+26
-8
lines changed

auto-configurations/models/tool/spring-ai-autoconfigure-model-tool/src/test/java/org/springframework/ai/model/tool/autoconfigure/ToolCallingAutoConfigurationTests.java

+12
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,18 @@ void resolveMultipleFunctionAndToolCallbacks() {
9999
});
100100
}
101101

102+
@Test
103+
void resolveMissingToolCallbacks() {
104+
new ApplicationContextRunner().withConfiguration(AutoConfigurations.of(ToolCallingAutoConfiguration.class))
105+
.withUserConfiguration(Config.class)
106+
.run(context -> {
107+
var toolCallbackResolver = context.getBean(ToolCallbackResolver.class);
108+
assertThat(toolCallbackResolver).isInstanceOf(DelegatingToolCallbackResolver.class);
109+
110+
assertThat(toolCallbackResolver.resolve("NonExisting")).isNull();
111+
});
112+
}
113+
102114
static class WeatherService {
103115

104116
@Tool(description = "Get the weather in location. Return temperature in 36°F or 36°C format.")

spring-ai-model/src/main/java/org/springframework/ai/tool/resolution/SpringBeanToolCallbackResolver.java

+14-8
Original file line numberDiff line numberDiff line change
@@ -88,18 +88,24 @@ public ToolCallback resolve(String toolName) {
8888
return resolvedToolCallback;
8989
}
9090

91-
ResolvableType toolType = TypeResolverHelper.resolveBeanType(this.applicationContext, toolName);
92-
ResolvableType toolInputType = (ResolvableType.forType(Supplier.class).isAssignableFrom(toolType))
93-
? ResolvableType.forType(Void.class) : TypeResolverHelper.getFunctionArgumentType(toolType, 0);
91+
try {
92+
ResolvableType toolType = TypeResolverHelper.resolveBeanType(this.applicationContext, toolName);
93+
ResolvableType toolInputType = (ResolvableType.forType(Supplier.class).isAssignableFrom(toolType))
94+
? ResolvableType.forType(Void.class) : TypeResolverHelper.getFunctionArgumentType(toolType, 0);
9495

95-
String toolDescription = resolveToolDescription(toolName, toolInputType.toClass());
96-
Object bean = this.applicationContext.getBean(toolName);
96+
String toolDescription = resolveToolDescription(toolName, toolInputType.toClass());
97+
Object bean = this.applicationContext.getBean(toolName);
9798

98-
resolvedToolCallback = buildToolCallback(toolName, toolType, toolInputType, toolDescription, bean);
99+
resolvedToolCallback = buildToolCallback(toolName, toolType, toolInputType, toolDescription, bean);
99100

100-
toolCallbacksCache.put(toolName, resolvedToolCallback);
101+
toolCallbacksCache.put(toolName, resolvedToolCallback);
101102

102-
return resolvedToolCallback;
103+
return resolvedToolCallback;
104+
}
105+
catch (Exception e) {
106+
logger.debug("ToolCallback resolution failed from Spring application context", e);
107+
return null;
108+
}
103109
}
104110

105111
public SchemaType getSchemaType() {

0 commit comments

Comments
 (0)