Koog 1.2 idioms, gotchas, and scaffolding skills for Kotlin agents on the JVM
71
89%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Low
Low-risk findings worth noting
AIAgent(...) factoryAIAgent is an expect abstract class with three concrete subtypes — GraphAIAgent, FunctionalAIAgent, PlannerAIAgent. Don't construct these directlyAIAgent(...) in ai.koog.agents.core.agent.AIAgentFactory — it returns the right concrete subtype for the strategy you pass ininvoke constructor (AIAgent.invoke(...)) was removed in 1.0 (#1882). The call site AIAgent(...) looks unchanged but it now resolves to the top-level factoryinstallFeatures: GraphAIAgent.FeatureContext.() -> Unit = {} — install OpenTelemetry, event handlers, long-term memory, persistence, and other features inside that blocksingleRunStrategy() is the defaultsingleRunStrategy(parallelTools: Boolean = false). It's the default; omit it from the call unless you're overriding itauthor-strategy skillThe cap is one underlying value, AIAgentConfig.maxAgentIterations, reached by two different parameter names depending on which overload you call. Verified against 1.2.0.
promptExecutor + llmModel + optional systemPrompt) expose it as maxIterations, defaulting to 50. There is no maxAgentIterations parameter on these — passing that name matches no overload, and the compiler then reports a cascade of unrelated errors inside the trailing lambda rather than naming the bad argumentagentConfig overloads take no cap parameter at all. Set maxAgentIterations on the AIAgentConfig you pass inAIAgentConfig.withSystemPrompt(...) defaults maxAgentIterations to 3. That is the trap: the same graph that runs on the convenience overload's 50 aborts on a config built this way. Set it explicitly whenever you build a config by handAIAgentMaxNumberOfIterationsReachedException — see the author-strategy skillid for production agents so traces and persistence records correlate across runs — auto-generated IDs make logs unreadableKoogClock.System (the default) in production; inject a fake KoogClock in tests so deterministic test runs don't drift on real wall timeAgentMemory was removed in 1.0AgentMemory feature — it doesn't exist anymore. Use LongTermMemory for cross-session memory; reach for it via the manage-state skillAIAgentContext.storage automatically and is serialized into checkpointsauthor-strategysubgraphWithTask<In, Out> per phase, verify/adjust loops) → domain-model-subtask-pipelineuse-plannerstorage, history compression, or LongTermMemory → manage-stateadd-tool; connecting to an MCP server → wire-mcp-serveradd-observabilitywire-spring-boot; Ktor plugin → wire-ktor-servermigrate-from-0-x.tessl-plugin
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-agent-skills
use-attachments
use-cli-agents
use-functional-agent
use-llm-node-variants
use-planner
wire-a2a
wire-acp-server
wire-ktor-server
wire-mcp-server
wire-spring-boot