Interface LLMProvider.ToolSpec

Enclosing interface:
LLMProvider

public static interface LLMProvider.ToolSpec
A framework-agnostic tool definition that the LLM can invoke.

Unlike vendor-specific tool annotations (e.g., LangChain4j's @Tool, Spring AI's @Tool), this interface allows tools to be defined programmatically without depending on any specific AI framework.

Tool definitions are typically provided by AIController implementations through their AIController.getTools() method.

  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final String
    JSON Schema for a tool that takes no parameters.
  • Method Summary

    Modifier and Type
    Method
    Description
    execute(tools.jackson.databind.JsonNode arguments)
    Executes the tool with the given arguments.
    Gets a human-readable description of what this tool does.
    Gets the unique name of this tool.
    Gets the JSON Schema describing the parameters this tool accepts.
  • Field Details

    • NO_PARAMETERS_SCHEMA

      static final String NO_PARAMETERS_SCHEMA
      JSON Schema for a tool that takes no parameters. Declares a single optional reason property that the tool ignores, so the LLM always has a well-formed, non-empty object to send as arguments.

      Use this instead of null or a schema with an empty properties object: without a declared property, models disagree on what to send as arguments — some send an empty string — and some LLM APIs (for example Anthropic models on Amazon Bedrock) reject the request that replays such a tool call.

      Since:
      25.3
      See Also:
  • Method Details

    • getName

      String getName()
      Gets the unique name of this tool. The name must contain only alphanumeric characters, underscores, and hyphens, with a maximum length of 64 characters (matching the pattern ^[a-zA-Z0-9_-]{1,64}$), as required by popular LLM APIs. Names that do not match this pattern will be rejected by the orchestrator at request time. To avoid name collisions, use a namespaced name such as "MyController_updateConfig".
      Returns:
      the tool name, never null or empty
    • getDescription

      String getDescription()
      Gets a human-readable description of what this tool does. This description is sent to the LLM to help it decide when to invoke the tool.
      Returns:
      the tool description, never null
    • getParametersSchema

      String getParametersSchema()
      Gets the JSON Schema describing the parameters this tool accepts. The schema should follow the JSON Schema specification.

      Example:

       {
         "type": "object",
         "properties": {
           "query": { "type": "string", "description": "The SQL query" }
         },
         "required": ["query"]
       }
       

      Hand-writing the JSON is fine for small schemas but becomes error-prone as they grow. For larger schemas, a schema generator catches keyword typos and structural mistakes at compile time. When using SpringAILLMProvider, Spring AI's JsonSchemaGenerator is available without an extra dependency:

       import com.fasterxml.jackson.annotation.JsonPropertyDescription;
       import org.springframework.ai.util.json.schema.JsonSchemaGenerator;
      
       record UpdateGridArgs(
               @JsonPropertyDescription("The SQL query") String query) {}
      
       private static final String SCHEMA = JsonSchemaGenerator
               .generateForType(UpdateGridArgs.class);
      
       // in execute(JsonNode arguments):
       UpdateGridArgs args = new ObjectMapper().treeToValue(arguments,
               UpdateGridArgs.class);
       

      For other setups, any general-purpose JSON Schema generator that produces a schema string from a typed Java class works equivalently.

      Whichever approach you pick, verify the output stays inside the portable JSON Schema subset (string, integer, number, boolean, array, object, plus anyOf and enum). Generators may emit keywords such as format, pattern, or $ref that not every LLM provider accepts.

      For a tool that takes no parameters, return NO_PARAMETERS_SCHEMA rather than null or a schema with an empty properties object — see the constant's documentation for why. The built-in providers substitute NO_PARAMETERS_SCHEMA for a null or blank return value, but an empty properties object is passed through as-is.

      Returns:
      the JSON Schema string, or NO_PARAMETERS_SCHEMA if the tool takes no parameters
    • execute

      String execute(tools.jackson.databind.JsonNode arguments)
      Executes the tool with the given arguments.

      Implementations should return a human-readable result string on success. On failure, throw a ToolException to pass its message to the LLM so it can correct its next attempt; any other runtime exception is caught, logged, and replaced with a generic error message so internal details are not leaked.

      May be invoked from a background thread — with a streaming provider, or with background execution enabled — where Vaadin thread locals such as UI.getCurrent() are not bound. Wrap UI component access in ui.access(), or work on state captured in AIController.onRequest().

      Parameters:
      arguments - the tool arguments as a JsonNode matching the parameters schema
      Returns:
      the result of the tool execution as a string, never null