Claude Code Plugins

Community-maintained marketplace

Feedback

langchain4j-tool-function-calling-patterns

@giuseppe-trisciuoglio/developer-kit
8
0

Tool and function calling patterns with LangChain4j. Define tools, handle function calls, and integrate with LLM agents. Use when building agentic applications that interact with tools.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name langchain4j-tool-function-calling-patterns
description Tool and function calling patterns with LangChain4j. Define tools, handle function calls, and integrate with LLM agents. Use when building agentic applications that interact with tools.
category ai-development
tags langchain4j, tools, function-calling, @Tool, ToolProvider, ToolExecutor, dynamic-tools, parameter-descriptions, java
version 1.1.0
allowed-tools Read, Write, Bash, WebFetch

LangChain4j Tool & Function Calling Patterns

Define tools and enable AI agents to interact with external systems, APIs, and services using LangChain4j's annotation-based and programmatic tool system.

When to Use This Skill

Use this skill when:

  • Building AI applications that need to interact with external APIs and services
  • Creating AI assistants that can perform actions beyond text generation
  • Implementing AI systems that need access to real-time data (weather, stocks, etc.)
  • Building multi-agent systems where agents can use specialized tools
  • Creating AI applications with database read/write capabilities
  • Implementing AI systems that need to integrate with existing business systems
  • Building context-aware AI applications where tool availability depends on user state
  • Developing production AI applications that require robust error handling and monitoring

Setup and Configuration

Basic Tool Registration

// Define tools using @Tool annotation
public class CalculatorTools {
    @Tool("Add two numbers")
    public double add(double a, double b) {
        return a + b;
    }
}

// Register with AiServices builder
interface MathAssistant {
    String ask(String question);
}

MathAssistant assistant = AiServices.builder(MathAssistant.class)
    .chatModel(chatModel)
    .tools(new CalculatorTools())
    .build();

Builder Configuration Options

AiServices.builder(AssistantInterface.class)

    // Static tool registration
    .tools(new Calculator(), new WeatherService())

    // Dynamic tool provider
    .toolProvider(new DynamicToolProvider())

    // Concurrent execution
    .executeToolsConcurrently()

    // Error handling
    .toolExecutionErrorHandler((request, exception) -> {
        return "Error: " + exception.getMessage();
    })

    // Memory for context
    .chatMemoryProvider(userId -> MessageWindowChatMemory.withMaxMessages(20))

    .build();

Core Patterns

Basic Tool Definition

Use @Tool annotation to define methods as executable tools:

public class BasicTools {

    @Tool("Add two numbers")
    public int add(@P("first number") int a, @P("second number") int b) {
        return a + b;
    }

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

Parameter Descriptions and Validation

Provide clear parameter descriptions using @P annotation:

public class WeatherService {

    @Tool("Get current weather conditions")
    public String getCurrentWeather(
        @P("City name or coordinates") String location,
        @P("Temperature unit (celsius, fahrenheit)", required = false) String unit) {

        // Implementation with validation
        if (location == null || location.trim().isEmpty()) {
            return "Location is required";
        }

        return weatherClient.getCurrentWeather(location, unit);
    }
}

Complex Parameter Types

Use Java records and descriptions for complex objects:

public class OrderService {

    @Description("Customer order information")
    public record OrderRequest(
        @Description("Customer ID") String customerId,
        @Description("List of items") List<OrderItem> items,
        @JsonProperty(required = false) @Description("Delivery instructions") String instructions
    ) {}

    @Tool("Create customer order")
    public String createOrder(OrderRequest order) {
        return orderService.processOrder(order);
    }
}

Advanced Features

Memory Context Integration

Access user context using @ToolMemoryId:

public class PersonalizedTools {

    @Tool("Get user preferences")
    public String getPreferences(
        @ToolMemoryId String userId,
        @P("Preference category") String category) {

        return preferenceService.getPreferences(userId, category);
    }
}

Dynamic Tool Provisioning

Create tools that change based on context:

public class ContextAwareToolProvider implements ToolProvider {

    @Override
    public ToolProviderResult provideTools(ToolProviderRequest request) {
        String message = request.userMessage().singleText().toLowerCase();
        var builder = ToolProviderResult.builder();

        if (message.contains("weather")) {
            builder.add(weatherToolSpec, weatherExecutor);
        }

        if (message.contains("calculate")) {
            builder.add(calcToolSpec, calcExecutor);
        }

        return builder.build();
    }
}

Immediate Return Tools

Return results immediately without full AI response:

public class QuickTools {

    @Tool(value = "Get current time", returnBehavior = ReturnBehavior.IMMEDIATE)
    public String getCurrentTime() {
        return LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
    }
}

Error Handling

Tool Error Handling

Handle tool execution errors gracefully:

AiServices.builder(Assistant.class)
    .chatModel(chatModel)
    .tools(new ExternalServiceTools())
    .toolExecutionErrorHandler((request, exception) -> {
        if (exception instanceof ApiException) {
            return "Service temporarily unavailable: " + exception.getMessage();
        }
        return "An error occurred while processing your request";
    })
    .build();

Resilience Patterns

Implement circuit breakers and retries:

public class ResilientService {

    private final CircuitBreaker circuitBreaker = CircuitBreaker.ofDefaults("external-api");

    @Tool("Get external data")
    public String getExternalData(@P("Data identifier") String id) {
        return circuitBreaker.executeSupplier(() -> {
            return externalApi.getData(id);
        });
    }
}

Integration Examples

Multi-Domain Tool Service

@Service
public class MultiDomainToolService {

    public String processRequest(String userId, String request, String domain) {
        String contextualRequest = String.format("[Domain: %s] %s", domain, request);

        Result<String> result = assistant.chat(userId, contextualRequest);

        // Log tool usage
        result.toolExecutions().forEach(execution ->
            analyticsService.recordToolUsage(userId, domain, execution.request().name()));

        return result.content();
    }
}

Streaming with Tool Execution

interface StreamingAssistant {
    TokenStream chat(String message);
}

StreamingAssistant assistant = AiServices.builder(StreamingAssistant.class)
    .streamingChatModel(streamingChatModel)
    .tools(new Tools())
    .build();

TokenStream stream = assistant.chat("What's the weather and calculate 15*8?");

stream
    .onToolExecuted(execution ->
        System.out.println("Executed: " + execution.request().name()))
    .onPartialResponse(System.out::print)
    .onComplete(response -> System.out.println("Complete!"))
    .start();

Best Practices

Tool Design Guidelines

  1. Descriptive Names: Use clear, actionable tool names
  2. Parameter Validation: Validate inputs before processing
  3. Error Messages: Provide meaningful error messages
  4. Return Types: Use appropriate return types that LLMs can understand
  5. Performance: Avoid blocking operations in tools

Security Considerations

  1. Permission Checks: Validate user permissions before tool execution
  2. Input Sanitization: Sanitize all tool inputs
  3. Audit Logging: Log tool usage for security monitoring
  4. Rate Limiting: Implement rate limiting for external APIs

Performance Optimization

  1. Concurrent Execution: Use executeToolsConcurrently() for independent tools
  2. Caching: Cache frequently accessed data
  3. Monitoring: Monitor tool performance and error rates
  4. Resource Management: Handle external service timeouts gracefully

Reference Documentation

For detailed API reference, examples, and advanced patterns, see:

Common Issues and Solutions

Tool Not Found

Problem: LLM calls tools that don't exist

Solution: Implement hallucination handler:

.hallucinatedToolNameStrategy(request -> {
    return ToolExecutionResultMessage.from(request,
        "Error: Tool '" + request.name() + "' does not exist");
})

Parameter Validation Errors

Problem: Tools receive invalid parameters

Solution: Add input validation and error handlers:

.toolArgumentsErrorHandler((error, context) -> {
    return ToolErrorHandlerResult.text("Invalid arguments: " + error.getMessage());
})

Performance Issues

Problem: Tools are slow or timeout

Solution: Use concurrent execution and resilience patterns:

.executeToolsConcurrently(Executors.newFixedThreadPool(5))
.toolExecutionTimeout(Duration.ofSeconds(30))

Related Skills

  • langchain4j-ai-services-patterns
  • langchain4j-rag-implementation-patterns
  • langchain4j-spring-boot-integration

References