Docs

Tool Calling & Programmatic Prompts

Register tool objects for LLM invocation and send prompts programmatically without a Message Input component.

Tools let the LLM call methods in your application during a conversation — query a database, look up an order, send an email, or any other action you want the assistant to be able to perform. Vaadin supports two ways to expose tools: registered tool objects (covered on this page) and framework-agnostic Controllers.

Tool Calling

Register objects with vendor-specific @Tool annotations that the LLM can invoke:

Source code
Java
public class WeatherTools {
    // Spring AI: org.springframework.ai.tool.annotation.Tool
    @Tool(description = "Get current weather for a city")
    public String getWeather(String city) {
        return weatherService.getCurrentWeather(city);
    }
}

var orchestrator = AIOrchestrator
        .builder(provider, systemPrompt)
        .withMessageList(messageList)
        .withInput(messageInput)
        .withTools(new WeatherTools())
        .build();

The annotation comes from the framework the provider wraps, and the two spell the description differently. For Spring AI, use @org.springframework.ai.tool.annotation.Tool with a description attribute, as above. For LangChain4j, use @dev.langchain4j.agent.tool.Tool, whose description is the annotation’s value:

Source code
Java
// LangChain4j: dev.langchain4j.agent.tool.Tool
@Tool("Get current weather for a city")
public String getWeather(String city) {
    return weatherService.getCurrentWeather(city);
}
Note
Tool Threading
With a streaming provider or background execution, tool methods are invoked off the request thread, where UI.getCurrent() and other Vaadin thread locals are not available. Wrap component access in ui.access(), or capture the needed state before the turn starts.
Tip
Framework-Agnostic Tools via Controllers
For a reusable set of tools that does not depend on a specific LLM framework’s annotations, or when a lifecycle hook is needed after each LLM request cycle, implement AIController instead. GridAIController and ChartAIController are built-in examples. Controllers and tool objects can be combined on the same orchestrator.
Note
Tool Errors
Tool objects registered via withTools() are executed by the vendor framework, whose own error handling decides what the LLM sees when a tool throws — by default, both LangChain4j and Spring AI relay the raw message of any exception. To control what the LLM learns about failures, define the tool through a controller instead and throw a ToolException for messages the LLM is meant to see; see Tool Error Handling.

Programmatic Prompts

Send prompts without a Message Input component using prompt(). This is useful for triggering AI interaction from button clicks or other events:

Source code
AIOrchestratorProgrammaticPrompt.java

Programmatic prompts go through the same pipeline as chat submits: a configured request interceptor can change or reject them before anything is sent.

Note
One Request at a Time
The orchestrator processes one prompt at a time. If prompt() is called while a previous request is still streaming, the new call is logged as a warning and silently dropped. Wait for the current response to complete before sending another prompt.
Important
UI Context Required
prompt() requires an active UI context. If called from a background thread or outside a Vaadin request, it throws an IllegalStateException. Always call prompt() from within a UI event handler or wrap the call in ui.access().

Updated