Tool Calling with Spring AI: Building Intelligent Applications
Tool calling is one of the most powerful features in Spring AI, enabling LLM-powered applications to dynamically execute functions and interact with external services. Unlike traditional APIs that require manual integration, tool calling allows your AI model to decide when and how to use available tools to accomplish user tasks.
What is Tool Calling?
Tool calling (also known as function calling) is a mechanism where an LLM can request to execute specific functions based on user input. Instead of just generating text responses, the model can:
- Analyze user requests to determine which tools are needed
- Generate function calls with appropriate parameters
- Execute those functions through your application
- Process results and provide intelligent responses
This creates a feedback loop where the AI becomes an orchestrator rather than just a responder.
Setting Up Spring AI for Tool Calling
First, let's configure Spring AI with tool calling capabilities:
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SpringAIConfig {
@Bean
public ChatClient chatClient(ChatModel chatModel) {
return ChatClient.builder(chatModel)
.build();
}
}
Defining Tools
Tools are simple Java methods annotated with Spring AI's tool-calling decorators. Here's a complete example of a weather tool:
import org.springframework.stereotype.Component;
import java.util.function.Function;
@Component
public class WeatherTools {
public static class GetWeatherRequest {
public String location;
public String unit; // celsius or fahrenheit
}
public static class WeatherResponse {
public String location;
public double temperature;
public String condition;
public String unit;
}
public Function<GetWeatherRequest, WeatherResponse> getWeatherTool() {
return request -> {
// In production, call actual weather API
WeatherResponse response = new WeatherResponse();
response.location = request.location;
response.temperature = 72.5;
response.condition = "Sunny";
response.unit = request.unit;
return response;
};
}
}
Registering Tools with ChatClient
Integrate your tools with the ChatClient:
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.stereotype.Service;
@Service
public class WeatherAssistant {
private final ChatClient chatClient;
private final WeatherTools weatherTools;
public WeatherAssistant(ChatClient chatClient, WeatherTools weatherTools) {
this.chatClient = chatClient;
this.weatherTools = weatherTools;
}
public String getWeatherInsights(String userQuery) {
return this.chatClient
.prompt()
.user(userQuery)
.functions("getWeatherTool", weatherTools.getWeatherTool())
.call()
.content();
}
}
Advanced: Multiple Tool Handling
For applications requiring multiple tools, create a tool registry:
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
@Component
public class ToolRegistry {
private final Map<String, Function<?, ?>> tools = new HashMap<>();
public ToolRegistry(WeatherTools weatherTools,
CalculatorTools calculatorTools,
DatabaseTools databaseTools) {
registerTool("getWeather", weatherTools.getWeatherTool());
registerTool("calculate", calculatorTools.calculateTool());
registerTool("queryDatabase", databaseTools.queryTool());
}
public void registerTool(String name, Function<?, ?> function) {
tools.put(name, function);
}
public Map<String, Function<?, ?>> getTools() {
return tools;
}
}
Real-World Example: Intelligent Data Assistant
Here's a production-ready example combining multiple tools:
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.stereotype.Service;
import java.util.Map;
import java.util.function.Function;
@Service
public class IntelligentAssistant {
private final ChatClient chatClient;
private final ToolRegistry toolRegistry;
public IntelligentAssistant(ChatClient chatClient, ToolRegistry toolRegistry) {
this.chatClient = chatClient;
this.toolRegistry = toolRegistry;
}
public String processUserRequest(String userRequest) {
Map<String, Function<?, ?>> availableTools = toolRegistry.getTools();
return this.chatClient
.prompt()
.user(userRequest)
.functions(availableTools)
.call()
.content();
}
}
Best Practices for Tool Calling
- Clear Tool Descriptions: Document your tools thoroughly so the LLM understands when to use them
- Precise Parameter Types: Use strongly-typed request/response objects
- Error Handling: Implement graceful fallbacks when tools fail
- Rate Limiting: Add safeguards to prevent excessive tool calls
- Logging & Monitoring: Track which tools are being called and their outcomes
Security Considerations
Tool calling grants AI models the ability to execute functions. Protect your application:
@Component
public class SecureToolFactory {
public Function<?, ?> createSecureTool(Function<?, ?> tool) {
return new Function<Object, Object>() {
@Override
public Object apply(Object input) {
// Validate input before execution
if (!isValidInput(input)) {
throw new IllegalArgumentException("Invalid tool input");
}
// Execute with audit logging
auditLog("Tool executed with input: " + input);
return tool.apply(input);
}
private boolean isValidInput(Object input) {
return input != null && isExpectedType(input);
}
};
}
private void auditLog(String message) {
// Log all tool invocations for security audit
}
}
Why Tool Calling Matters
Tool calling transforms Spring AI from a text-generation engine into a true AI agent framework. Your application can:
- Automate workflows by having AI decide which operations to execute
- Integrate with external systems seamlessly
- Build intelligent agents that improve through feedback loops
- Reduce latency by batching multiple tool calls
- Enhance accuracy by grounding responses in real data
Conclusion
Tool calling in Spring AI is the bridge between static LLM responses and dynamic, interactive AI applications. By mastering this pattern, you unlock the full potential of AI-driven development.
Start simple with a single tool, validate your approach, then scale to more complex multi-tool orchestrations. The framework handles the heavy lifting—you focus on defining what your AI can do.
Top comments (0)