spring-ai icon indicating copy to clipboard operation
spring-ai copied to clipboard

feat: Extend ToolDefinition to Support Metadata

Open liugddx opened this issue 3 weeks ago • 1 comments
trafficstars

Close #4743

Extend ToolDefinition to Support Metadata

Create a ToolDefinitionWithMetadata Class

package org.springframework.ai.tool.definition;

import java.util.Map;
import org.springframework.util.Assert;

/**
 * Tool definition with metadata support.
 */
public record ToolDefinitionWithMetadata(
    String name,
    String description,
    String inputSchema,
    Map<String, Object> metadata
) implements ToolDefinition {

    public ToolDefinitionWithMetadata {
        Assert.hasText(name, "name cannot be null or empty");
        Assert.hasText(description, "description cannot be null or empty");
        Assert.hasText(inputSchema, "inputSchema cannot be null or empty");
        // Metadata can be empty
        metadata = metadata != null ? Map.copyOf(metadata) : Map.of();
    }

    public static Builder builder() {
        return new Builder();
    }

    public static final class Builder {
        private String name;
        private String description;
        private String inputSchema;
        private Map<String, Object> metadata = Map.of();

        private Builder() {}

        public Builder name(String name) {
            this.name = name;
            return this;
        }

        public Builder description(String description) {
            this.description = description;
            return this;
        }

        public Builder inputSchema(String inputSchema) {
            this.inputSchema = inputSchema;
            return this;
        }

        public Builder metadata(Map<String, Object> metadata) {
            this.metadata = metadata;
            return this;
        }

        public Builder addMetadata(String key, Object value) {
            if (this.metadata.isEmpty()) {
                this.metadata = new java.util.HashMap<>();
            } else if (!(this.metadata instanceof java.util.HashMap)) {
                this.metadata = new java.util.HashMap<>(this.metadata);
            }
            this.metadata.put(key, value);
            return this;
        }

        public ToolDefinitionWithMetadata build() {
            return new ToolDefinitionWithMetadata(name, description, inputSchema, metadata);
        }
    }
}

Extend the @Tool Annotation

@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Tool {

    String name() default "";
    String description() default "";
    boolean returnDirect() default false;
    Class<? extends ToolCallResultConverter> resultConverter() default DefaultToolCallResultConverter.class;

    // New: Metadata support
    /**
     * Tool metadata for filtering and categorization.
     * Format: "key1=value1,key2=value2"
     * Example: "type=RealTimeAnalysis,priority=high"
     */
    String metadata() default "";
}

Create a Dedicated @ToolMetadata Annotation (More Elegant Approach)

package org.springframework.ai.tool.annotation;

import java.lang.annotation.*;

/**
 * Annotation to add metadata to a tool method.
 * Can be used in conjunction with @Tool annotation.
 * 
 * @author 
 * @since 1.0.0
 */
@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ToolMetadata {

    /**
     * Metadata entries in key-value format.
     * Example: {"type=RealTimeAnalysis", "category=analytics"}
     */
    String[] value() default {};

    /**
     * Tool category for filtering purposes.
     */
    String category() default "";

    /**
     * Tool type for classification.
     */
    String type() default "";

    /**
     * Priority level (1–10, where 10 is the highest).
     */
    int priority() default 5;
}

Usage Example

@Component
public class AnalysisTools {

    @Tool(description = "Performs real-time data analysis")
    @ToolMetadata(type = "RealTimeAnalysis", category = "analytics", priority = 8)
    public String analyzeRealTimeData(String data) {
        // Implementation
        return "analysis result";
    }

    @Tool(description = "Performs historical data analysis")
    @ToolMetadata(type = "HistoricalAnalysis", category = "analytics", priority = 5)
    public String analyzeHistoricalData(String period) {
        // Implementation
        return "historical analysis";
    }
}

Modify the Tool Registration Process

Modify MethodToolCallbackProvider to support metadata.

// Pseudocode example
private ToolDefinition createToolDefinition(Method method) {
    ToolMetadata metadata = method.getAnnotation(ToolMetadata.class);

    if (metadata != null) {
        Map<String, Object> metadataMap = new HashMap<>();

        if (!metadata.type().isEmpty()) {
            metadataMap.put("type", metadata.type());
        }
        if (!metadata.category().isEmpty()) {
            metadataMap.put("category", metadata.category());
        }
        metadataMap.put("priority", metadata.priority());

        // Parse additional metadata from value entries
        for (String entry : metadata.value()) {
            String[] parts = entry.split("=", 2);
            if (parts.length == 2) {
                metadataMap.put(parts[0], parts[1]);
            }
        }

        return ToolDefinitionWithMetadata.builder()
            .name(getToolName(method))
            .description(getToolDescription(method))
            .inputSchema(generateSchema(method))
            .metadata(metadataMap)
            .build();
    }

    // Return the default ToolDefinition
    return DefaultToolDefinition.builder()...build();
}

Summary: This proposal introduces metadata support for tool definitions, providing a standardized and extensible mechanism to annotate and categorize tools. It allows fine-grained filtering, better organization, and easier integration in complex AI systems.

liugddx avatar Oct 30 '25 15:10 liugddx