koog-edge
0.0.4indexedOn-device AI for mobile apps, integrating Koog Agents with local small language models; enables privacy-focused offline tool-calling, easy model download/management, multi-backend inference and streaming.
On-device AI for mobile apps, integrating Koog Agents with local small language models; enables privacy-focused offline tool-calling, easy model download/management, multi-backend inference and streaming.
Stable? That's for horses 🐴 This library is in early experimental stage, do not use it for any serious work!
Koog Edge is a Kotlin Multiplatform library that brings on-device AI capabilities to your mobile applications. It provides seamless integration between the Koog Agents framework and local Small Language Models (SLMs), enabling privacy-focused, offline AI experiences.
✨ On-Device AI - Run AI models locally without internet connectivity
🔧 Tool Calling Support - Enable agents to interact with external tools and APIs
🌐 Kotlin Multiplatform - Support for Android and iOS platforms
🔌 Multiple Backends - Support for Cactus Compute and Leap SDK
🎯 Koog Integration - Works seamlessly with Koog Agents Core
📦 Easy Model Management - Download and load models with simple APIs
| Model | Size | Context Length | Tool Calling |
|---|---|---|---|
| Qwen 3 0.6B | 394 MB |
| Model | Context Length | Tool Calling |
|---|---|---|
| LFM2 1.2B Tool | 32,768 tokens | ✅ Yes |
Add the dependency to your Gradle build file:
dependencies {
implementation("io.github.lemcoder:koog-edge:0.0.2")
// Also add Koog Agents Core if not already included
implementation("ai.koog:agents-core:0.5.3")
}
dependencies {
implementation 'io.github.lemcoder:koog-edge:0.0.2'
// Also add Koog Agents Core if not already included
implementation 'ai.koog:agents-core:0.5.3'
}
Koog Edge supports two inference backends:
import io.github.lemcoder.koog.edge.cactus.getCactusLLMClient
import io.github.lemcoder.koog.edge.cactus.CactusModels
import io.github.lemcoder.koog.edge.cactus.CactusLLMParams
// Create the LLM client (pass Android context on Android, null on iOS)
val llmClient = getCactusLLMClient(context)
// Create a prompt executor
val executor = SingleLLMPromptExecutor(llmClient)
// Use with Koog Agents
val agent = AIAgent(
promptExecutor = executor,
strategy = yourStrategy,
agentConfig = AIAgentConfig(
prompt = prompt("assistant") {
system()
},
model = CactusModels.Chat.Qwen3_0_6B,
maxAgentIterations =
)
)
import io.github.lemcoder.koog.edge.leap.getLeapLLMClient
import io.github.lemcoder.koog.edge.leap.LeapModels
// Specify the path to your downloaded model
val modelPath = "/path/to/model"
val llmClient = getLeapLLMClient(modelPath)
val executor = SingleLLMPromptExecutor(llmClient)
import ai.koog.agents.core.agent.AIAgent
import ai.koog.agents.core.agent.config.AIAgentConfig
import ai.koog.agents.core.agent.functionalStrategy
import ai.koog.agents.core.dsl.extension.requestLLM
ai.koog.prompt.dsl.prompt
strategy = functionalStrategy<String, String>() { input ->
response = requestLLM(input, allowToolCalls = )
response.content
}
agent = AIAgent(
promptExecutor = executor,
strategy = strategy,
agentConfig = AIAgentConfig(
prompt = prompt(, params = CactusLLMParams()) {
system()
},
model = CactusModels.Chat.Qwen3_0_6B,
maxAgentIterations =
)
)
result = agent.execute()
println(result)
import io.github.lemcoder.koog.edge.LocalModelDownloader
import io.github.lemcoder.koog.edge.cactus.CactusModels
// Download a Cactus model with progress tracking
val downloader = LocalModelDownloader.downloadCactusModel(CactusModels.Chat.Qwen3_0_6B)
downloader.collect { progress ->
println("Download progress: ${(progress * 100).toInt()}%")
}
import io.github.lemcoder.koog.edge.cactus.CactusLLMParams
import com.cactus.InferenceMode
val params = CactusLLMParams(
temperature = 0.7,
maxTokens = 512,
topK = 40,
topP = 0.95,
stopSequences = listOf("</s>", "[DONE]"),
inferenceMode = InferenceMode.LOCAL_FIRST, // LOCAL, CLOUD, or LOCAL_FIRST
cactusToken =
)
agentConfig = AIAgentConfig(
prompt = prompt(, params = params) {
system()
},
model = CactusModels.Chat.Qwen3_0_6B,
maxAgentIterations =
)
import io.github.lemcoder.koog.edge.leap.LeapLLMParams
val params = LeapLLMParams(
temperature = 0.7f,
topP = 0.95f,
minP = 0.05f,
repetitionPenalty = 1.1f,
jsonSchemaConstraint = """{"type": "object", "properties": {...}}"""
)
val agent = AIAgent(
promptExecutor = executor,
strategy = strategy,
agentConfig = agentConfig
)
// Execute with streaming
agent.executeStreaming("Tell me a story").collect { frame ->
when (frame) {
is StreamFrame.Append -> print(frame.text)
is StreamFrame.End -> println("\nFinished: ${frame.finishReason}")
is StreamFrame.ToolCall -> println("Tool called: ${frame.name}")
}
}
Koog Edge acts as a bridge between the Koog Agents framework and on-device inference engines:
┌─────────────────────┐
│ Your Android/iOS │
│ Application │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Koog Agents │ ← High-level AI agent framework
│ Core │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Koog Edge │ ← This library (LLM client adapters)
│ (This Library) │
└──────────┬──────────┘
│
┌────┴────┐
▼ ▼
┌──────────┐ ┌──────────┐
│ Cactus │ │ Leap SDK │ ← On-device inference engines
│ Compute │ │ │
└──────────┘ └──────────┘
Koog Edge is built on top of:
This repository includes a complete example app demonstrating:
Check out the app/ directory for full examples.
Contributions are welcome! Please feel free to submit a Pull Request.
Copyright 2025 Mikołaj Lemański
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance the License.
You may obtain a copy of the License at
http:
Unless applicable law agreed to writing, software
distributed under the License distributed an BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express implied.
See the License the specific language governing permissions
limitations under the License.
Made with ❤️ by Mikołaj Lemański
| 16,384 tokens |
| ✅ Yes |
| Qwen 3 1.7B | 1,161 MB | 16,384 tokens | ✅ Yes |
import io.github.lemcoder.koog.edge.log.KoogEdgeLog
import io.github.lemcoder.koog.edge.log.KoogEdgeLogger
// Implement custom logger
object MyLogger : KoogEdgeLogger {
override fun info(message: () -> String) {
Log.i("KoogEdge", message())
}
override fun warning(message: () -> String) {
Log.w("KoogEdge", message())
}
override fun error(message: String, error: Throwable?) {
Log.e("KoogEdge", message, error)
}
}
// Set custom logger
KoogEdgeLog.setLogger(MyLogger)
Surfaced from shared tags and platforms — no rankings paid for.