Turn Java Methods into AI Agent Tools with @Tool Annotation – Day 2 of 3‑Day Spring AI Crash Course

This article explains how to equip a Spring AI Agent with real‑world capabilities by annotating Java methods with @Tool, registers those tools for the agent, demonstrates single‑ and multi‑tool orchestration, and shows how the Advisor mechanism brings AOP‑style processing such as RAG and memory management into AI workflows.

AI Illustrated Series
AI Illustrated Series
AI Illustrated Series
Turn Java Methods into AI Agent Tools with @Tool Annotation – Day 2 of 3‑Day Spring AI Crash Course

What it means for an AI Agent to "do things"

Unlike a pure language model that can only talk, an AI Agent can invoke real functions and access external systems. The model decides which tool to call and with what parameters, while the actual execution is performed by ordinary Java methods, similar to how Spring MVC’s DispatcherServlet delegates to Controllers.

@Tool: Defining a tool with an annotation

Spring AI makes tool definition extremely simple: add the @Tool annotation to any Java method. For example:

import org.springframework.ai.tool.annotation.Tool;
import org.springframework.stereotype.Component;

@Component
public class WeatherTools {
    // This method becomes callable by the AI Agent
    @Tool(description = "Query real‑time weather for a city, returning condition and temperature")
    public String getWeather(String city) {
        return city + ": sunny, 25°C, humidity 40%";
    }

    @Tool(description = "Query weather forecast for a date (yyyy‑MM‑dd)")
    public String getWeatherForecast(String city, String dateStr) {
        return city + " " + dateStr + ": cloudy to sunny, 22‑30°C";
    }
}

Compared with @RequestMapping, the purpose is identical: both expose a Java method to an external caller, the difference being that the caller is an HTTP client in the former case and a large language model in the latter.

Registering tools with the Agent

After defining tools, they must be made visible to the Agent:

@Service
public class WeatherAgentService {
    @Autowired
    private ChatClient chatClient;

    @Autowired
    private WeatherTools weatherTools;

    public String askWeather(String question) {
        return chatClient.prompt()
                .system("You are a weather‑query assistant. When a weather‑related question appears, proactively call the appropriate tool.")
                .user(question)
                .tools(weatherTools) // register tools like a Bean dependency
                .call()
                .content();
    }
}

A test shows the Agent automatically invoking getWeather and getWeatherForecast and composing a natural‑language answer:

@SpringBootTest
class WeatherAgentServiceTest {
    @Autowired
    private WeatherAgentService service;

    @Test
    void testWeatherQuery() {
        String result = service.askWeather("北京今天天气怎么样?明天需要带伞吗?");
        System.out.println(result); // Agent calls the two tools and returns the combined answer
    }
}

Tool call sequence

Spring AI automatically transforms the @Tool method signatures into model‑understandable descriptions, parses the model’s tool‑call request, executes the Java method, and returns the result. (Diagram omitted.)

Parameter types: leveraging Java’s type system

Complex parameter types, including POJOs, are supported. Spring AI converts them to JSON Schema. Example:

public record SearchRequest(
    @JsonProperty(required = true) String keyword,
    @JsonProperty(defaultValue = "10") Integer limit,
    @JsonProperty(required = false) String category) {}

@Component
public class SearchTools {
    @Tool(description = "Search documents in a knowledge base, optional category filter")
    public List<String> searchDocs(SearchRequest request) {
        // Simulated search
        return List.of(
            "关于 " + request.keyword() + " 的文档1",
            "关于 " + request.keyword() + " 的文档2"
        );
    }

    @Tool(description = "Query user information from the database")
    public UserInfo getUserInfo(Long userId) {
        return userRepository.findById(userId)
                .orElseThrow(() -> new RuntimeException("用户不存在"));
    }
}

Multi‑tool collaboration: letting the Agent plan

When an Agent has several tools, the model decides the execution order. Example with order assistance:

@Component
public class OrderAssistantTools {
    @Autowired
    private OrderService orderService;
    @Autowired
    private InventoryService inventoryService;
    @Autowired
    private LogisticsService logisticsService;

    @Tool(description = "Query order status by order ID")
    public String getOrderStatus(String orderId) {
        Order order = orderService.findById(orderId);
        return "订单" + orderId + ":" + order.getStatus().getDescription();
    }

    @Tool(description = "Query inventory by SKU")
    public Integer getInventory(String sku) {
        return inventoryService.getStock(sku);
    }

    @Tool(description = "Query logistics by tracking number")
    public String getLogistics(String trackingNo) {
        return logisticsService.track(trackingNo);
    }
}

When a user asks “帮我查一下订单ORD001的物流”, the Agent performs:

Call getOrderStatus("ORD001") to obtain the tracking number.

Call getLogistics(trackingNo) to fetch logistics info.

Combine the two results into a natural‑language response.

The call chain is autonomously planned by the model, not hard‑coded.

Advisor: applying AOP concepts to AI

Spring AI’s Advisor mechanism works exactly like Spring AOP, adding cross‑cutting concerns to the call chain. Example:

@Service
public class SmartChatService {
    @Autowired
    private ChatClient chatClient;
    @Autowired
    private VectorStore vectorStore; // RAG knowledge base

    public String chat(String sessionId, String question) {
        return chatClient.prompt()
                .user(question)
                // Advisor 1: Retrieve relevant documents from the vector store (RAG)
                .advisors(new QuestionAnswerAdvisor(vectorStore))
                // Advisor 2: Manage conversation memory (multi‑turn)
                .advisors(new MessageChatMemoryAdvisor(new InMemoryChatMemory(), sessionId, 10))
                // Advisor 3: Simple logging (like @Slf4j)
                .advisors(new SimpleLoggerAdvisor())
                .call()
                .content();
    }
}

Each advisor adds a specific capability: document retrieval, memory handling, and logging, all with a single line of code.

Day 2 recap

1. The @Tool annotation turns a Java method into an Agent‑callable tool, analogous to @RequestMapping for HTTP endpoints.

2. In multi‑tool scenarios the Agent autonomously decides the execution order, removing the need for manual orchestration.

3. The Advisor mechanism brings AOP‑style processing into AI, enabling RAG, memory management, and logging.

Looking ahead

Tomorrow will cover how Spring AI integrates with enterprise systems—database access, internal knowledge bases, and permission control—to deliver a complete enterprise‑grade AI Agent solution.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaBackend DevelopmentRAGAI AgentSpring AIAdvisorTool Annotation
AI Illustrated Series
Written by

AI Illustrated Series

Illustrated hardcore tech: AI, agents, algorithms, databases—one picture worth a thousand words.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.