Spring AI - Tools, Function Calling & Agents
Description
Complete guide for implementing tools and function calling in Spring AI. Covers multiple tool definition patterns, tool execution strategies, error handling, and building autonomous agents with reasoning capabilities.
When to Use
- Enabling models to call functions/APIs
- Building autonomous AI agents
- Implementing tool-use patterns (ReAct)
- Multi-step reasoning with actions
- API integration with LLMs
- Custom command execution
- Workflow automation
- Decision support systems
Topics Covered
1. Tool Definition Patterns
@Tool Annotation (Simplest)
@Component
public class MathTools {
@Tool(description = "Calculates sum of two numbers")
public int add(int a, int b) {
return a + b;
}
}
Functional Interface (Spring 6)
@Configuration
public class ToolConfig {
@Bean
public java.util.function.Function<Request, Response> calculator() {
return request -> { /* implementation */ };
}
}
MethodToolCallback (Fine-grained)
var addTool = MethodToolCallback.builder()
.description("Add two numbers")
.method(calculator::add)
.inputType(AddRequest.class)
.build();
Dynamic Tool Definition
- Runtime tool registration
- Plugin architecture
- Tool marketplace integration
- User-defined tools
2. Tool Specification Formats
- OpenAI Function Calling: JSON Schema format
- Anthropic Tool Use: Tool definition with input schema
- Google Gemini Tools: Function declarations
- Bedrock Tools: Tool specifications
- Model-agnostic: Adapter pattern
3. Tool Execution Modes
Framework-Controlled Execution
chatClient.prompt()
.user("Search for Spring Boot docs")
.functions("searchWeb")
.call()
.content();
Advisor Pattern
- Tools automatically applied
- Middleware-style execution
- Configurable tool stack
- Error recovery
User-Controlled Execution
- Explicit function call detection
- Manual execution flow
- Fine-grained control
- Custom retry logic
4. Tool Response Handling
- Text responses: Direct content
- Structured responses: JSON objects
- Media responses: Images, files
- Error responses: Exception handling
- Streaming responses: Token-by-token
5. Tool Context & Metadata
- Tool execution context: Available context during execution
- Tool state: Maintaining state across calls
- Tool metadata: Versioning, dependencies
- Security context: Authorization, validation
- Tracing: Execution logging and debugging
6. Advanced Patterns
Tool Use Iterations (ReAct)
Thought → Action (Tool Call) → Observation → Repeat until Answer
Conditional Tool Chains
IF condition → Tool A → Tool B → Result
ELSE → Tool C → Result
Parallel Tool Execution
Execute Tool A, B, C in parallel → Aggregate results
Tool Exception Handling
- Graceful degradation
- Retry strategies
- Fallback tools
- Error reporting
Code Patterns
Basic Tool Definition
@Component
public class WeatherTool {
@Tool(description = "Get current weather for a location")
public String getWeather(
@Param(description = "City name") String city,
@Param(description = "Country code") String country) {
return "Sunny, 72°F in " + city;
}
}
Tool with ChatModel
@Service
public class AgentService {
@Autowired
private ChatModel chatModel;
@Autowired
private WeatherTool weatherTool;
public String runAgent(String query) {
var tools = List.of(
MethodToolCallback.builder()
.description("Get weather")
.method(weatherTool::getWeather)
.inputType(WeatherRequest.class)
.build()
);
Prompt prompt = new Prompt(
new UserMessage(query),
new ChatOptions() { }
);
ChatResponse response = chatModel.call(prompt);
return response.getResult().getOutput().getContent();
}
}
Tool Calling with ChatClient
String result = chatClient.prompt()
.user("What's the weather in San Francisco?")
.functions("getWeather", "getLocation")
.call()
.content();
ReAct Loop (Autonomous Agent)
public String reagentLoop(String question, int maxIterations) {
String currentThought = question;
for (int i = 0; i < maxIterations; i++) {
// LLM generates thought + action
var response = chatClient.prompt()
.user(currentThought)
.functions("tool1", "tool2", "tool3")
.call();
String content = response.getResult().getOutput().getContent();
// Check if we have final answer
if (content.contains("Final Answer:")) {
return content;
}
// Extract tool call and execute
var toolCall = parseToolCall(content);
var observation = executeTool(toolCall);
currentThought = "Observation: " + observation + "\nThink about next step";
}
return "Max iterations reached";
}
Streaming Function Calls
chatClient.prompt()
.user("Run analysis tools")
.stream()
.toolCall()
.subscribe(toolCall -> {
Object result = executeTool(toolCall);
logger.info("Tool {} returned: {}", toolCall.getName(), result);
});
Error Handling in Tools
@Tool(description = "Divide two numbers")
public double divide(double a, double b) {
if (b == 0) {
throw new IllegalArgumentException("Cannot divide by zero");
}
return a / b;
}
Tool with Return Direct
// Return result directly without LLM further processing
@Tool(description = "Execute SQL query",
returnDirect = true)
public String executeSql(String query) {
return database.executeQuery(query);
}
Tool Advisor Pattern
@Configuration
public class ToolAdvisorConfig {
@Bean
public ChatClientRequestAdvisor toolAdvisor(ChatModel chatModel) {
return new ToolsAdvisor(
chatModel,
List.of(weatherTool, databaseTool, webTool)
);
}
}
Configuration
Tool Execution Properties
spring.ai.tool.max-iterations=10
spring.ai.tool.timeout=30s
spring.ai.tool.error-recovery=true
spring.ai.tool.streaming.enabled=true
Tool Registration
@Configuration
public class ToolRegistration {
@Bean
public ToolCallbackRegistry toolRegistry(
WeatherTool weather,
DatabaseTool database) {
return new ToolCallbackRegistry()
.register("getWeather", weather::getWeather)
.register("queryDb", database::query);
}
}
Tool Discovery & Composition
Auto-discovery
// Spring automatically discovers @Tool annotated methods
@Component
public class ToolLibrary {
@Tool
public String tool1() { }
@Tool
public String tool2() { }
}
Manual Registration
registry.register("custom", customToolCallback);
Best Practices
- Keep tools focused and composable
- Provide clear descriptions for LLM understanding
- Validate input parameters
- Implement proper error handling
- Monitor tool execution
- Cache tool results when appropriate
- Version tools appropriately
- Test tools independently
Related Skills
advisors/SKILL.md- Advisor patternchat-models/SKILL.md- Chat modelsagents/SKILL.md- Agent patternsrag-retrieval/SKILL.md- RAG integration
References
- API:
/pages/api/tools.adoc - Migration:
/pages/api/tools-migration.adoc - ChatModel:
/pages/api/chatmodel.adoc - Examples: Tool calling examples in provider docs