Files
gh-giuseppe-trisciuoglio-de…/skills/langchain4j-tool-function-calling-patterns/references/references.md
2025-11-29 18:28:34 +08:00

9.3 KiB

LangChain4j Tool & Function Calling - API References

Complete API reference for tool and function calling with LangChain4j.

Tool Definition

@Tool Annotation

Purpose: Mark methods that LLM can call.

@Tool(value = "Description of what this tool does")
ReturnType methodName(ParameterType param) {
    // Implementation
}

// Examples
@Tool("Add two numbers together")
int add(int a, int b) { return a + b; }

@Tool("Query database for user information")
User getUserById(String userId) { ... }

@Tool("Send email to recipient")
void sendEmail(String to, String subject, String body) { ... }

@P Annotation

Purpose: Describe tool parameters for LLM understanding.

@Tool("Transfer money between accounts")
void transfer(
    @P("source account ID") String fromAccount,
    @P("destination account ID") String toAccount,
    @P("amount in dollars") double amount
) { ... }

Builder Configuration

AiServices Builder Extensions for Tools

AiServices.builder(AssistantInterface.class)
    
    // Register tool objects
    .tools(Object... tools)                    // Multiple tool objects
    .tools(new Calculator())                   // Single tool
    .tools(new Calculator(), new DataService()) // Multiple
    
    // Dynamic tool provider
    .toolProvider(ToolProvider toolProvider)
    
    // Error handlers
    .toolExecutionErrorHandler(ToolExecutionErrorHandler)
    .toolArgumentsErrorHandler(ToolArgumentsErrorHandler)
    
    .build();

Error Handlers

ToolExecutionErrorHandler

Purpose: Handle errors during tool execution.

@FunctionalInterface
interface ToolExecutionErrorHandler {
    String handle(ToolExecutionRequest request, Throwable exception);
}

// Usage
.toolExecutionErrorHandler((request, exception) -> {
    logger.error("Tool " + request.name() + " failed", exception);
    return "Error executing " + request.name() + ": " + exception.getMessage();
})

ToolArgumentsErrorHandler

Purpose: Handle errors in tool argument parsing/validation.

@FunctionalInterface
interface ToolArgumentsErrorHandler {
    String handle(ToolExecutionRequest request, Throwable exception);
}

// Usage
.toolArgumentsErrorHandler((request, exception) -> {
    logger.warn("Invalid arguments for " + request.name());
    return "Invalid arguments provided";
})

Tool Provider

ToolProvider Interface

Purpose: Dynamically select tools based on context.

@FunctionalInterface
interface ToolProvider {
    List<Object> getTools(ToolProviderContext context);
}

// Context available
interface ToolProviderContext {
    UserMessage userMessage();
    List<ChatMessage> messages();
}

Dynamic Tool Selection

.toolProvider(context -> {
    String message = context.userMessage().singleText();
    
    if (message.contains("calculate")) {
        return Arrays.asList(new Calculator());
    } else if (message.contains("weather")) {
        return Arrays.asList(new WeatherService());
    } else {
        return Collections.emptyList();
    }
})

Tool Execution Models

ToolExecutionRequest

interface ToolExecutionRequest {
    String name();                // Tool name from @Tool
    String description();         // Tool description
    Map<String, String> arguments(); // Tool arguments
}

ToolExecution (for streaming)

class ToolExecution {
    ToolExecutionRequest request();  // The tool being executed
    String result();                 // Execution result
}

Return Types

Supported Return Types

Primitives:

@Tool("Add numbers")
int add(@P("a") int x, @P("b") int y) { return x + y; }

@Tool("Compare values")
boolean isGreater(@P("a") int x, @P("b") int y) { return x > y; }

@Tool("Get temperature")
double getTemp() { return 22.5; }

String:

@Tool("Get greeting")
String greet(@P("name") String name) { return "Hello " + name; }

Objects (will be converted to String):

@Tool("Get user")
User getUser(@P("id") String id) { return new User(id); }

@Tool("Get user list")
List<User> listUsers() { return userService.getAll(); }

Collections:

@Tool("Search documents")
List<Document> search(@P("query") String q) { return results; }

@Tool("Get key-value pairs")
Map<String, String> getConfig() { return config; }

Void:

@Tool("Send notification")
void notify(@P("message") String msg) { 
    notificationService.send(msg);
}

Parameter Types

Supported Parameter Types

Primitives:

int, long, float, double, boolean, byte, short, char

Strings and wrapper types:

String, Integer, Long, Float, Double, Boolean

Collections:

List<String>, Set<Integer>, Collection<T>

Custom objects (must have toString() that's meaningful):

@Tool("Process data")
void process(CustomData data) { ... }

Dates and times:

@Tool("Get events for date")
List<Event> getEvents(LocalDate date) { ... }

@Tool("Schedule for time")
void schedule(LocalDateTime when) { ... }

Annotation Combinations

Complete Tool Definition

class DataService {
    
    // Basic tool
    @Tool("Get user information")
    User getUser(@P("user ID") String userId) { ... }
    
    // Tool with multiple params
    @Tool("Search users by criteria")
    List<User> search(
        @P("first name") String firstName,
        @P("last name") String lastName,
        @P("department") String dept
    ) { ... }
    
    // Tool returning collection
    @Tool("List all active users")
    List<User> getActiveUsers() { ... }
    
    // Tool with void return
    @Tool("Archive old records")
    void archiveOldRecords(@P("older than days") int days) { ... }
    
    // Tool with complex return
    @Tool("Get detailed report")
    Map<String, Object> generateReport(@P("month") int month) { ... }
}

Best Practices for API Usage

Tool Design

  1. Descriptive Names: Use clear, actionable names
// Good
@Tool("Get current weather for a city")
String getWeather(String city) { ... }

// Avoid
@Tool("Get info")
String getInfo(String x) { ... }
  1. Parameter Descriptions: Be specific about formats
// Good
@Tool("Calculate date difference")
long daysBetween(
    @P("start date in YYYY-MM-DD format") String start,
    @P("end date in YYYY-MM-DD format") String end
) { ... }

// Avoid
@Tool("Calculate difference")
long calculate(@P("date1") String d1, @P("date2") String d2) { ... }
  1. Appropriate Return Types: Return what LLM can use
// Good - LLM can interpret
@Tool("Get user role")
String getUserRole(String userId) { return "admin"; }

// Avoid - hard to parse
@Tool("Get user info")
User getUser(String id) { ... } // Will convert to toString()
  1. Error Messages: Provide actionable errors
.toolExecutionErrorHandler((request, exception) -> {
    if (exception instanceof IllegalArgumentException) {
        return "Invalid argument: " + exception.getMessage();
    }
    return "Error executing " + request.name();
})

Common Patterns

Validation Pattern:

@Tool("Create user")
String createUser(@P("email") String email) {
    if (!email.contains("@")) {
        throw new IllegalArgumentException("Invalid email format");
    }
    return "User created: " + email;
}

Batch Pattern:

@Tool("Bulk delete users")
String deleteUsers(@P("user IDs comma-separated") String userIds) {
    List<String> ids = Arrays.asList(userIds.split(","));
    return "Deleted " + ids.size() + " users";
}

Async Pattern (synchronous wrapper):

@Tool("Submit async task")
String submitTask(@P("task name") String name) {
    // Internally async, but returns immediately
    taskExecutor.submitAsync(name);
    return "Task " + name + " submitted";
}

Integration with AiServices

Complete Setup

interface Assistant {
    String execute(String command);
}

public class Setup {
    public static void main(String[] args) {
        var chatModel = OpenAiChatModel.builder()
            .apiKey(System.getenv("OPENAI_API_KEY"))
            .modelName("gpt-4o-mini")
            .temperature(0.0)  // Deterministic
            .build();

        var assistant = AiServices.builder(Assistant.class)
            .chatModel(chatModel)
            
            // Register tools
            .tools(
                new Calculator(),
                new WeatherService(),
                new UserDataService()
            )
            
            // Error handling
            .toolExecutionErrorHandler((request, exception) -> {
                System.err.println("Tool error: " + exception.getMessage());
                return "Tool failed";
            })
            
            // Optional: memory for context
            .chatMemory(MessageWindowChatMemory.withMaxMessages(10))
            
            .build();

        // Use the assistant
        String result = assistant.execute("What is the weather in Paris?");
        System.out.println(result);
    }
}