Koog 1.3 idioms, gotchas, and scaffolding skills for Kotlin agents on the JVM
72
91%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Low
Low-risk findings worth noting
Add ai.koog:agents-features-snapshot:1.3.0. Adapt the prefix and continuation
nodes to the existing graph. This in-memory example compares two continuations
from one saved checkpoint without repeating the prefix. The capture output ends
the initial run; only explicitly tagged fork outputs enter the continuation. Use durable storage for
recovery in a later process.
import ai.koog.agents.core.agent.AIAgent
import ai.koog.agents.core.agent.execution.path
import ai.koog.agents.core.dsl.builder.node
import ai.koog.agents.core.dsl.builder.strategy
import ai.koog.agents.snapshot.feature.AgentCheckpointData
import ai.koog.agents.snapshot.feature.Persistence
import ai.koog.agents.snapshot.feature.withPersistence
import ai.koog.agents.snapshot.providers.InMemoryPersistenceStorageProvider
import ai.koog.prompt.executor.clients.openai.OpenAIModels
import ai.koog.prompt.executor.model.PromptExecutor
import ai.koog.serialization.JSONPrimitive
import ai.koog.serialization.typeToken
fun checkpointForkAgent(
executor: PromptExecutor,
onPrefix: () -> Unit,
onCheckpoint: (AgentCheckpointData) -> Unit,
onContinuation: (String) -> Unit = {},
): AIAgent<String, String> {
val graph =
strategy<String, String>("checkpoint-fork") {
val prepare by node<String, String> { input ->
onPrefix()
input
}
val branchPoint by node<String, String> { input ->
val captureOutput = "capture:$input"
val checkpoint =
withPersistence { context ->
createCheckpointAfterNode(
agentContext = context,
nodePath = context.executionInfo.path(),
lastOutput = captureOutput,
lastOutputType = typeToken<String>(),
version = 0L,
)
}
onCheckpoint(
requireNotNull(checkpoint) {
"Register a supported serializer and ensure node output and stored values are serializable"
},
)
captureOutput
}
val continueBranch by node<String, String> { input ->
val variant = input.removePrefix("fork:")
onContinuation(variant)
"result:$variant"
}
edge(nodeStart forwardTo prepare)
edge(prepare forwardTo branchPoint)
edge(branchPoint forwardTo continueBranch onCondition { it.startsWith("fork:") })
edge(branchPoint forwardTo nodeFinish onCondition { it.startsWith("capture:") })
edge(continueBranch forwardTo nodeFinish)
}
return AIAgent(
promptExecutor = executor,
llmModel = OpenAIModels.Chat.GPT4o,
strategy = graph,
) {
install(Persistence) {
storage = InMemoryPersistenceStorageProvider()
enableAutomaticPersistence = false
}
}
}
suspend fun compareCheckpointBranches(
agent: AIAgent<String, String>,
checkpoint: AgentCheckpointData,
): Pair<String, String> {
val graphState =
requireNotNull(checkpoint.graphProperties) {
"Supply a checkpoint from the matching graph strategy; planner checkpoints cannot be forked here"
}
suspend fun branch(variant: String): String =
Persistence.runFromCheckpoint(
agent = agent,
input = "",
checkpoint =
AgentCheckpointData(
checkpointId = checkpoint.checkpointId,
createdAt = checkpoint.createdAt,
messageHistory = checkpoint.messageHistory,
llmParams = checkpoint.llmParams,
version = checkpoint.version,
graphProperties = graphState.copy(lastOutput = JSONPrimitive("fork:$variant")),
properties = checkpoint.properties,
llmModel = checkpoint.llmModel,
tools = checkpoint.tools,
storage = checkpoint.storage,
agentIterations = checkpoint.agentIterations,
),
sessionId = "fork-$variant",
)
return branch("A") to branch("B")
}.tessl-plugin
skills
add-observability
add-persistence
references
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
references
test-koog-agents
trace-agent-internals
use-agent-skills
references
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