Skip to content
Volume K · The TensorCore.si Library

Kotlin

Concise, safe and the language of Android.

Kotlin is a modern JVM language from JetBrains and Google's preferred language for Android. It interoperates fully with Java, removes boilerplate and prevents null-pointer crashes, and Koog and LangChain4j bring AI agents to it.

Prologue

Why learn Kotlin?

Kotlin does everything Java does with less code and fewer bugs, and it is the default for new Android apps.

  • Android first: Google recommends Kotlin for Android development.
  • Null safety: the compiler stops most null-pointer errors.
  • Coroutines: simple, efficient async code for network and AI calls.
Prologue

Set up and run your first program

Install IntelliJ IDEA (Community is free) or the Kotlin command-line compiler. Android Studio includes Kotlin.

terminal
kotlinc hello.kt -include-runtime -d hello.jar
java -jar hello.jar
hello.kt
fun main() {
    val name = "Ada"
    println("Hello, AI! Welcome to Kotlin, $name.")
}
TipGradle with the Kotlin plugin is the standard build tool for projects.
Chapter 1

val, var and null safety

val is read-only, var can change. Types are inferred. A type ending in ? may be null, and the compiler makes you handle it with ?. or ?:.

variables.kt
fun main() {
    val layers = 32
    var lr = 3e-4
    lr /= 2
    val params = 8_030_000_000L
    val note: String? = null
    println("$layers layers, lr=$lr, FP16 " + "%.1f".format(params * 2 / 1e9) + " GB")
    println(note?.length ?: "no note")
}
Chapter 2

Control flow and when

if and when are expressions that return values. for loops over ranges and collections.

control.kt
fun main() {
    for (epoch in 0 until 3) println("epoch $epoch")
    val bits = 8
    val name = when (bits) {
        32 -> "FP32"
        16 -> "FP16"
        8 -> "FP8"
        else -> "other"
    }
    val tier = if (bits <= 8) "low precision" else "high precision"
    println("$name, $tier")
}
Chapter 3

Functions and lambdas

Functions can have default and named arguments, and single-expression bodies. Lambdas are passed to functions like map and filter.

functions.kt
fun params(layers: Int, width: Int = 4096): Long = 12L * layers * width * width

fun main() {
    println(params(32))
    println(params(layers = 80, width = 8192))
    val squares = (1..5).map { it * it }
    println(squares)
}
Chapter 4

Data classes and collections

A data class gets equals, toString and copy for free. Lists and maps are read-only by default; use mutableListOf to change them.

data.kt
data class Gpu(val name: String, val vramGb: Int)

fun main() {
    val gpus = listOf(Gpu("H100", 80), Gpu("H200", 141), Gpu("B200", 180))
    val big = gpus.filter { it.vramGb > 100 }.map { it.name }
    println(big)
    println(gpus.first().copy(vramGb = 94))
}
Chapter 5

Coroutines

suspend functions can pause without blocking a thread. launch and async start coroutines, so you can run many network calls at once.

coroutines.kt
import kotlinx.coroutines.*

suspend fun fakeModel(prompt: String): String { delay(300); return "answer to $prompt" }

fun main() = runBlocking {
    val answers = listOf("a", "b", "c").map { p -> async { fakeModel(p) } }.awaitAll()
    println(answers)   // three calls in about 300 ms total
}
Part II · AI with Kotlin

AI with Kotlin

Kotlin is used to build AI features into Android apps and JVM back ends: on-device models with MediaPipe or LiteRT, server-side LLM calls, and agents with JetBrains' Koog framework.

The essential libraries

KoogJetBrains' framework for AI agents in Kotlin.
LangChain4jLLM chains and tools, works from Kotlin.
MediaPipe / LiteRTOn-device AI for Android.
KotlinDLDeep learning on the JVM.

Gradient descent from scratch

Learn y = 3x + 0.5 with loops.

gradient.kt
import kotlin.random.Random

fun main() {
    val n = 100
    val xs = DoubleArray(n) { -1 + 2.0 * it / (n - 1) }
    val ys = DoubleArray(n) { 3 * xs[it] + 0.5 + 0.1 * (Random.nextDouble() - 0.5) }
    var w = 0.0; var b = 0.0; val lr = 0.1
    repeat(500) {
        var gw = 0.0; var gb = 0.0
        for (i in 0 until n) { val err = w * xs[i] + b - ys[i]; gw += 2 * err * xs[i] / n; gb += 2 * err / n }
        w -= lr * gw; b -= lr * gb
    }
    println("w=%.2f b=%.2f".format(w, b))
}
Part III · Build an AI agent

Build an AI agent in Kotlin

Kotlin can use LangChain4j directly: describe tools as annotated methods and let the library run the tool-calling loop against a local model.

Your goal→Model plans→Tool call→Your code runs the tool→Result back to model→Final answer
Agent.kt
// Gradle: dev.langchain4j:langchain4j, dev.langchain4j:langchain4j-ollama
import dev.langchain4j.agent.tool.Tool
import dev.langchain4j.model.ollama.OllamaChatModel
import dev.langchain4j.service.AiServices

class Weather {
    @Tool("Get the current weather for a city")
    fun getWeather(city: String) = "It is 24°C and sunny in $city."
}
interface Assistant { fun chat(message: String): String }

fun main() {
    val model = OllamaChatModel.builder()
        .baseUrl("https://localhost:11434").modelName("llama3.1").build()
    val bot = AiServices.builder(Assistant::class.java)
        .chatModel(model).tools(Weather()).build()
    println(bot.chat("Should I take an umbrella in Lahore today?"))
}

Koog offers a Kotlin-native alternative with coroutines and agent strategies; check each library's docs for current method names.

Run it locallyInstall Ollama, run ollama pull llama3.1, and keep it running. The code talks to its OpenAI-compatible API at http://localhost:11434/v1, so the same program also works with vLLM, llama.cpp server or a cloud API by changing the URL, model name and adding an API key.
Part IV · Your path

Kotlin learning roadmap

Tick items off as you go. Your progress is saved in this browser.

Beginner

Intermediate

Advanced

Part IV · Your path

Projects to build

Notes appAn Android app with Jetpack Compose and Room.
Chat assistantA Compose UI that streams answers from an LLM.
Ktor APIA server that wraps an LLM with your own tools.
Reference

Kotlin cheat sheet

TaskSyntax
Read-onlyval x = 1
Mutablevar y = 2
Nullableval s: String? = null
Safe calls?.length ?: 0
Data classdata class P(val x: Int)
Lambdalist.map { it * 2 }
Reference

Common mistakes

  • Using !! to force non-null throws at runtime; handle nulls instead.
  • Blocking calls inside coroutines freeze the dispatcher; use suspend APIs.
  • listOf is read-only; use mutableListOf when you need to add items.
Reference

Where to go next

On TensorCore.si: Java volume, Swift volume.

Keyboard: [ previous language · ] next language · / search the library