$npx -y skills add giuseppe-trisciuoglio/developer-kit --skill langchain4j-tool-function-calling-patternsProvides and generates LangChain4j tool and function calling patterns: annotates methods as tools with @Tool, configures tool executors, registers tools with AiServices, validates tool parameters, and handles tool execution errors. Use when building AI agents that call tools, def
| 1 | # LangChain4j Tool & Function Calling Patterns |
| 2 | |
| 3 | Provides patterns for annotating methods as tools, configuring tool executors, registering tools with AI services, validating parameters, and handling tool execution errors in LangChain4j applications. |
| 4 | |
| 5 | ## Overview |
| 6 | |
| 7 | LangChain4j uses the `@Tool` annotation to expose Java methods as callable functions for AI agents. The `AiServices` builder registers tools with a chat model, enabling LLMs to perform actions beyond text generation: database queries, API calls, calculations, and business system integrations. Parameters use `@P` for descriptions that guide the LLM. |
| 8 | |
| 9 | ## When to Use |
| 10 | |
| 11 | - Building AI agents that call external tools (weather, stocks, database queries) |
| 12 | - Defining function specifications for LLM tool use (`@Tool`, `@P` annotations) |
| 13 | - Registering and managing tool sets with `AiServices.builder().tools()` |
| 14 | - Handling tool execution errors, timeouts, and hallucinated tool names |
| 15 | - Implementing context-aware tools that inject user state via `@ToolMemoryId` |
| 16 | - Configuring dynamic tool providers for large or conditional tool sets |
| 17 | |
| 18 | ## Instructions |
| 19 | |
| 20 | ### 1. Annotate Methods with `@Tool` |
| 21 | |
| 22 | Define a tool class with methods annotated `@Tool`. Provide a description as the first parameter. Use `@P` for each parameter description. |
| 23 | |
| 24 | ```java |
| 25 | public class WeatherTools { |
| 26 | private final WeatherService weatherService; |
| 27 | |
| 28 | public WeatherTools(WeatherService weatherService) { |
| 29 | this.weatherService = weatherService; |
| 30 | } |
| 31 | |
| 32 | @Tool("Get current weather for a city") |
| 33 | public String getWeather( |
| 34 | @P("City name") String city, |
| 35 | @P("Temperature unit: celsius or fahrenheit") String unit) { |
| 36 | return weatherService.getWeather(city, unit); |
| 37 | } |
| 38 | } |
| 39 | ``` |
| 40 | |
| 41 | **Validate**: Create an instance and confirm the class loads without errors. |
| 42 | |
| 43 | ### 2. Register Tools with AiServices |
| 44 | |
| 45 | Use `AiServices.builder()` to register tool instances with the chat model. |
| 46 | |
| 47 | ```java |
| 48 | MathAssistant assistant = AiServices.builder(MathAssistant.class) |
| 49 | .chatModel(chatModel) |
| 50 | .tools(new Calculator(), new WeatherTools(weatherService)) |
| 51 | .build(); |
| 52 | ``` |
| 53 | |
| 54 | **Validate**: Call `assistant.chat("What is 2 + 2?")` and verify the LLM responds without throwing. |
| 55 | |
| 56 | ### 3. Test Tool Invocation End-to-End |
| 57 | |
| 58 | Send a prompt that triggers tool usage and verify the tool executes and its result is incorporated. |
| 59 | |
| 60 | ```java |
| 61 | String response = assistant.chat("What is the weather in Rome?"); |
| 62 | System.out.println(response); |
| 63 | ``` |
| 64 | |
| 65 | **Validate**: Check logs for tool invocation and confirm the response uses the tool output. |
| 66 | |
| 67 | ### 4. Handle Tool Execution Errors |
| 68 | |
| 69 | Add error handlers to gracefully manage failures without exposing stack traces. |
| 70 | |
| 71 | ```java |
| 72 | AiServices.builder(Assistant.class) |
| 73 | .chatModel(chatModel) |
| 74 | .tools(new ExternalServiceTools()) |
| 75 | .toolExecutionErrorHandler((request, exception) -> { |
| 76 | logger.error("Tool '{}' failed: {}", request.name(), exception.getMessage()); |
| 77 | return "An error occurred while processing your request"; |
| 78 | }) |
| 79 | .hallucinatedToolNameStrategy(request -> |
| 80 | ToolExecutionResultMessage.from(request, |
| 81 | "Error: tool '" + request.name() + "' does not exist")) |
| 82 | .toolArgumentsErrorHandler((error, context) -> |
| 83 | ToolErrorHandlerResult.text("Invalid arguments: " + error.getMessage())) |
| 84 | .build(); |
| 85 | ``` |
| 86 | |
| 87 | **Validate**: Trigger an error condition and confirm the LLM receives a safe error message. |
| 88 | |
| 89 | ### 5. Optimize for Performance and Scale |
| 90 | |
| 91 | Enable concurrent tool execution and set timeouts for long-running tools. |
| 92 | |
| 93 | ```java |
| 94 | AiServices.builder(Assistant.class) |
| 95 | .chatModel(chatModel) |
| 96 | .tools(new DbTools(), new HttpTools()) |
| 97 | .executeToolsConcurrently(Executors.newFixedThreadPool(5)) |
| 98 | .toolExecutionTimeout(Duration.ofSeconds(30)) |
| 99 | .build(); |
| 100 | ``` |
| 101 | |
| 102 | **Validate**: Run concurrent requests and confirm no thread contention or deadlocks. |
| 103 | |
| 104 | ## Examples |
| 105 | |
| 106 | ### Calculator Tool with Full Class |
| 107 | |
| 108 | ```java |
| 109 | public class Calculator { |
| 110 | @Tool("Perform basic arithmetic") |
| 111 | public double calculate( |
| 112 | @P("Expression like 2+2 or 10*5") String expression) { |
| 113 | // Parse and evaluate expression |
| 114 | return eval(expression); |
| 115 | } |
| 116 | } |
| 117 | |
| 118 | Assistant assistant = AiServices.builder(Assistant.class) |
| 119 | .chatModel(ChatModel.builder() |
| 120 | .apiKey(System.getenv("API_KEY")) |
| 121 | .model("gpt-4o") |
| 122 | .build()) |
| 123 | .tools(new Calculator()) |
| 124 | .build(); |
| 125 | ``` |
| 126 | |
| 127 | ### Immediate Return Tool (No LLM Response) |
| 128 | |
| 129 | ```java |
| 130 | @Tool(value = "Send email notification", ret |