Building Java AI Agents with Koog: A Hands‑On Guide to Native Java Agent APIs
JetBrains' newly released Koog for Java provides a native Java AI Agent framework that lets developers annotate methods as tools, assemble agents with a Builder‑style API, and let large language models orchestrate multi‑step tasks without writing explicit control flow, as demonstrated with banking and e‑commerce examples.
What is Koog for Java?
Koog for Java is an AI‑agent framework that provides a native Java Builder‑style API. It enables agents to perform reliable multi‑step tasks, manage tool‑call chains, and keep intermediate state without requiring explicit conditional logic in user code.
Motivation
The framework was created because JetBrains’ earlier AI Assistant relied on a Python service for agent orchestration. As the system grew to require complex multi‑step workflows, the Python‑based approach became a bottleneck, prompting a JVM‑native solution.
Defining tools with annotations
Any public method can be exposed as a tool by annotating it with @Tool and describing its purpose and parameters with @LLMDescription. Example:
public class BankingTools implements ToolSet {
@Tool
@LLMDescription("Transfer money to a specified recipient")
public Boolean sendMoney(
@LLMDescription("Recipient unique ID") String recipientId,
@LLMDescription("Amount in yuan") Integer amount) {
// transfer logic
return true;
}
@Tool
@LLMDescription("Query user account balance, return amount")
public Integer getAccountBalance(
@LLMDescription("User ID") String userId) {
// balance query logic
return 1_000_000;
}
}Building an agent
The Builder API configures the LLM provider, system prompt, and a registry of tools. The agent then runs a user request, letting the LLM decide which tools to invoke.
MultiLLMPromptExecutor promptExecutor = new MultiLLMPromptExecutor(
new OpenAILLMClient("OPENAI_API_KEY")
);
AIAgent bankingAgent = AIAgent.builder()
.promptExecutor(promptExecutor)
.llmModel(OpenAIModels.Chat.GPT5_4)
.systemPrompt("You are a banking assistant that can check balances and make transfers.")
.toolRegistry(ToolRegistry.builder()
.tools(new BankingTools())
.build())
.build();
bankingAgent.run("Check if I have enough balance, and if so transfer 500 yuan to wang_0056.");When executed, the LLM first calls getAccountBalance to verify funds, then calls sendMoney to complete the transfer, all without explicit if‑else code.
E‑Commerce customer‑service agent
Typical use case: an online store needs an agent that can query orders, check inventory, and place new orders.
Maven dependency
<dependency>
<groupId>ai.koog</groupId>
<artifactId>koog-agents-jvm</artifactId>
<version>0.7.2</version>
</dependency>Tool definitions
public class ECommerceTools implements ToolSet {
@Tool
@LLMDescription("Query order status by order ID, return details")
public String queryOrder(@LLMDescription("Order ID, e.g., ORD-20260325-001") String orderId) {
return "Order " + orderId + " status: shipped, expected delivery tomorrow";
}
@Tool
@LLMDescription("Check inventory quantity by product name")
public String checkInventory(@LLMDescription("Product name, e.g., mechanical keyboard") String productName) {
return productName + " current stock: 128 units";
}
@Tool
@LLMDescription("Create a new order for the user")
public String createOrder(@LLMDescription("User ID") String userId,
@LLMDescription("Product name") String productName,
@LLMDescription("Quantity") Integer quantity) {
String orderId = "ORD-" + System.currentTimeMillis();
return "Order placed successfully, order ID: " + orderId + ", product: " + productName + " x " + quantity;
}
}Agent assembly
MultiLLMPromptExecutor promptExecutor = new MultiLLMPromptExecutor(
new OpenAILLMClient("OPENAI_API_KEY")
);
AIAgent customerServiceAgent = AIAgent.builder()
.promptExecutor(promptExecutor)
.llmModel("deepseek-chat")
.systemPrompt("你是一个电商平台的智能客服。用简洁友好的中文回答用户问题。你可以帮用户查订单、查库存、下单。如果用户的问题超出你的能力范围,礼貌地建议用户联系人工客服。")
.toolRegistry(ToolRegistry.builder()
.tools(new ECommerceTools())
.build())
.build();
customerServiceAgent.run("帮我看看订单 ORD-20260325-001 到哪了");The LLM automatically calls queryOrder and returns the result in Chinese. If the user requests a purchase, the LLM first calls checkInventory and, when stock is sufficient, calls createOrder —all without developer‑written branching.
Strict functional strategy
For tighter control, a custom functional strategy can separate intent detection from tool execution:
AIAgent strictAgent = AIAgent.builder()
.promptExecutor(promptExecutor)
.functionalStrategy("strict-order-flow", (ctx, userInput) -> {
// Step 1: Determine intent
String intent = ctx.subtask("Determine user intent, return only: query order, check inventory, place order, other. User says: " + userInput)
.withOutput(String.class)
.run();
// Step 2: Execute the appropriate tool
String result = ctx.subtask("Execute operation based on intent: " + intent)
.withOutput(String.class)
.withTools(new ECommerceTools())
.run();
return result;
})
.build();This two‑step flow makes the decision points explicit, improving predictability and debuggability.
Conclusion
As of 2026, the Java AI‑agent ecosystem includes Spring AI (infrastructure) and LangChain4j (unified API). Koog fills the gap by providing JVM‑native agent orchestration with a Builder pattern, annotation‑driven tool registration, and optional functional strategies, making it straightforward to integrate reliable multi‑step agents into Java applications.
Java Architecture Diary
Committed to sharing original, high‑quality technical articles; no fluff or promotional content.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
