Interface LLMProvider.ToolSpec
- Enclosing interface:
LLMProvider
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
FieldsModifier and TypeFieldDescriptionstatic final StringJSON Schema for a tool that takes no parameters. -
Method Summary
Modifier and TypeMethodDescriptionexecute(tools.jackson.databind.JsonNode arguments) Executes the tool with the given arguments.Gets a human-readable description of what this tool does.getName()Gets the unique name of this tool.Gets the JSON Schema describing the parameters this tool accepts.
-
Field Details
-
NO_PARAMETERS_SCHEMA
JSON Schema for a tool that takes no parameters. Declares a single optionalreasonproperty that the tool ignores, so the LLM always has a well-formed, non-empty object to send as arguments.Use this instead of
nullor a schema with an emptypropertiesobject: 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
nullor 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'sJsonSchemaGeneratoris 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
anyOfandenum). Generators may emit keywords such asformat,pattern, or$refthat not every LLM provider accepts.For a tool that takes no parameters, return
NO_PARAMETERS_SCHEMArather thannullor a schema with an emptypropertiesobject — see the constant's documentation for why. The built-in providers substituteNO_PARAMETERS_SCHEMAfor anullor blank return value, but an emptypropertiesobject is passed through as-is.- Returns:
- the JSON Schema string, or
NO_PARAMETERS_SCHEMAif the tool takes no parameters
-
execute
Executes the tool with the given arguments.Implementations should return a human-readable result string on success. On failure, throw a
ToolExceptionto 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 inui.access(), or work on state captured inAIController.onRequest().- Parameters:
arguments- the tool arguments as aJsonNodematching the parameters schema- Returns:
- the result of the tool execution as a string, never
null
-