langchain4j-tool-function-calling-patterns by giuseppe-trisciuoglio/developer-kit
npx skills add https://github.com/giuseppe-trisciuoglio/developer-kit --skill langchain4j-tool-function-calling-patterns使用 LangChain4j 基于注解和编程式的工具系统定义工具,使 AI 代理能够与外部系统、API 和服务进行交互。
LangChain4j 的工具系统使 AI 代理能够通过声明式注解和编程式接口执行外部函数。工具使用 @Tool 注解定义,并自动注册到 AI 服务,允许大型语言模型执行文本生成之外的操作,例如数据库查询、API 调用和计算。
在以下情况下使用此技能:
按照以下步骤使用 LangChain4j 实现工具:
在类中创建带有 @Tool 注解的方法:
public class WeatherTools {
@Tool("Get current weather for a city")
public String getWeather(
@P("City name") String city,
@P("Temperature unit (celsius or fahrenheit)", required = false) String unit) {
// Implementation
return weatherService.getWeather(city, unit);
}
}
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
使用 @P 注解提供清晰的参数描述,帮助 LLM 理解如何调用工具:
@Tool("Calculate total order amount")
public double calculateOrderTotal(
@P("List of product IDs") List<String> productIds,
@P("Customer discount percentage", required = false) Double discount) {
// Implementation
}
使用 AiServices 构建器将工具连接到 AI 服务:
MathAssistant assistant = AiServices.builder(MathAssistant.class)
.chatModel(chatModel)
.tools(new Calculator(), new WeatherService())
.build();
为工具执行失败实现错误处理:
AiServices.builder(Assistant.class)
.chatModel(chatModel)
.tools(new ExternalServiceTools())
.toolExecutionErrorHandler((request, exception) -> {
log.error("Tool execution failed: {}", exception.getMessage());
return "An error occurred while processing your request";
})
.build();
跟踪工具调用以进行调试和分析:
Result<String> result = assistant.chat(question);
result.toolExecutions().forEach(execution ->
log.info("Executed tool: {} in {}ms",
execution.request().name(),
execution.duration().toMillis())
);
// 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();
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();
使用 @Tool 注解将方法定义为可执行工具:
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 + "!";
}
}
使用 @P 注解提供清晰的参数描述:
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);
}
}
使用 Java 记录和描述来处理复杂对象:
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);
}
}
使用 @ToolMemoryId 访问用户上下文:
public class PersonalizedTools {
@Tool("Get user preferences")
public String getPreferences(
@ToolMemoryId String userId,
@P("Preference category") String category) {
return preferenceService.getPreferences(userId, category);
}
}
创建基于上下文变化的工具:
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();
}
}
无需完整 AI 响应即可立即返回结果:
public class QuickTools {
@Tool(value = "Get current time", returnBehavior = ReturnBehavior.IMMEDIATE)
public String getCurrentTime() {
return LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
}
}
优雅地处理工具执行错误:
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();
实现熔断器和重试机制:
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);
});
}
}
@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();
}
}
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();
executeToolsConcurrently()public class CalculatorTools {
@Tool("Add two numbers")
public double add(@P("First number") double a,
@P("Second number") double b) {
return a + b;
}
@Tool("Multiply two numbers")
public double multiply(@P("First number") double a,
@P("Second number") double b) {
return a * b;
}
}
// Usage
interface MathAssistant {
String ask(String question);
}
MathAssistant assistant = AiServices.builder(MathAssistant.class)
.chatModel(chatModel)
.tools(new CalculatorTools())
.build();
String result = assistant.ask("What is 15 times 7 plus 3?");
@Component
public class DatabaseTools {
private final CustomerRepository repository;
@Tool("Get customer information by ID")
public Customer getCustomer(@P("Customer ID") Long customerId) {
return repository.findById(customerId)
.orElseThrow(() -> new IllegalArgumentException("Customer not found"));
}
@Tool("Update customer email address")
public String updateEmail(
@P("Customer ID") Long customerId,
@P("New email address") String newEmail) {
Customer customer = repository.findById(customerId)
.orElseThrow(() -> new IllegalArgumentException("Customer not found"));
customer.setEmail(newEmail);
repository.save(customer);
return "Email updated successfully";
}
}
@Component
public class ApiTools {
private final WebClient webClient;
@Tool("Get current stock price")
public String getStockPrice(@P("Stock symbol") String symbol) {
return webClient.get()
.uri("/api/stocks/{symbol}", symbol)
.retrieve()
.bodyToMono(String.class)
.block();
}
}
public class UserPreferencesTools {
@Tool("Get user preferences for a category")
public String getPreferences(
@ToolMemoryId String userId,
@P("Preference category (e.g., theme, language)") String category) {
return preferencesService.getPreferences(userId, category);
}
@Tool("Set user preference")
public String setPreference(
@ToolMemoryId String userId,
@P("Preference category") String category,
@P("Preference value") String value) {
preferencesService.setPreference(userId, category, value);
return "Preference saved";
}
}
public class DynamicToolProvider implements ToolProvider {
private final Map<String, Object> availableTools = new HashMap<>();
public void registerTool(String name, ToolSpecification spec, ToolExecutor executor) {
availableTools.put(name, new ToolWithSpec(spec, executor));
}
@Override
public ToolProviderResult provideTools(ToolProviderRequest request) {
var builder = ToolProviderResult.builder();
String message = request.userMessage().singleText().toLowerCase();
// Dynamically filter tools based on user message
if (message.contains("weather")) {
builder.add(weatherToolSpec, weatherExecutor);
}
if (message.contains("calculate") || message.contains("math")) {
builder.add(calculatorToolSpec, calculatorExecutor);
}
return builder.build();
}
}
有关详细的 API 参考、示例和高级模式,请参阅:
问题:LLM 调用不存在的工具
解决方案:实现幻觉处理器:
.hallucinatedToolNameStrategy(request -> {
return ToolExecutionResultMessage.from(request,
"Error: Tool '" + request.name() + "' does not exist");
})
问题:工具接收到无效参数
解决方案:添加输入验证和错误处理器:
.toolArgumentsErrorHandler((error, context) -> {
return ToolErrorHandlerResult.text("Invalid arguments: " + error.getMessage());
})
问题:工具执行缓慢或超时
解决方案:使用并发执行和弹性模式:
.executeToolsConcurrently(Executors.newFixedThreadPool(5))
.toolExecutionTimeout(Duration.ofSeconds(30))
langchain4j-ai-services-patternslangchain4j-rag-implementation-patternslangchain4j-spring-boot-integration每周安装次数
351
代码仓库
GitHub 星标数
173
首次出现
2026年2月3日
安全审计
安装于
claude-code275
gemini-cli270
opencode269
cursor265
codex264
github-copilot249
Define tools and enable AI agents to interact with external systems, APIs, and services using LangChain4j's annotation-based and programmatic tool system.
LangChain4j's tool system enables AI agents to execute external functions through declarative annotations and programmatic interfaces. Tools are defined using the @Tool annotation and automatically registered with AI services, allowing LLMs to perform actions beyond text generation such as database queries, API calls, and calculations.
Use this skill when:
Follow these steps to implement tools with LangChain4j:
Create methods annotated with @Tool in a class:
public class WeatherTools {
@Tool("Get current weather for a city")
public String getWeather(
@P("City name") String city,
@P("Temperature unit (celsius or fahrenheit)", required = false) String unit) {
// Implementation
return weatherService.getWeather(city, unit);
}
}
Use @P annotation for clear parameter descriptions that help the LLM understand how to call the tool:
@Tool("Calculate total order amount")
public double calculateOrderTotal(
@P("List of product IDs") List<String> productIds,
@P("Customer discount percentage", required = false) Double discount) {
// Implementation
}
Connect tools to an AI service using the AiServices builder:
MathAssistant assistant = AiServices.builder(MathAssistant.class)
.chatModel(chatModel)
.tools(new Calculator(), new WeatherService())
.build();
Implement error handling for tool failures:
AiServices.builder(Assistant.class)
.chatModel(chatModel)
.tools(new ExternalServiceTools())
.toolExecutionErrorHandler((request, exception) -> {
log.error("Tool execution failed: {}", exception.getMessage());
return "An error occurred while processing your request";
})
.build();
Track tool calls for debugging and analytics:
Result<String> result = assistant.chat(question);
result.toolExecutions().forEach(execution ->
log.info("Executed tool: {} in {}ms",
execution.request().name(),
execution.duration().toMillis())
);
// 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();
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();
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 + "!";
}
}
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);
}
}
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);
}
}
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);
}
}
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();
}
}
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);
}
}
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();
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);
});
}
}
@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();
}
}
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();
executeToolsConcurrently() for independent toolspublic class CalculatorTools {
@Tool("Add two numbers")
public double add(@P("First number") double a,
@P("Second number") double b) {
return a + b;
}
@Tool("Multiply two numbers")
public double multiply(@P("First number") double a,
@P("Second number") double b) {
return a * b;
}
}
// Usage
interface MathAssistant {
String ask(String question);
}
MathAssistant assistant = AiServices.builder(MathAssistant.class)
.chatModel(chatModel)
.tools(new CalculatorTools())
.build();
String result = assistant.ask("What is 15 times 7 plus 3?");
@Component
public class DatabaseTools {
private final CustomerRepository repository;
@Tool("Get customer information by ID")
public Customer getCustomer(@P("Customer ID") Long customerId) {
return repository.findById(customerId)
.orElseThrow(() -> new IllegalArgumentException("Customer not found"));
}
@Tool("Update customer email address")
public String updateEmail(
@P("Customer ID") Long customerId,
@P("New email address") String newEmail) {
Customer customer = repository.findById(customerId)
.orElseThrow(() -> new IllegalArgumentException("Customer not found"));
customer.setEmail(newEmail);
repository.save(customer);
return "Email updated successfully";
}
}
@Component
public class ApiTools {
private final WebClient webClient;
@Tool("Get current stock price")
public String getStockPrice(@P("Stock symbol") String symbol) {
return webClient.get()
.uri("/api/stocks/{symbol}", symbol)
.retrieve()
.bodyToMono(String.class)
.block();
}
}
public class UserPreferencesTools {
@Tool("Get user preferences for a category")
public String getPreferences(
@ToolMemoryId String userId,
@P("Preference category (e.g., theme, language)") String category) {
return preferencesService.getPreferences(userId, category);
}
@Tool("Set user preference")
public String setPreference(
@ToolMemoryId String userId,
@P("Preference category") String category,
@P("Preference value") String value) {
preferencesService.setPreference(userId, category, value);
return "Preference saved";
}
}
public class DynamicToolProvider implements ToolProvider {
private final Map<String, Object> availableTools = new HashMap<>();
public void registerTool(String name, ToolSpecification spec, ToolExecutor executor) {
availableTools.put(name, new ToolWithSpec(spec, executor));
}
@Override
public ToolProviderResult provideTools(ToolProviderRequest request) {
var builder = ToolProviderResult.builder();
String message = request.userMessage().singleText().toLowerCase();
// Dynamically filter tools based on user message
if (message.contains("weather")) {
builder.add(weatherToolSpec, weatherExecutor);
}
if (message.contains("calculate") || message.contains("math")) {
builder.add(calculatorToolSpec, calculatorExecutor);
}
return builder.build();
}
}
For detailed API reference, examples, and advanced patterns, see:
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");
})
Problem : Tools receive invalid parameters
Solution : Add input validation and error handlers:
.toolArgumentsErrorHandler((error, context) -> {
return ToolErrorHandlerResult.text("Invalid arguments: " + error.getMessage());
})
Problem : Tools are slow or timeout
Solution : Use concurrent execution and resilience patterns:
.executeToolsConcurrently(Executors.newFixedThreadPool(5))
.toolExecutionTimeout(Duration.ofSeconds(30))
langchain4j-ai-services-patternslangchain4j-rag-implementation-patternslangchain4j-spring-boot-integrationWeekly Installs
351
Repository
GitHub Stars
173
First Seen
Feb 3, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
claude-code275
gemini-cli270
opencode269
cursor265
codex264
github-copilot249
AI 代码实施计划编写技能 | 自动化开发任务分解与 TDD 流程规划工具
43,400 周安装
Go命名规范详解:Google官方风格指南与最佳实践
263 周安装
Mole Mac 清理工具 - macOS 系统优化与磁盘空间管理 CLI 工具
263 周安装
React Three Fiber 后期处理教程:Bloom辉光、Vignette暗角等效果实现
263 周安装
React-PDF 使用指南:在 React 中生成 PDF 的完整教程与最佳实践
263 周安装
Legal Advisor - Claude AI 法律顾问技能,智能法律咨询与文档分析助手
263 周安装
飞书CLI工具箱:13个功能模块命令速查,高效管理电子表格、日历、任务、文件等
263 周安装