Teaches AI agents to write idiomatic Kotlin (data classes, val, scope fns, Kotest) AND to make the right stack choices on JVM: Kotlin 2.3 + JDK 21 + Gradle Kotlin DSL, Ktor for HTTP, kotlinx-coroutines, DJL for ML inference, JavaCV for vision, Koog for AI agent orchestration.
95
95%
Does it follow best practices?
Impact
95%
1.23xAverage score across 10 eval scenarios
Passed
No known issues
ai.koog:koog-agents, current 1.0.0-preview3 — release candidate ahead of the upcoming 1.0 GA; 0.8.0 is the latest stable if you can't take a pre-release)1.0.0-preview*) and beta (1.0.0-beta-preview*) streams so production code can pin to APIs that won't break without a deprecation cycleimplementation("ai.koog:koog-agents:1.0.0-preview3")KoogHttpClient.Factory), AgentMemory removed in favor of LongTermMemory, Java blocking methods renamed to *Blocking, planners moved to a separate agents:agents-planners module. Full list in the initial 1.0.0-preview release notes; preview2 / preview3 add follow-up bug fixes onlyPromptExecutor.builder().anthropic(apiKey).build() (same shape for .openAI(...), .google(...), .ollama(...)). The 0.7.x / 0.8.0 simpleAnthropicExecutor(apiKey) convenience is gone in 1.0 — PromptExecutor.builder() is the replacementAIAgent(...) is a top-level factory function and strategy is required, not optional. The shape is AIAgent(promptExecutor = ..., llmModel = ..., strategy = ..., systemPrompt = ...) — the 0.7.x signature without strategy does not compile against 1.0functionalStrategy<I, O> { input -> ... } factory in ai.koog.agents.core.agentthis is AIAgentFunctionalContext, not a second context argrequestLLM(input) returns Message.Assistant with parts: List<MessagePart>, not a .content / .text string; extract via parts.filterIsInstance<MessagePart.Text>().joinToString("\n") { it.text } (explicit separator — the default ", " will insert commas between parts)AIAgent.builder().functionalStrategy(BiFunction<...>) overload exists but is blocking; Kotlin code uses the top-level functionalStrategy factory so suspend calls (like requestLLM) workanthropicClient(...) or AnthropicClientFactory from ai.koog.prompt.executor.clients.anthropic directly — the bytecode advertises them as a top-level facade but they're not resolvable from Kotlin source against Kotlin 2.3.0. Use PromptExecutor.builder().anthropic(key) insteadAnthropicModels.Sonnet_4 / Opus_4_*, OpenAIModels.Chat.GPT4o, the relevant Gemini model for Google, Ollama integration for localagent.run(input) is suspend — call from runBlocking { } at the top levelai.koog:koog-agents:0.8.0. The 0.8.0 API matches 0.7.3: simpleAnthropicExecutor(apiKey) for the executor, AIAgent(promptExecutor, llmModel, systemPrompt) for the agent — no strategy required, no functionalStrategy needed. This is the explicit "stay on stable" code path; everything else in this rule targets the 1.0 preview lineAIAgentService.fromAgent(...).createAgentTool(...), then register it in the parent's ToolRegistry. Each sub-agent invocation gets a fresh context — pass anything it needs explicitly via its system prompt (see jbaruch/sub-agent-delegation)kotlinx-serialization-json — more robust than free-form natural languageanthropic-sdk-python, claude-agent-sdk) from a Kotlin app to orchestrate sub-agentsHttpClient calls to Anthropic — you'll reinvent retries, conversation history, tool calling, and break before you shipGlobalScope.launch { agent.run(...) } — unowned scope, leaks; use structured concurrencyPredictor or LLM client across non-coroutine threads