Enterprise Java

Dynamic Tool Discovery with Spring AI

As AI applications evolve from simple question-answering systems to enterprise-grade intelligent assistants, the ability to efficiently manage and integrate external capabilities becomes increasingly important. Modern applications require scalable approaches for connecting Large Language Models (LLMs) with hundreds of business functions without increasing complexity or performance overhead. This article explores how Spring AI enables scalable AI tool integration and introduces the concept of Dynamic Tool Discovery, where AI models can identify and invoke only the capabilities required for a specific user request. It explains the difference between traditional tool calling and dynamic discovery, the internal workflow, and the implementation approach using Spring AI tool abstractions.

1. Introduction to Dynamic Tool Discovery in Spring AI

Traditional AI applications typically register all available tools with the language model before processing any user request. While this approach works for applications with a limited number of tools, it becomes increasingly inefficient as the tool catalog expands, resulting in larger prompts, higher token consumption, increased latency, and the inclusion of many irrelevant tools in the model’s context. Spring AI addresses this challenge by providing tool calling abstractions that allow AI models to interact with application capabilities. In addition to traditional tool calling, Spring AI also provides Dynamic Tool Discovery through components such as ToolSearchTool and ToolSearcher. Instead of exposing every available tool to the language model, the application first exposes a searchable tool catalog. The model searches this catalog at runtime, identifies the required tools, and only those selected tools become available for execution during the current interaction.

2. Understanding Spring AI and Dynamic Tool Discovery

Spring AI is the official Spring ecosystem project for building AI-powered applications using familiar Spring programming models. It provides abstractions for integrating Large Language Models (LLMs), embedding models, vector databases, prompt templates, retrieval-augmented generation (RAG), and tool calling, allowing developers to build intelligent applications without dealing with vendor-specific APIs. By supporting multiple AI providers through a consistent programming model, Spring AI enables applications to switch between models while keeping the application code largely unchanged.

2.1 What is Dynamic Tool Discovery?

Dynamic Tool Discovery is an architectural approach supported by Spring AI that enables language models to discover and use only the tools relevant to a user’s request at runtime. Unlike traditional tool calling, where available tools are directly provided to the model, dynamic discovery introduces an intermediate discovery layer that allows the model to search tool metadata and identify suitable capabilities before invocation.

2.2 How the Tool Search Mechanism Works

Unlike traditional tool calling, where every tool is registered with the language model before processing a request, Dynamic Tool Discovery introduces an intermediate discovery step. Spring AI provides this capability through the ToolSearchTool, which exposes a searchable catalog of available tools, and a ToolSearcher implementation such as ToolSearcherRegex, which performs the actual search over tool metadata.

When a user submits a request, the language model first invokes the ToolSearchTool to identify the most relevant capabilities based on tool names, descriptions, and parameter metadata. The ToolSearcher searches the application’s tool catalog and returns only the matching tools. Spring AI then makes those selected tools available for execution during the current interaction. The language model invokes only the discovered tools, receives their outputs, and combines the results into a natural language response.

This discovery-first workflow allows enterprise applications to maintain hundreds or thousands of available tools while minimizing prompt size, reducing token consumption, and avoiding unnecessary tool metadata being sent to the language model.

3. Building a Dynamic Tool Discovery Application with Spring AI

3.1 Adding Spring AI Dependencies

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-tool</artifactId>
</dependency>

The spring-ai-starter-model-openai dependency provides the integration layer between Spring Boot applications and OpenAI models, allowing developers to use Spring AI abstractions such as ChatClient. Spring AI provides tool calling capabilities through its core tool abstractions, enabling developers to expose application methods as AI-invokable functions using annotations such as @Tool. Dynamic Tool Discovery is implemented using components such as ToolSearchTool and ToolSearcher, which allow models to discover required capabilities at runtime.

3.2 Configuring Spring AI Application Properties

The application configuration (application.yml) defines the OpenAI connection details required by Spring AI to communicate with the language model.

spring:
  ai:
    openai:
      api-key: ${OPENAI_API_KEY}

The application.yml file configures Spring AI with the OpenAI API key. The value is loaded from the OPENAI_API_KEY environment variable, which keeps sensitive credentials outside the source code. Spring AI automatically uses this configuration when creating model clients and handling AI requests.

To generate an OpenAI API key, sign in to the OpenAI developer platform and navigate to the API keys section. Create a new secret key, provide an optional name to identify its usage, and copy the generated key value. The key should be stored securely and should not be committed to source control or exposed in application configuration files. Once generated, configure it as an environment variable named OPENAI_API_KEY so that Spring AI can access it at runtime. For example, on Linux or macOS, the environment variable can be configured using export OPENAI_API_KEY=your_api_key, while on Windows it can be added through system environment variables or the command prompt. This approach follows security best practices by separating application code from sensitive credentials.

3.3 Configuring Dynamic Tool Discovery

Spring AI provides Dynamic Tool Discovery through the ToolSearchTool and a ToolSearcher implementation. Instead of exposing every application tool directly to the language model, the application first registers a searchable tool catalog. During a conversation, the model invokes the search tool to discover only the capabilities relevant to the user’s request.

package com.example.travel.config;

import java.util.List;

import org.springframework.ai.tool.ToolCallback;
import org.springframework.ai.tool.search.ToolSearcher;
import org.springframework.ai.tool.search.ToolSearcherRegex;
import org.springframework.ai.tool.search.ToolSearchTool;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ToolConfiguration {

    @Bean
    public ToolSearcher toolSearcher(List tools) {
        return ToolSearcherRegex.builder()
                .toolCallbacks(tools)
                .build();
    }

    @Bean
    public ToolSearchTool toolSearchTool(ToolSearcher toolSearcher) {
        return ToolSearchTool.builder(toolSearcher)
                .build();
    }
}

The ToolConfiguration class configures Spring AI Dynamic Tool Discovery. The toolSearcher() bean creates a searchable view of the available AI tools registered through Spring AI tool callbacks. The ToolSearcherRegex implementation searches tool metadata such as names, descriptions, and parameters to identify capabilities matching the user’s request. The ToolSearcherRegex implementation searches tool metadata such as tool names, descriptions, and parameters to identify capabilities matching the user’s request.

The toolSearchTool() bean exposes this search capability to the language model through Spring AI’s ToolSearchTool. Initially, the model receives only this discovery tool instead of the complete list of application tools. When the model requires additional capabilities, it invokes the ToolSearchTool, which searches the tool catalog and returns the relevant tools for execution during the current interaction.

3.4 Implementing a Flight Search Tool

This tool represents a business capability that can be exposed to the AI model for retrieving flight information based on user requirements.

package com.example.travel.tool;

import org.springframework.ai.tool.annotation.Tool;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClient;

@Component
public class FlightTool {

    private final RestClient restClient;

    public FlightTool(RestClient.Builder builder){
        this.restClient = builder.build();
    }

    @Tool(description="Search available flights between source and destination")
    public String searchFlights(String source, String destination){

        String url = "https://api.example.com/flights?source=" + source + "&destination=" + destination;
        return restClient.get()
                .uri(url)
                .retrieve()
                .body(String.class);
    }
}

The FlightTool class represents an AI-accessible business capability that allows the language model to invoke flight search functionality when required based on the tool metadata. The @Component annotation registers this class as a Spring-managed bean, making it available within the application context. The RestClient instance is injected through the constructor using Spring’s dependency injection mechanism and is used to communicate with external REST services. The @Tool annotation exposes the searchFlights() method as an AI-invokable function, where the description helps the language model understand when this capability should be used. When a user requests flight information, Spring AI allows the model to identify this tool, extract the required parameters such as source and destination, and invoke the method. The method dynamically builds the flight service URL using the provided inputs, sends an HTTP GET request using RestClient, retrieves the response from the external flight API, and returns the result back to the language model. The model can then use this tool output along with other discovered capabilities to generate a complete response for the user.

3.5 Implementing a Hotel Search Tool

The hotel tool demonstrates how additional domain capabilities can be added to the Spring AI tool catalog and discovered dynamically by the language model when required.

package com.example.travel.tool;

import org.springframework.ai.tool.annotation.Tool;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClient;

@Component
public class HotelTool {

    private final RestClient restClient;

    public HotelTool(RestClient.Builder builder){
        this.restClient = builder.build();
    }

    @Tool(description="Find available hotels for a given city")
    public String searchHotels(String city){
        return restClient.get()
                .uri("https://api.example.com/hotels?city=" + city)
                .retrieve()
                .body(String.class);
    }
}

The HotelTool class exposes hotel search functionality as an AI-invokable capability that can be discovered and executed by the language model through Spring AI. The @Component annotation registers the class as a Spring bean, allowing it to be managed by the Spring container. The RestClient object is created using the injected RestClient.Builder, which provides a convenient way to perform HTTP communication with external services. The @Tool annotation marks the searchHotels() method as a tool that the AI model can call when a user request requires hotel information. The tool description helps the model understand the purpose of this capability and decide when it should be invoked. When the method receives a city name from the AI model, it constructs a request URL for the hotel service, sends an HTTP GET request using RestClient, retrieves the response from the external hotel API, and returns the result as a string. The returned hotel information is then provided back to the language model, which can combine it with other tool outputs to generate a contextual response for the user.

3.6 Implementing a Weather Information Tool

The weather tool provides another example of adding real-time capabilities to the Spring AI tool catalog that can be discovered and invoked dynamically based on user intent.

package com.example.travel.tool;

import org.springframework.ai.tool.annotation.Tool;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClient;

@Component
public class WeatherTool {

    private final RestClient restClient;

    public WeatherTool(RestClient.Builder builder){
        this.restClient = builder.build();
    }

    @Tool(description="Get current weather information for a city")
    public String weather(String city){
        return restClient.get()
                .uri("https://api.example.com/weather?city=" + city)
                .retrieve()
                .body(String.class);
    }
}

The WeatherTool class provides weather lookup functionality as an AI-accessible tool that can be dynamically invoked by the language model when weather information is required. The @Component annotation registers the class as a Spring-managed bean, allowing Spring AI to discover and use this capability within the application. The RestClient instance is initialized through the constructor using Spring’s dependency injection with RestClient.Builder, enabling the tool to communicate with external weather services. The @Tool annotation exposes the weather() method as a callable function for the AI model, while the description helps the model understand the purpose of the tool and determine when it should be used. When the method receives a city name, it creates a request URL for the weather service, executes an HTTP GET request using RestClient, retrieves the weather response from the external API, and returns the result to the language model. The AI model can then combine this real-time weather information with other discovered tool outputs to generate a complete and context-aware response for the user.

3.7 Integrating AI Tools with Spring AI ChatClient

The controller uses Spring AI’s ChatClient abstraction to receive user requests, communicate with the language model, and coordinate tool execution when additional business capabilities are required.

The tools themselves are not configured in application.yml. Spring AI discovers tool implementations from Spring-managed beans annotated with @Tool and maintains them in the tool catalog. During execution, the language model does not receive all available tools directly. Instead, it initially receives only the ToolSearchTool, which searches the catalog and returns only the capabilities required for the current request.

package com.example.travel.controller;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.tool.search.ToolSearchTool;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TravelController {

    private final ChatClient chatClient;

    public TravelController(ChatClient.Builder builder,
                            ToolSearchTool toolSearchTool) {

        this.chatClient = builder
                .defaultTools(toolSearchTool)
                .build();
    }

    @GetMapping("/travel")
    public String travel(@RequestParam String prompt){

        return chatClient.prompt(prompt)
                .call()
                .content();
    }
}

The TravelController class exposes a REST API endpoint that accepts user requests and uses Spring AI’s ChatClient to communicate with the language model. The @RestController annotation marks this class as a Spring MVC REST controller, allowing it to handle HTTP requests and return AI-generated responses. The ChatClient instance is created in the constructor using Spring AI’s builder pattern. The ToolSearchTool is registered using defaultTools(), which is the key part of Dynamic Tool Discovery. Instead of exposing all application tools such as flight search, hotel search, or weather services directly to the language model, only the discovery capability is initially provided. When a user submits a request, the language model can invoke the ToolSearchTool to search the available tool catalog through the configured ToolSearcher implementation. When a user submits a request, the language model can invoke the ToolSearchTool to search the available tool catalog through the configured ToolSearcher implementation. The search results identify the capabilities required for the request, and Spring AI enables only those discovered tools for the current interaction. The model then invokes these tools, receives the results, and generates the final response.

3.8 Executing the Application and Analyzing the Output

Once the Spring Boot application is started, the travel API can be invoked by sending a natural language request through the /travel endpoint. The user does not need to specify the individual tools required to complete the request. Spring AI sends the user prompt to the language model along with the configured discovery capability, allowing the model to search the available tool catalog and identify the tools required to complete the request.

GET http://localhost:8080/travel?prompt=Find a flight from Delhi to London, suggest a hotel, and provide current weather information

Response:

Flight:
AI101 Delhi -> London
Departure: 10:30 AM
Price: ₹58,500

Hotel:
Grand London Hotel
Price: ₹12,000/night

Weather:
London: 18°C, Cloudy

In this example, the user submits a single travel-related request containing multiple requirements. The request first reaches the TravelController, which passes the prompt to Spring AI’s ChatClient. The ChatClient communicates with the language model, which analyzes the user’s intent and identifies the capabilities required to answer the request. For this example, the language model first invokes the ToolSearchTool, which searches the registered tool catalog using the configured ToolSearcherRegex implementation. Based on the returned metadata, Spring AI enables only the relevant tools required for the current request, such as FlightTool, HotelTool, and WeatherTool. The model then invokes these tools, receives their outputs, and combines the results into a single response.

In a traditional approach, every available tool would need to be manually managed and included in the model context for every request. Dynamic Tool Discovery extends this workflow by introducing a discovery layer where the model can search a larger tool catalog and load only the capabilities required for a specific task. This allows enterprise applications to scale to hundreds or thousands of tools while reducing unnecessary tool metadata exposure, prompt size, and execution overhead.

4. Conclusion

Spring AI’s Dynamic Tool Discovery builds upon traditional tool calling by introducing a searchable tool catalog through ToolSearchTool and ToolSearcher. Rather than exposing every available capability to the language model, applications allow the model to discover relevant tools at runtime and invoke only those required for a specific request. This discovery-first approach reduces prompt size, improves scalability, lowers token consumption, and enables enterprise AI applications to efficiently manage hundreds or thousands of tools while maintaining a clean and extensible architecture.

Yatin Batra

An experience full-stack engineer well versed with Core Java, Spring/Springboot, MVC, Security, AOP, Frontend (Angular & React), and cloud technologies (such as AWS, GCP, Jenkins, Docker, K8).
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Back to top button