The @Tool annotation marks a Java method as a callable tool that a language model can request through a Spring AI application. Its name identifies the tool, while its description helps the model decide when to use it. section 6.1.1 section 6.4
Define an annotated tool by following these implementation choices:
- Place one or more annotated methods in a Spring-managed component such as a class marked with @Component or @Service. section 6.1.1 section 7.3.3
- Give every tool a distinct name; if name is omitted, the Java method name becomes the tool name. section 6.1.1
- Describe parameters with @ToolParam so the model understands the values required for invocation. section 6.2.2
- Expose tools through ChatClient.defaultTools(), prompt.tools(), or an MCP ToolCallbackProvider. section 6.2.3 section 7.3.3
A time-zone tool
Annotate a Spring component method with @Tool(name = "getCurrentTime", description = "Get the current time in the specified time zone."). Accept a time-zone String, obtain the time with LocalDateTime.now(ZoneId.of(timeZone)), and return the result. Inject the component into the controller and register it with defaultTools(timeTools).
Listing 6.4 Declaring a game complexity tool
@Bean
package com.example.boardgamebuddy;
import com.example.boardgamebuddy.gamedata.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Component;
import java.util.Optional;
@Component
public class GameTools {
private final GameRepository gameRepository;
public GameTools(GameRepository gameRepository) { #1
this.gameRepository = gameRepository;
}
private static final Logger LOGGER =
LoggerFactory.getLogger(GameTools.class);
@Tool(name = "getGameComplexity",
description = "Returns a game's complexity/difficulty " +
"given the game's title/name.")
public GameComplexityResponse getGameComplexity(
@ToolParam(description="The title of the game") #2
String gameTitle) {
var gameSlug = gameTitle #3
.toLowerCase()
.replace(" ", "_");
LOGGER.info("Getting complexity for {} ({})",
gameTitle, gameSlug);
var gameOpt = gameRepository.findBySlug(gameSlug); #4
var game = gameOpt.orElseGet(() -> { #5
LOGGER.warn("Game not found: {}", gameSlug);
return new Game(
null,
gameSlug,
gameTitle,
GameComplexity.UNKNOWN.getValue());
});
return new GameComplexityResponse( #6
game.title(), game.complexityEnum());
}
}
Browse a repository-backed @Tool method that accepts a described parameter, queries game data, and returns a typed Java record. section 6.2.2
The model does not invoke the method directly. It requests a tool call, the application executes the method, and the tool result returns as context for continued generation. Method-level security can protect an annotated method with @PreAuthorize. section 6.4 section 10.2

