CtrlK
BlogDocsLog inGet started
Tessl Logo

jbaruch/koog

Koog 1.0 idioms, gotchas, and scaffolding skills for Kotlin agents on the JVM

91

1.73x
Quality

89%

Does it follow best practices?

Impact

92%

1.73x

Average score across 47 eval scenarios

SecuritybySnyk

Advisory

Suggest reviewing before use

Overview
Quality
Evals
Security
Files

Evaluation results

100%

100%

Ground an Agent in a Documentation Corpus

Embed and retrieve from a docs corpus as an agent tool

Criteria
Without context
With context

Exposes retrieval as a Tool, not as an augmenter

0%

100%

Builds an embedder from a provider

0%

100%

Builds a vector store and indexes documents

0%

100%

Adds the RAG and embeddings dependencies

0%

100%

Registers the search tool with the agent's ToolRegistry

0%

100%

Search tool returns formatted results, not raw vector hits

0%

100%

63%

63%

Expose a Koog Agent on an HTTP Endpoint

Expose an agent over a Ktor HTTP route

Criteria
Without context
With context

Installs the Koog Ktor plugin

0%

66%

Adds the koog-ktor dependency

0%

65%

Configures the prompt executor inside the install block

0%

33%

Reads the OpenAI API key from the environment

0%

90%

Adds a POST /agent route

0%

86%

Resolves the agent from the plugin attribute

0%

30%

100%

100%

Delegate Heavy Analysis to a Remote Agent

Consume a remote A2A agent as a tool

Criteria
Without context
With context

Uses A2AClient to call the remote

0%

100%

Adds a2a-core and a2a-client dependencies

0%

100%

Wraps the A2A call inside a tool

0%

100%

Reads the bearer token from the environment

0%

100%

Registers the wrapper tool with the agent

0%

100%

100%

100%

Send Agent Traces to Langfuse

Install Langfuse exporter via the OpenTelemetry feature

Criteria
Without context
With context

Adds the agents-features-opentelemetry dependency

0%

100%

Installs OpenTelemetry in the trailing lambda

0%

100%

Calls addLangfuseExporter inside the install block

0%

100%

Sets langfuse.session.id from the environment

0%

100%

Turns on verbose mode

0%

100%

Does not stack a second backend integration

0%

100%

100%

100%

Compress History Between Phases of a Long Run

Compress conversation history with TL;DR mid-run

Criteria
Without context
With context

Calls replaceHistoryWithTLDR inside llm.writeSession

0%

100%

Compresses only at the boundary node, not every node

0%

100%

Picks WholeHistory or equivalent TL;DR strategy

0%

100%

Does not introduce LongTermMemory

0%

100%

Compression happens before the next LLM call in drafting

0%

100%

100%

100%

Find Out Why an Agent Is Stuck in a Loop

Install Trace feature with edge and node events for local debugging

Criteria
Without context
With context

Installs the Trace feature

0%

100%

Adds the agents-features-trace dependency

0%

100%

Captures EDGE_EVALUATION events

0%

100%

Captures NODE_ENTRY events

0%

100%

Sends trace to a local sink

0%

100%

100%

100%

Send a User-Uploaded Screenshot to the Agent

Attach a user-uploaded image via Attachment.image()

Criteria
Without context
With context

Uses Attachment.image to wrap the file

0%

100%

Constructs a Message.User with attachments

0%

100%

Sends via nodeLLMSendMessage, not nodeLLMRequest

0%

100%

Strategy is typed strategy<File, String>

0%

100%

Returns text from a final nodeFinish edge

0%

100%

100%

100%

Contract and Product Image Analyzer

PDF and URL image attachments in one agent call

Criteria
Without context
With context

PDF via Attachment.file

0%

100%

Image via Attachment.image(url)

0%

100%

Anthropic model with PDF support

0%

100%

No manual file encoding

0%

100%

Both attachments in one Message.User

0%

100%

Runtime attachment construction in node body

0%

100%

Sends via nodeLLMSendMessage

0%

100%

100%

100%

Wrap a Smaller Agent as a Tool for a Bigger One

Sub-agent-as-tool via AIAgentService.fromAgent

Criteria
Without context
With context

Uses AIAgentService.fromAgent to wrap the find agent

0%

100%

Calls createAgentTool with typed input/output

0%

100%

Provides agentDescription and inputDescription for the LLM

0%

100%

Preserves the find agent's separate configuration

0%

100%

Registers the wrapped tool in the main agent's ToolRegistry

0%

100%

Does not introduce a strategy graph or subgraph

0%

100%

95%

95%

Build a Triage Agent Whose Steps Depend on Findings

Construct PlannerAIAgent with Planners.llmBased

Criteria
Without context
With context

Picks the LLM-based planner primitive

0%

100%

Adds the separate planner module dependency

0%

75%

Passes the planner as the strategy parameter

0%

100%

Sets a much higher maxIterations than the default

0%

100%

Includes the lookup tools in the registry

0%

100%

Uses top-level AIAgent factory

0%

100%

100%

100%

Make a Koog Agent Cancellable from an IDE Plugin

Wire an ACP server with cancellation support

Criteria
Without context
With context

Installs the ACP feature

0%

100%

Adds the agents-features-acp dependency

0%

100%

Makes the long-running tool honor cancellation

0%

100%

Notes that catching CancellationException would defeat cancel

0%

100%

Mentions the example or feature module's API

0%

100%

Does not block on coroutine internals

0%

100%

93%

93%

Let an Analytics Agent Read From the Events Table

Install the Sql feature with read-only mode and schema scope

Criteria
Without context
With context

Installs the Sql feature in read-only mode

0%

100%

Scopes the schema to the named tables

0%

100%

Caps result rows

0%

100%

Reads DB credentials from environment

0%

100%

Pins schema in system prompt

0%

66%

Adds the agents-features-sql dependency and JDBC driver

0%

60%

100%

100%

Build a Minimal Text-Transform Agent

Build a single-block FunctionalAIAgent

Criteria
Without context
With context

Uses the functional-agent factory

0%

100%

Strategy block is a single suspending block

0%

100%

Trims the LLM response inside the block

0%

100%

Includes the system prompt for formal-English rewriting

0%

100%

Reads OPENAI_API_KEY from environment

0%

100%

No tools registered

0%

100%

100%

100%

Write a Deterministic Unit Test for a Koog Agent

Test with TestPromptExecutor.scripted and an event recorder

Criteria
Without context
With context

Adds agents-test as testImplementation

0%

100%

Uses a scripted/mocked prompt executor

0%

100%

Records tool-call sequence via handleEvents

0%

100%

Asserts ordering — lookup_priority before classification

0%

100%

Tools run their real implementations

0%

100%

Single agent.run call per test

0%

100%

100%

100%

Wire a Spring Boot App With Two LLM Providers

Configure two LLM providers via Spring Boot autoconfig

Criteria
Without context
With context

Configures both providers under ai.koog.<provider>

0%

100%

Reads both keys from environment variables

0%

100%

Migrates service code from LLMClient to MultiLLMPromptExecutor

0%

100%

Routes by model at the call site

0%

100%

Does not introduce a custom @Bean LLMClient override

0%

100%

Does not remove the starter dependency

0%

100%

100%

100%

Add a Weather Lookup Function to an Existing Agent

Annotated ToolSet for a String-in/String-out function

Criteria
Without context
With context

Picks the annotated ToolSet style

0%

100%

Annotates parameters with @LLMDescription

0%

100%

Annotates the class and method with @LLMDescription

0%

100%

Registers via ToolRegistry DSL

0%

100%

Passes the registry into AIAgent at construction

0%

100%

Does not introduce typed args classes

0%

100%

100%

100%

Author a Generate → Verify → Fix Strategy

Custom strategy graph with subgraphWithVerification and fix

Criteria
Without context
With context

Uses subgraphWithTask and subgraphWithVerification

0%

100%

Conditional edge from verify drives the loop

0%

100%

Fix loops back to verify

0%

100%

Each subgraph has its own tools set

0%

100%

Verifier uses a cheaper model than fixer

0%

100%

Top-level strategy<Input, Output>(name) declaration

0%

100%

100%

100%

Cache a Long System Prompt for Anthropic Calls

cacheControl breakpoint on a long Anthropic system prompt

Criteria
Without context
With context

Uses cacheControl on the system segment

0%

100%

Mentions Anthropic minimum-token requirement

0%

100%

Places the breakpoint at end of system content

0%

100%

Uses the prompt DSL builder

0%

100%

References observability for cache-hit verification

0%

100%

Does not change the agent's model

0%

100%

100%

100%

Stream the Agent's Reply to the Caller

Stream LLM reply via nodeLLMRequestStreaming

Criteria
Without context
With context

Uses nodeLLMRequestStreaming

0%

100%

Supplies a chunk handler lambda

0%

100%

Names that the handler must not block

0%

100%

Wires the streaming node into a top-level strategy<...>

0%

100%

Does not include tool nodes

0%

100%

96%

96%

Cap an Agent's Token Spend with Graceful Degradation

Cap token spend with history compression on overrun

Criteria
Without context
With context

Installs the Tokenizer feature

0%

100%

Sets a 50000 runBudget

0%

100%

Picks BudgetAction.CompressHistory

0%

100%

Adds the tokenizer dependencies

0%

100%

Does not lower the model to a cheaper one

0%

100%

Notes how the cap surfaces in observability if installed

0%

20%

100%

100%

Build a Prompt With Few-Shot Examples

Build a prompt DSL with few-shot examples

Criteria
Without context
With context

Uses the prompt { ... } DSL builder

0%

100%

System turn names the classification task

0%

100%

Each example is a user/assistant pair

0%

100%

Examples are inline literal strings

0%

100%

Imports prompt builder from ai.koog.prompt.dsl

0%

100%

Does not introduce a PromptAugmenter

0%

100%

95%

95%

Make a Long-Running Planner Agent Survive Restarts

Install the Persistence feature for planner crash recovery

Criteria
Without context
With context

Installs the Persistence feature

0%

100%

Adds the JDBC persistence backend dependency

0%

100%

Configures the backend with the JDBC connection

0%

100%

Uses Persistence type names, not Persistency

0%

100%

Shows resume path with runFromCheckpoint

0%

100%

Notes serializability requirement for storage

0%

0%

100%

100%

Scaffold a New Agent Project from Scratch

Scaffold a new Koog 1.0 OpenAI project from scratch

Criteria
Without context
With context

Uses 1.0+ umbrella coordinate

0%

100%

Targets JDK 17 toolchain

0%

100%

Uses top-level AIAgent factory

0%

100%

Reads API key from environment

0%

100%

Wires simpleOpenAIExecutor and a current OpenAI model

0%

100%

Omits the default singleRunStrategy

0%

100%

Runs the agent inside runBlocking

0%

100%

Initializes git in the new directory

0%

100%

Application plugin wired with mainClass

0%

100%

100%

100%

Fork an Agent Run to Compare Two Strategy Variants

Caller-triggered snapshot with runFromSnapshot fork

Criteria
Without context
With context

Installs the Snapshot feature

0%

100%

Adds the agents-features-snapshot dependency

0%

100%

Calls snapshot() at the decision point

0%

100%

Demonstrates two runFromSnapshot calls

0%

100%

Notes serializability requirement

0%

100%

100%

100%

Bump a 0.x Codebase Using AgentMemory to 1.0

Replace removed AgentMemory with LongTermMemory

Criteria
Without context
With context

Replaces AgentMemory with LongTermMemory

0%

100%

Renames queryExtractor and extractionStrategy

0%

100%

Removes IngestionTiming

0%

100%

Drops .invoke from the AIAgent call

0%

100%

Adds the new LongTermMemory dependency

0%

100%

Bumps JDK target to 17

0%

100%

Updates all Koog coordinates to 1.0+

0%

100%

63%

63%

Model a Research Workflow as Parallel Subtasks

Compose PlannerNode tree with parallel inside sequential

Criteria
Without context
With context

Uses PlannerNode.parallel inside PlannerNode.sequential

0%

60%

Builds the agent with PlannerAIAgent / Planners.*

0%

60%

Tracks current subtask via storage key

0%

25%

Adds the planner module dependency

0%

100%

Sets maxIterations well above the default

0%

100%

Does not over-engineer with graph subgraphs

0%

60%

15%

15%

Scaffold an Agent into an Existing Empty Directory with Anthropic

Scaffold a Koog 1.0 Anthropic project into an empty existing directory

Criteria
Without context
With context

Uses simpleAnthropicExecutor

0%

0%

Selects a current Anthropic model

0%

0%

Reads ANTHROPIC_API_KEY from the environment

0%

0%

Accepts the existing-empty-directory state without overwrite

0%

100%

Uses 1.0+ umbrella coordinate

0%

0%

Top-level AIAgent factory call

0%

0%

83%

83%

Returning Users Lose Their Conversation

Install JDBC chat-history feature for per-user session resume

Criteria
Without context
With context

Installs the JDBC chat-history feature

0%

60%

Adds the JDBC chat-history dependency

0%

85%

Reads DB credentials from environment

0%

100%

Threads userId as sessionId on agent.run

0%

92%

Does not require user to thread message history manually

0%

100%

73%

73%

Expose an Account Lookup to the Agent

Tool<TArgs, TResult> subclass with typed input and output

Criteria
Without context
With context

Subclasses Tool<TArgs, TResult>

0%

60%

Declares a ToolDescriptor

0%

100%

Implements suspend execute(args) returning the typed result

0%

75%

Registers with the ToolRegistry DSL

0%

100%

Reuses the existing @Serializable data classes

0%

0%

Does not introduce a ToolSet wrapper

0%

100%

100%

100%

Add an MCP Server's Tools Alongside Existing Local Tools

Merge MCP registry with existing local ToolRegistry via +

Criteria
Without context
With context

Composes the two registries with +

0%

100%

Preserves the existing CalculatorTools registration

0%

100%

Uses the modern HTTP MCP transport

0%

100%

Adds the agents-mcp dependency

0%

100%

Constructs the merged registry before AIAgent(...)

0%

100%

Calls the suspending MCP builder inside a coroutine context

0%

100%

100%

100%

Add a Tool-Handling Loop to a Koog Strategy

Build a Koog strategy with a tool-handling loop and conditional branching; produce correct member-vs-extension imports for the DSL primitives

Criteria
Without context
With context

Imports the `onToolCalls` extension explicitly

0%

100%

Imports the `onTextMessage` extension explicitly

0%

100%

Does not invent a member import for `forwardTo`

0%

100%

Uses both edge primitives the loop needs

0%

100%

Chains `nodeExecuteTools` to `nodeLLMSendToolResults` explicitly

0%

100%

Wires the loop back through `nodeExecuteTool` on continued tool calls

0%

100%

100%

100%

Connect a Koog Agent to an Older MCP Server

Connect to an SSE-only MCP server; produce correct extension imports for `fromSseUrl` and the `-jvm:1.0.0-beta` dependency line

Criteria
Without context
With context

Picks the SSE transport

0%

100%

Imports the `fromSseUrl` extension explicitly

0%

100%

Pins the MCP artifact to `1.0.0-beta`

0%

100%

Uses the `-jvm` suffix on the artifact

0%

100%

Builds the registry before constructing the agent

0%

100%

Calls the suspending builder inside a coroutine context

0%

100%

100%

100%

Connect an Agent to the GitHub MCP Server

Wire Streamable HTTP MCP transport to a remote server

Criteria
Without context
With context

Uses the Streamable HTTP transport

0%

100%

Adds the agents-mcp dependency

0%

100%

Passes the server URL to the transport configuration

0%

100%

Builds the registry before constructing the agent

0%

100%

Calls the suspending builder inside a coroutine context

0%

100%

Reads the GitHub token from the environment

0%

100%

Passes the token as a bearer header in the transport config

0%

100%

100%

100%

Connect an Agent to a Locally Launched Playwright MCP Server

Wire stdio MCP transport against a local subprocess

Criteria
Without context
With context

Uses the process-based MCP transport

0%

100%

Launches the process with ProcessBuilder

0%

100%

Adds the agents-mcp dependency

0%

100%

Builds the registry before constructing the agent

0%

100%

Calls the suspending builder inside a coroutine context

0%

100%

Does not import Ktor or HTTP-client types

0%

100%

100%

100%

Build a Customer-Support Agent for a Bank

Build a support triage agent with four typed phases, sliced tools, and a verify/adjust loop

Criteria
Without context
With context

Tools sliced into communication / read / write ToolSets

0%

100%

Each phase grants only the matching tool subset

0%

100%

Typed @LLMDescription'd data classes for inter-phase handoffs

0%

100%

Uses subgraphWithTask<In, Out> for each phase

0%

100%

Verification + adjust loop with CriticResult branching

0%

100%

Mixed model selection per phase

0%

100%

Declares the required Gradle dependencies

0%

100%

100%

100%

See What the Agent Is Doing During a Demo

Print tool-call trace via handleEvents

Criteria
Without context
With context

Installs the event-handler feature

0%

100%

Adds the agents-features-event-handler dependency

0%

100%

Subscribes to onToolCallStarting

0%

100%

Subscribes to onToolCallFinished

0%

100%

Uses distinct visual markers for start vs end

0%

100%

Does not also install OpenTelemetry

0%

100%

100%

100%

Expose a Calendar ToolSet to Other Agents over MCP

Expose an existing ToolSet as a stdio MCP server

Criteria
Without context
With context

Calls startStdioMcpServer

0%

100%

Adds the agents-mcp-server dependency

0%

100%

Wraps the existing ToolSet in a ToolRegistry

0%

100%

Keeps the process alive after startup

0%

100%

Does not reach for the client transport surface

0%

100%

97%

97%

Migrate a Custom-Strategy Agent With a Shared HTTP Client to 1.0

Criteria
Without context
With context

Routes tool results through an explicit send-results node

0%

100%

Adapts the LLM client to the decoupled HTTP transport

0%

88%

Swaps kotlin.time.Clock for KoogClock

0%

100%

Raises the JDK and Kotlin toolchain minima

0%

100%

Drops .invoke from the AIAgent construction

0%

100%

Bumps all Koog coordinates to 1.0 with no mixed versions

0%

100%

100%

95%

Expose a Koog Agent to an Orchestration Dashboard

Criteria
Without context
With context

Chooses ACP for the tooling-client case

0%

100%

Adds the ACP dependency

0%

100%

Correct ACP import

0%

100%

install(ACP) in the AIAgent trailing lambda

0%

100%

Configures the endpoint inside install(ACP)

0%

100%

Notes progress events surface to the client

50%

100%

Rationale for ACP over A2A

0%

100%

95%

39%

Make a Long-Running Agent Survive Server Restarts

Redirect from Snapshot to Persistence for automatic crash recovery

Criteria
Without context
With context

Distinguishes caller-triggered from continuous save

32%

100%

Routes to the Persistence feature

73%

100%

Does NOT recommend installing the snapshot feature

100%

80%

Acknowledges the developer's word choice without capitulating

10%

100%

Mentions the cost of frequent checkpoints

0%

100%

100%

5%

Scaffold Into a Directory That Already Contains Files

Refuse to scaffold over an existing non-empty directory

Criteria
Without context
With context

Detects the non-empty state before writing

100%

100%

Refuses to proceed without explicit confirmation

100%

100%

Asks an explicit yes/no overwrite question

75%

100%

Names what would be overwritten

100%

100%

Leaves the directory unchanged on refusal

100%

100%

94%

21%

Build a "Planning" Agent for a Fully Known Workflow

Redirect from planner to graph DSL when topology is fixed

Criteria
Without context
With context

Names the topology as the disqualifying signal

92%

92%

Redirects to the graph DSL

26%

93%

Does not install agents-planner

90%

100%

Acknowledges the developer's framing without capitulating

93%

93%

Mentions the cost penalty of an unwarranted planner

100%

90%

65%

-4%

Make a Chatbot Remember Conversations Per User

Redirect from generic Persistence to chat-history for conversation resume

Criteria
Without context
With context

Identifies the three persistence layers in Koog

80%

0%

Routes to chat-history-jdbc

66%

100%

Does NOT install the generic Persistence feature

80%

100%

Acknowledges the developer's word choice without capitulating

40%

0%

Does NOT recommend LongTermMemory

50%

100%

60%

12%

Make an Agent Return a Typed Classification

Use responseProcessor for typed JSON output from the agent

Criteria
Without context
With context

Uses responseProcessor on the factory

0%

0%

Parameterizes AIAgent with the typed Output

100%

100%

Reuses the developer's data class verbatim

53%

100%

Drops the regex parsing

100%

100%

Does not introduce a custom strategy

0%

50%

70%

-14%

Build a Quick One-Shot Text Reformatter

Decline to apply the subtask-pipeline pattern when the workload is a single text-to-text transform with no phases

Criteria
Without context
With context

Names the absence of distinct phases as the disqualifier

100%

20%

Redirects to the simpler shape

100%

100%

Does not produce subgraphWithTask code

50%

100%

Does not introduce typed handoff data classes

60%

100%

Engages with the developer's framing without capitulating

100%

0%

90%

Cut Costs on a Long System Prompt That's Called Hundreds of Times a Day

Redirect from response cache to Anthropic prompt caching

Criteria
Without context
With context

Names the cache-vs-response distinction

100%

100%

Recommends the provider-side caching path

100%

93%

Does not wrap the executor in an in-process cache

100%

80%

Acknowledges the framing without capitulating

100%

70%

Mentions Anthropic's minimum-token requirement

0%

100%

95%

1%

Remember Which Excuses We've Already Sent

Refuses to use chat-history as a fact store

Criteria
Without context
With context

Does not install JdbcChatHistory / chat-history-jdbc

100%

100%

Recommends LongTermMemory or a Tool

93%

100%

Does not synthesise pseudo-turns into a custom ChatHistoryProvider

100%

100%

Names the chat-history-vs-fact-store distinction

60%

50%

Evaluated
Agent
Claude Code
Model
Claude Sonnet 4.6

Table of Contents

Ground an Agent in a Documentation CorpusExpose a Koog Agent on an HTTP EndpointDelegate Heavy Analysis to a Remote AgentSend Agent Traces to LangfuseCompress History Between Phases of a Long RunFind Out Why an Agent Is Stuck in a LoopSend a User-Uploaded Screenshot to the AgentContract and Product Image AnalyzerWrap a Smaller Agent as a Tool for a Bigger OneBuild a Triage Agent Whose Steps Depend on FindingsMake a Koog Agent Cancellable from an IDE PluginLet an Analytics Agent Read From the Events TableBuild a Minimal Text-Transform AgentWrite a Deterministic Unit Test for a Koog AgentWire a Spring Boot App With Two LLM ProvidersAdd a Weather Lookup Function to an Existing AgentAuthor a Generate → Verify → Fix StrategyCache a Long System Prompt for Anthropic CallsStream the Agent's Reply to the CallerCap an Agent's Token Spend with Graceful DegradationBuild a Prompt With Few-Shot ExamplesMake a Long-Running Planner Agent Survive RestartsScaffold a New Agent Project from ScratchFork an Agent Run to Compare Two Strategy VariantsBump a 0.x Codebase Using AgentMemory to 1.0Model a Research Workflow as Parallel SubtasksScaffold an Agent into an Existing Empty Directory with AnthropicReturning Users Lose Their ConversationExpose an Account Lookup to the AgentAdd an MCP Server's Tools Alongside Existing Local ToolsAdd a Tool-Handling Loop to a Koog StrategyConnect a Koog Agent to an Older MCP ServerConnect an Agent to the GitHub MCP ServerConnect an Agent to a Locally Launched Playwright MCP ServerBuild a Customer-Support Agent for a BankSee What the Agent Is Doing During a DemoExpose a Calendar ToolSet to Other Agents over MCPMigrate a Custom-Strategy Agent With a Shared HTTP Client to 1.0Expose a Koog Agent to an Orchestration DashboardMake a Long-Running Agent Survive Server RestartsScaffold Into a Directory That Already Contains FilesBuild a "Planning" Agent for a Fully Known WorkflowMake a Chatbot Remember Conversations Per UserMake an Agent Return a Typed ClassificationBuild a Quick One-Shot Text ReformatterCut Costs on a Long System Prompt That's Called Hundreds of Times a DayRemember Which Excuses We've Already Sent