Slide 1

Slide 1 text

Márton Braun @zsmb13 Building with AI in Kotlin Sebastian Aigner @sebi_io

Slide 2

Slide 2 text

Part 1 AI-assisted coding in Kotlin Part 2 Building AI-powered apps in Kotlin

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

github.com/JetBrains/kotlinconf-app

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

Next Edit Suggestions

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

No content

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

No content

Slide 17

Slide 17 text

No content

Slide 18

Slide 18 text

No content

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

No content

Slide 21

Slide 21 text

No content

Slide 22

Slide 22 text

No content

Slide 23

Slide 23 text

No content

Slide 24

Slide 24 text

No content

Slide 25

Slide 25 text

No content

Slide 26

Slide 26 text

No content

Slide 27

Slide 27 text

No content

Slide 28

Slide 28 text

3x speed

Slide 29

Slide 29 text

No content

Slide 30

Slide 30 text

No content

Slide 31

Slide 31 text

No content

Slide 32

Slide 32 text

No content

Slide 33

Slide 33 text

No content

Slide 34

Slide 34 text

4x speed

Slide 35

Slide 35 text

No content

Slide 36

Slide 36 text

No content

Slide 37

Slide 37 text

3x speed

Slide 38

Slide 38 text

No content

Slide 39

Slide 39 text

No content

Slide 40

Slide 40 text

No content

Slide 41

Slide 41 text

No content

Slide 42

Slide 42 text

No content

Slide 43

Slide 43 text

No content

Slide 44

Slide 44 text

No content

Slide 45

Slide 45 text

EAP jb.gg/junie-github

Slide 46

Slide 46 text

No content

Slide 47

Slide 47 text

No content

Slide 48

Slide 48 text

No content

Slide 49

Slide 49 text

No content

Slide 50

Slide 50 text

No content

Slide 51

Slide 51 text

No content

Slide 52

Slide 52 text

jb.gg/ai

Slide 53

Slide 53 text

No content

Slide 54

Slide 54 text

Part 1 AI-assisted coding in Kotlin Part 2 Building AI-powered apps in Kotlin

Slide 55

Slide 55 text

Kotlin ♡ AI on every layer • Model Provider SDKs • Core AI toolkit • Agentic Frameworks

Slide 56

Slide 56 text

Model Provider SDKs

Slide 57

Slide 57 text

Model Provider SDKs

Slide 58

Slide 58 text

ML Kit from Google

Slide 59

Slide 59 text

AI Edge & MediaPipe

Slide 60

Slide 60 text

Introducing Koog Kotlin AI Agent Framework

Slide 61

Slide 61 text

What is Koog? • Kotlin framework for AI agents – LLM-enabled applications that make decisions and can influence other systems • Manages LLM interactions • Provides DSLs to express complex workflows via graphs

Slide 62

Slide 62 text

Platforms supported by Koog • Android • JVM (Desktop / Server-Side) • Web (Wasm / JS) (iOS not supported out of the box, but possible)

Slide 63

Slide 63 text

Let's cook with Koog!

Slide 64

Slide 64 text

Step 0: Get LLM access! Koog supports major vendors • Google • OpenAI • Anthropic • OpenRouter • Ollama (on-device LLMs!)

Slide 65

Slide 65 text

Personal recommendation: OpenRouter

Slide 66

Slide 66 text

Personal recommendation: OpenRouter prepaid = no scary billing! (and $5 gets you a lot of tokens!)

Slide 67

Slide 67 text

You can choose and try different models

Slide 68

Slide 68 text

A very simple agent val agent = AIAgent( executor = simpleOpenRouterExecutor(ApiKeys.openRouter), systemPrompt = "You are a helpful assistant. Answer concisely.", llmModel = OpenAIModels.Chat.GPT5, ) suspend fun main() { val result: Agent = agent.run("What is the capital of Bavaria?") println(result) } The capital of Bavaria is Munich.

Slide 69

Slide 69 text

We need more… much more! • Exchanging more than one message • A way to steer the agent • Working with tools • A way to observe the agent

Slide 70

Slide 70 text

Koog gives you everything to build production-ready agents.

Slide 71

Slide 71 text

Koog's fundamental structures Graph(s): Made from nodes and edges LLM message history

Slide 72

Slide 72 text

LLM message history • Automatically managed by Koog • Doesn't have to be manually changed in normal operation – Ability to make changes is still exposed • Advanced features for management (like history compression)

Slide 73

Slide 73 text

Introducing graphs and nodes Output Input Node

Slide 74

Slide 74 text

Some available nodes Message.Response String node LLMRequest ReceivedToolResult Message.Tool.Call node executeTool Message.Response ReceivedToolResult node LLM SendToolResult Message.Assistant Message.Tool.Call node Start node Finish

Slide 75

Slide 75 text

ReceivedToolResult node LLM SendToolResult ReceivedToolResult Message.Tool.Call node executeTool Nodes snap together with edges Message.Response node LLMRequest Message.Assistant Message.Tool.Call

Slide 76

Slide 76 text

Custom node U T block() val nodeCustom by node { str -> println(str) 42 }

Slide 77

Slide 77 text

String String node Finish node Start Creating graphs with nodes and edges used node LLMRequest "only use " else "I'm blue. What emotion am I feeling?" private val classificationStrategy = strategy("Emotion classification") { val nodeSendToLLM by nodeLLMRequest() val nodeSayEmojiOnlyPlease by node { "Please only react using the following emojis: " } edge(nodeStart forwardTo nodeSendToLLM) edge(nodeSendToLLM forwardTo nodeFinish onAssistantMessage { msg -> listOf(" ", " ", " ").any { emoji -> emoji in msg.content } }) edge(nodeSendToLLM forwardTo nodeSayEmojiOnlyPlease) edge(nodeSayEmojiOnlyPlease forwardTo nodeSendToLLM) }

Slide 78

Slide 78 text

Plugging it in AIAgent( executor = simpleOpenRouterExecutor(ApiKeys.openRouter), systemPrompt = "Answer the user's question.", llmModel = OpenAIModels.Chat.GPT5, strategy = classificationStrategy, )

Slide 79

Slide 79 text

Integrating with tools • We want our agent to affect the world around it! • We need to provide it with (deterministic) integrations for the agent to: – Obtain task-specific information (e.g. "Read this GitHub issue") – Perform task-specific actions (e.g. "Transfer to ") • LLMs are specifically trained for this!

Slide 80

Slide 80 text

Declaring our own tool (almost) suspend fun getGitHubIssueContents( owner: String, repo: String, issueNumber: Int, token: String? = null, ): String = GitHubIssueClient.getGitHubIssueContents( owner, repo, issueNumber, token )

Slide 81

Slide 81 text

Creating a toolset with LLM descriptions @LLMDescription("Tools for interacting with GitHub Issues API. Can fetch JSON of a GitHub issue.") class GitHubIssueToolset : ToolSet { @Tool("get_github_issue_contents") @LLMDescription("Fetch the JSON of a GitHub issue and return it as a raw string.") suspend fun getGitHubIssueContents( @LLMDescription("Repository owner or organization, e.g., 'octocat'.") owner: String, @LLMDescription("Repository name, e.g., 'hello-world'.") repo: String, @LLMDescription("Issue number in the repository.") issueNumber: Int, @LLMDescription("Optional GitHub token. If omitted, GITHUB_TOKEN env variable will be used.") token: String? = null, ): String = GitHubIssueClient.getGitHubIssueContents( owner, repo, issueNumber, token ) }

Slide 82

Slide 82 text

Plugging it in AIAgent( executor = simpleOpenRouterExecutor(ApiKeys.openRouter), systemPrompt = """Answer the user's question |about a specific GitHub issue using tools.""".trimMargin(), llmModel = OpenAIModels.Chat.GPT5, toolRegistry = ToolRegistry { tools(GitHubIssueToolset()) }, strategy = oneShotStrategy, )

Slide 83

Slide 83 text

Let's run it!

Slide 84

Slide 84 text

External tools in Koog via MCP • AI Tool communication protocol • stdio or server-sent events

Slide 85

Slide 85 text

MCP server inspiration

Slide 86

Slide 86 text

Adding MCP val process = ProcessBuilder("path/to/mcp/server").start() val stdioTransport = McpToolRegistryProvider.defaultStdioTransport(process) val sseTransport = McpToolRegistryProvider.defaultSseTransport( "http://localhost:8931" ) val toolRegistry = McpToolRegistryProvider.fromTransport( transport = yourTransport, name = "my-client", version = "1.0.0" )

Slide 87

Slide 87 text

Koog also covers advanced use cases!

Slide 88

Slide 88 text

Agents as tools takes String returns String val tool = myAgent.asTool(/*...*/)

Slide 89

Slide 89 text

Not just String → String! val typedStrategy = strategy("Calculation") { val nodeToNumber by node { it.split(" ").sumOf { it.toInt() } } edge(nodeStart forwardTo nodeToNumber) edge(nodeToNumber forwardTo nodeFinish) } val typedAgent = AIAgent( inputType = typeOf(), outputType = typeOf(), promptExecutor = simpleOpenRouterExecutor(ApiKeys.openRouter), strategy = typedStrategy, agentConfig = AIAgentConfig.withSystemPrompt(prompt = "You are..."), ) val result: Int = typedAgent.run("5 7 10")

Slide 90

Slide 90 text

Structured data processing @Serializable data class WeatherForecast( val temperature: Int, val conditions: String, val precipitation: Int )

Slide 91

Slide 91 text

Structured data processing @Serializable @SerialName("WeatherForecast") @LLMDescription("Weather forecast for a given location") data class WeatherForecast( @property:LLMDescription("Temperature in Celsius") val temperature: Int, @property:LLMDescription("Weather conditions (e.g., sunny, cloudy, rainy)") val conditions: String, @property:LLMDescription("Chance of precipitation in percentage") val precipitation: Int ) node LLMRequest node LLMRequestStructured

Slide 92

Slide 92 text

History compression • LLM APIs are $/token • LLMs have limited context windows

Slide 93

Slide 93 text

• Different strategies to remove unnecessary information from LLM message history – WholeHistory – FromLastNMessages – Chunked node LLM CompressHistory

Slide 94

Slide 94 text

Observability / Tracing • Insights into what's happening inside your agent via the tracing module • Integration with OpenTelemetry

Slide 95

Slide 95 text

Supporting advanced use cases • Memory: Concepts & Facts management • Content moderation • Ranked Document Storage for RAG • Semantic meaning via Embeddings • Testing & Mocking

Slide 96

Slide 96 text

Koog runs on phones and servers! • You can write and run Koog agents to run on Android phones! • Koog doesn't do inference by itself – it uses APIs for that • Agents themselves aren't that computationally heavy!

Slide 97

Slide 97 text

koog.ai youtube.com/kotlin

Slide 98

Slide 98 text

Concluding highlights • AI Tooling helps you work with Kotlin! – IDE features like completion and next edit suggestions help write code – AI Assistant provides project insights and edits – Junie, the JetBrains AI agent, can write full features end-to-end • Koog makes building AI agents idiomatic – It's superpower is composability via graphs! – It type-safely integrates into 3rd party systems and your own systems, via tools, MCP & co. – It's designed to scale, with features like history compression, observability integrations, and tracing. – Koog becomes more powerful day by day!

Slide 99

Slide 99 text

Come visit the JetBrains booth! Enjoy DroidKaigi! Márton Braun @zsmb13 Sebastian Aigner @sebi_io