Koog 1.0 idioms, gotchas, and scaffolding skills for Kotlin agents on the JVM
89
89%
Does it follow best practices?
Impact
89%
1.78xAverage score across 47 eval scenarios
Advisory
Suggest reviewing before use
A developer maintains a Koog 0.7.x agent that uses a hand-authored graph strategy with a tool loop, and constructs its LLM client by hand so it can share one tuned HTTP client (timeouts, corporate proxy) across the whole app. They also inject a clock so the run timestamps are testable.
build.gradle.kts:
plugins {
kotlin("jvm") version "2.0.21"
application
}
dependencies {
implementation("ai.koog:koog-agents:0.7.1")
implementation("io.ktor:ktor-client-cio:2.3.12")
}
kotlin {
jvmToolchain(11)
}Strategy.kt:
import ai.koog.agents.core.dsl.builder.strategy
import ai.koog.agents.core.dsl.extension.*
val weatherChat = strategy<String, String>("weather-chat") {
val callModel by nodeLLMRequest()
val runTools by nodeExecuteTools() // tool results are written back to the prompt automatically
edge(nodeStart forwardTo callModel)
edge(callModel forwardTo runTools onToolCall { true })
edge(callModel forwardTo nodeFinish onAssistantMessage { true })
edge(runTools forwardTo callModel) // loop back to the model after the tools have run
}Main.kt:
import ai.koog.agents.core.agent.AIAgent
import ai.koog.prompt.executor.clients.openai.OpenAILLMClient
import ai.koog.prompt.executor.clients.openai.OpenAIModels
import ai.koog.prompt.executor.llms.SingleLLMPromptExecutor
import io.ktor.client.HttpClient
import io.ktor.client.engine.cio.CIO
import kotlinx.coroutines.runBlocking
import kotlin.time.Clock
fun main() = runBlocking {
val sharedHttp = HttpClient(CIO) {
// tuned timeouts + corporate proxy shared across the app
}
val client = OpenAILLMClient(System.getenv("OPENAI_API_KEY"), httpClient = sharedHttp)
val executor = SingleLLMPromptExecutor(client)
val agent = AIAgent.invoke(
promptExecutor = executor,
strategy = weatherChat,
llmModel = OpenAIModels.Chat.GPT4o,
systemPrompt = "You are a weather assistant.",
toolRegistry = weatherTools,
clock = Clock.System,
)
println(agent.run("What's the weather in Paris?"))
}They want to bring this project to Koog 1.0 with the same behavior — keep the shared, tuned HTTP client and the injectable clock. They're on JDK 11 today.
Walk through every change required to compile and run this against Koog 1.0. Produce the changed build.gradle.kts, Strategy.kt, and Main.kt as a single response, each file clearly labeled.
.gemini
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10
scenario-11
scenario-12
scenario-13
scenario-14
scenario-15
scenario-16
scenario-17
scenario-18
scenario-19
scenario-20
scenario-21
scenario-22
scenario-23
scenario-24
scenario-25
scenario-26
scenario-27
scenario-28
scenario-29
scenario-30
scenario-31
scenario-32
scenario-33
scenario-34
scenario-35
scenario-36
scenario-37
scenario-38
scenario-39
scenario-40
scenario-41
scenario-42
scenario-43
scenario-44
scenario-45
scenario-46
scenario-47
skills
add-observability
add-persistence
add-rag
add-structured-output
add-token-budgeting
add-tool
cache-llm-calls
define-prompt
domain-model-subtask-pipeline
references
enable-prompt-caching
handle-agent-events
manage-state
migrate-from-0-x
model-planner-subtasks
persist-chat-history
query-sql-from-agent
scaffold-agent
snapshot-and-restore
test-koog-agents
trace-agent-internals
use-attachments
use-functional-agent
use-llm-node-variants
use-planner
wire-a2a
wire-acp-server
wire-ktor-server
wire-mcp-server
wire-spring-boot