# John O'Reilly

John O'Reilly's Blog

This is one page of public article previews, not the complete archive. Follow Next page to continue. Summaries are not the original full articles.

## Using the new Google Gen AI SDK for Kotlin

DevFeed: [Using the new Google Gen AI SDK for Kotlin](<https://devfeed.tech/articles/using-the-new-google-gen-ai-sdk-for-kotlin-25196.md>)

Original publisher: [Read original article](<https://johnoreilly.dev/posts/genai-kotlin-sdk/>)

Published: 2026-09-04T23:00:00Z

Content type: tutorial

Language: en

Sources: [John O'Reilly](<https://devfeed.tech/sources/john-o-reilly.md>)

Topics: [Kotlin](<https://devfeed.tech/topics/kotlin.md>), [SDKs](<https://devfeed.tech/topics/sdks.md>), [Google](<https://devfeed.tech/topics/google.md>), [Artificial Intelligence](<https://devfeed.tech/topics/ai.md>), [API](<https://devfeed.tech/topics/api.md>)

Tags: [ai](<https://devfeed.tech/tags/ai.md>), [apis](<https://devfeed.tech/tags/apis.md>), [google](<https://devfeed.tech/tags/google.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [sdk](<https://devfeed.tech/tags/sdk.md>)

### AI overview

This tutorial shows how to replace hand-written Gemini REST calls with Google's version 1.0 Gen AI SDK for Kotlin. It covers the SDK's coroutine- and Flow-based client, video and text requests, and structured JSON output.

### Source excerpt

Google have just released version 1.0 of the Gen AI SDK for Kotlin, an idiomatic Kotlin client for the Gemini APIs. Up to now, calling Gemini from Kotlin has generally meant use of one of the Firebase SDKs, a community wrapper, an agent framework like Koog, or (as in the code below) just talking to the REST endpoint yourself. This is Google's own Kotlin library for it, built around coroutines and Flow.

## Running golf swing analysis on an Android device with a fine-tuned Gemma 4 model

DevFeed: [Running golf swing analysis on an Android device with a fine-tuned Gemma 4 model](<https://devfeed.tech/articles/running-golf-swing-analysis-on-an-android-device-with-a-fine-tuned-gemma-4-model-25193.md>)

Original publisher: [Read original article](<https://johnoreilly.dev/posts/formai-gemma4-ondevice/>)

Published: 2026-08-29T23:00:00Z

Content type: tutorial

Language: en

Sources: [John O'Reilly](<https://devfeed.tech/sources/john-o-reilly.md>)

Topics: [Kotlin Multiplatform](<https://devfeed.tech/topics/kotlin-multiplatform.md>), [gemma4](<https://devfeed.tech/topics/gemma4.md>), [LiteRT](<https://devfeed.tech/topics/litert.md>), [On-device AI](<https://devfeed.tech/topics/on-device-ai.md>), [Fine-tuning](<https://devfeed.tech/topics/fine-tuning.md>)

Tags: [ai](<https://devfeed.tech/tags/ai.md>), [android](<https://devfeed.tech/tags/android.md>), [cross-platform](<https://devfeed.tech/tags/cross-platform.md>), [fine-tuning](<https://devfeed.tech/tags/fine-tuning.md>), [gemma](<https://devfeed.tech/tags/gemma.md>), [gemma-4](<https://devfeed.tech/tags/gemma-4.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [kotlin-multiplatform](<https://devfeed.tech/tags/kotlin-multiplatform.md>), [litert](<https://devfeed.tech/tags/litert.md>), [model](<https://devfeed.tech/tags/model.md>), [multiplatform](<https://devfeed.tech/tags/multiplatform.md>), [on-device-ai](<https://devfeed.tech/tags/on-device-ai.md>)

### AI overview

This article explains how FormAI adds Android on-device golf-swing analysis using a small Gemma 4 model fine-tuned to imitate Gemini for a narrow coaching task. It covers generating training data with Gemini, fine-tuning with LoRA, converting the model for LiteRT-LM, and the current fallback to cloud analysis on other platforms.

### Source excerpt

FormAI is a Kotlin Multiplatform app that analyses a video of your golf swing, basketball shot or running form and gives you coaching feedback. Up to now that has always meant uploading the video to Gemini and getting the response back over the network. We've added an option to do the golf swing analysis entirely on an Android device instead, using a small Gemma 4 model that we fine-tuned to imitate Gemini for that one task. LiteRT-LM, the runtime we use for this, is itself cross platform (Android, iOS, desktop and web), but we've only wired up the Android side so far, so this path lives in androidMain and the other targets report it as unavailable and fall back to the cloud.

## Engineering log: fine-tuning Gemma 4 E4B with LoRA to bring FormAI's coaching on-device

DevFeed: [Engineering log: fine-tuning Gemma 4 E4B with LoRA to bring FormAI's coaching on-device](<https://devfeed.tech/articles/engineering-log-fine-tuning-gemma-4-e4b-with-lora-to-bring-formai-s-coaching-on-device-25192.md>)

Original publisher: [Read original article](<https://johnoreilly.dev/posts/formai-gemma4-lora/>)

Published: 2026-08-28T23:00:00Z

Content type: article

Language: en

Sources: [John O'Reilly](<https://devfeed.tech/sources/john-o-reilly.md>)

Topics: [gemma4](<https://devfeed.tech/topics/gemma4.md>), [Fine-tuning](<https://devfeed.tech/topics/fine-tuning.md>), [lora](<https://devfeed.tech/topics/lora.md>), [On-device AI](<https://devfeed.tech/topics/on-device-ai.md>), [multiplatform](<https://devfeed.tech/topics/multiplatform.md>), [LiteRT](<https://devfeed.tech/topics/litert.md>), [Android](<https://devfeed.tech/topics/android.md>), [Artificial Intelligence](<https://devfeed.tech/topics/ai.md>), [API](<https://devfeed.tech/topics/api.md>)

Tags: [ai](<https://devfeed.tech/tags/ai.md>), [android](<https://devfeed.tech/tags/android.md>), [api](<https://devfeed.tech/tags/api.md>), [data](<https://devfeed.tech/tags/data.md>), [data-quality](<https://devfeed.tech/tags/data-quality.md>), [engineering](<https://devfeed.tech/tags/engineering.md>), [fine-tuning](<https://devfeed.tech/tags/fine-tuning.md>), [gemini](<https://devfeed.tech/tags/gemini.md>), [gemma](<https://devfeed.tech/tags/gemma.md>), [gemma-4](<https://devfeed.tech/tags/gemma-4.md>), [inference](<https://devfeed.tech/tags/inference.md>), [kotlin-multiplatform](<https://devfeed.tech/tags/kotlin-multiplatform.md>), [litert](<https://devfeed.tech/tags/litert.md>), [lora](<https://devfeed.tech/tags/lora.md>), [multiplatform](<https://devfeed.tech/tags/multiplatform.md>), [on-device](<https://devfeed.tech/tags/on-device.md>)

### AI overview

This engineering log describes a prototype that distils FormAI's Gemini-based sports coaching feedback into Gemma 4 E4B fine-tuned with LoRA. The local pipeline uses seed videos, filters inadequate critiques, extracts frames, trains and merges the adapter, then converts the model to LiteRT-LM for possible on-device Android inference.

### Source excerpt

⚠ Note: this post is AI-generated. The text below was written by Claude, and documents findings from a series of Claude Code sessions working on this project -- the experiments, bugs and measurements described are ones that came out of those sessions. The engineering work is real and the numbers were measured rather than estimated, but the write-up is the model's own account of what it did, not a human's independent retelling of it.

## Scanning bus stop codes with ML Kit and Vision in the GalwayBus Compose Multiplatform app

DevFeed: [Scanning bus stop codes with ML Kit and Vision in the GalwayBus Compose Multiplatform app](<https://devfeed.tech/articles/scanning-bus-stop-codes-with-ml-kit-and-vision-in-the-galwaybus-compose-multiplatform-app-25195.md>)

Original publisher: [Read original article](<https://johnoreilly.dev/posts/galwaybus-scan-stop-kmp/>)

Published: 2026-08-06T23:00:00Z

Content type: tutorial

Language: en

Sources: [John O'Reilly](<https://devfeed.tech/sources/john-o-reilly.md>)

Topics: [compose-multiplatform](<https://devfeed.tech/topics/compose-multiplatform.md>), [ML Kit](<https://devfeed.tech/topics/ml-kit.md>), [Android](<https://devfeed.tech/topics/android.md>), [cameraX](<https://devfeed.tech/topics/camerax.md>), [iOS](<https://devfeed.tech/topics/ios.md>), [Code](<https://devfeed.tech/topics/code.md>), [ui](<https://devfeed.tech/topics/ui.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [apple](<https://devfeed.tech/tags/apple.md>), [camera](<https://devfeed.tech/tags/camera.md>), [camerax](<https://devfeed.tech/tags/camerax.md>), [code](<https://devfeed.tech/tags/code.md>), [compose-multiplatform](<https://devfeed.tech/tags/compose-multiplatform.md>), [ios](<https://devfeed.tech/tags/ios.md>), [ml-kit](<https://devfeed.tech/tags/ml-kit.md>), [multiplatform](<https://devfeed.tech/tags/multiplatform.md>), [native](<https://devfeed.tech/tags/native.md>), [ocr](<https://devfeed.tech/tags/ocr.md>), [on-device](<https://devfeed.tech/tags/on-device.md>), [platform](<https://devfeed.tech/tags/platform.md>), [recognition](<https://devfeed.tech/tags/recognition.md>), [ui](<https://devfeed.tech/tags/ui.md>)

### AI overview

This tutorial explains how the GalwayBus app scans six-digit bus stop codes using on-device ML Kit on Android and Apple's Vision framework on iOS. Camera preview, matching logic, and UI are shared through Compose Multiplatform, while platform-specific implementations handle camera access and OCR. Recognized six-digit runs are matched exactly to stops, and overlapping recognition requests are avoided by dropping newer frames.

### Source excerpt

Every bus stop in Galway has a plate with a 6-digit stop code printed on it. We recently added a "Scan" tab to the GalwayBus app that lets you point the camera at that plate and jump straight to the stop's departures. The text recognition runs entirely on device (ML Kit on Android, Apple's Vision framework on iOS), with the camera preview, matching logic and UI all living in the shared Compose Multiplatform code.

## Adding a Koog AI assistant (with structured output) to the FantasyPremierLeague CMP sample

DevFeed: [Adding a Koog AI assistant (with structured output) to the FantasyPremierLeague CMP sample](<https://devfeed.tech/articles/adding-a-koog-ai-assistant-with-structured-output-to-the-fantasypremierleague-cmp-sample-25194.md>)

Original publisher: [Read original article](<https://johnoreilly.dev/posts/fpl-koog-structured-output/>)

Published: 2026-07-27T23:00:00Z

Content type: tutorial

Language: en

Sources: [John O'Reilly](<https://devfeed.tech/sources/john-o-reilly.md>)

Topics: [Artificial Intelligence](<https://devfeed.tech/topics/ai.md>), [compose-multiplatform](<https://devfeed.tech/topics/compose-multiplatform.md>), [Kotlin](<https://devfeed.tech/topics/kotlin.md>), [jetbrains](<https://devfeed.tech/topics/jetbrains.md>), [Framework](<https://devfeed.tech/topics/framework.md>), [App](<https://devfeed.tech/topics/app.md>)

Tags: [agents](<https://devfeed.tech/tags/agents.md>), [ai](<https://devfeed.tech/tags/ai.md>), [ai-agents](<https://devfeed.tech/tags/ai-agents.md>), [compose](<https://devfeed.tech/tags/compose.md>), [compose-multiplatform](<https://devfeed.tech/tags/compose-multiplatform.md>), [framework](<https://devfeed.tech/tags/framework.md>), [jetbrains](<https://devfeed.tech/tags/jetbrains.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [llm](<https://devfeed.tech/tags/llm.md>), [multiplatform](<https://devfeed.tech/tags/multiplatform.md>)

### AI overview

This tutorial adds a Koog-powered AI assistant to a FantasyPremierLeague Compose Multiplatform sample. It uses structured output to return typed player and fixture IDs, allowing the app to render cards and resolve references against its existing data.

### Source excerpt

Koog is JetBrains' Kotlin framework for building AI agents. In this article we're going to use it to add an in-app "FPL Assistant" to the FantasyPremierLeague Compose Multiplatform sample. This is a chat screen where you can ask about players, fixtures and mini-league standings. The answers render as player and fixture cards rather than just as text.

## Adding embeddings/RAG support to the Koog-based AI agent in Confetti

DevFeed: [Adding embeddings/RAG support to the Koog-based AI agent in Confetti](<https://devfeed.tech/articles/adding-embeddings-rag-support-to-the-koog-based-ai-agent-in-confetti-25191.md>)

Original publisher: [Read original article](<https://johnoreilly.dev/posts/confetti-koog-rag/>)

Published: 2026-05-25T23:00:00Z

Content type: tutorial

Language: en

Sources: [John O'Reilly](<https://devfeed.tech/sources/john-o-reilly.md>)

Topics: [AI Agent](<https://devfeed.tech/topics/ai-agent.md>), [Embeddings](<https://devfeed.tech/topics/embeddings.md>), [Retrieval-Augmented Generation](<https://devfeed.tech/topics/retrieval-augmented-generation.md>), [multiplatform](<https://devfeed.tech/topics/multiplatform.md>), [Kotlin](<https://devfeed.tech/topics/kotlin.md>), [GraphQL](<https://devfeed.tech/topics/graphql.md>)

Tags: [agent](<https://devfeed.tech/tags/agent.md>), [ai-agent](<https://devfeed.tech/tags/ai-agent.md>), [compose-multiplatform](<https://devfeed.tech/tags/compose-multiplatform.md>), [embeddings](<https://devfeed.tech/tags/embeddings.md>), [graphql](<https://devfeed.tech/tags/graphql.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [rag](<https://devfeed.tech/tags/rag.md>)

### AI overview

This tutorial explains how to add semantic search to the Koog-based AI agent in the Confetti Compose Multiplatform sample. It uses embeddings and retrieval-augmented generation to find related conference sessions even when query wording differs from session titles or descriptions.

### Source excerpt

Recently I started looking at reworking the recommendation feature in the Confetti Compose Multiplatform sample (which uses Apollo Kotlin to consume a GraphQL API serving data for various conferences). The new implementation uses a Koog AIAgent with a ToolRegistry that includes session and speaker tools, giving the LLM on-demand access to the conference data it needs.

## Using Navigation 3 with Compose Multiplatform

DevFeed: [Using Navigation 3 with Compose Multiplatform](<https://devfeed.tech/articles/using-navigation-3-with-compose-multiplatform-25199.md>)

Original publisher: [Read original article](<https://johnoreilly.dev/posts/navigation3-cmp/>)

Published: 2025-11-15T00:00:00Z

Content type: tutorial

Language: en

Sources: [John O'Reilly](<https://devfeed.tech/sources/john-o-reilly.md>)

Topics: [compose-multiplatform](<https://devfeed.tech/topics/compose-multiplatform.md>), [navigation](<https://devfeed.tech/topics/navigation.md>), [Compose](<https://devfeed.tech/topics/compose.md>), [Google](<https://devfeed.tech/topics/google.md>), [Kotlin](<https://devfeed.tech/topics/kotlin.md>), [ui](<https://devfeed.tech/topics/ui.md>)

Tags: [adaptive](<https://devfeed.tech/tags/adaptive.md>), [compose-multiplatform](<https://devfeed.tech/tags/compose-multiplatform.md>), [google](<https://devfeed.tech/tags/google.md>), [kmp](<https://devfeed.tech/tags/kmp.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [material3](<https://devfeed.tech/tags/material3.md>), [multiplatform](<https://devfeed.tech/tags/multiplatform.md>), [navigation](<https://devfeed.tech/tags/navigation.md>), [ui](<https://devfeed.tech/tags/ui.md>)

### AI overview

A tutorial on using Navigation 3 with Compose Multiplatform in a shared Kotlin Multiplatform project. It covers dependencies, back-stack-based navigation, route mapping, and adaptive list/detail layouts using Material3 Adaptive Navigation3.

### Source excerpt

Navigation 3 is a new Compose based navigation library from Google that's designed with ease of use and flexibility in mind.

## Deploying a Kotlin-based remote MCP Server to Google Cloud Run

DevFeed: [Deploying a Kotlin-based remote MCP Server to Google Cloud Run](<https://devfeed.tech/articles/deploying-a-kotlin-based-remote-mcp-server-to-google-cloud-run-25200.md>)

Original publisher: [Read original article](<https://johnoreilly.dev/posts/remote-mcp/>)

Published: 2025-07-26T23:00:00Z

Content type: tutorial

Language: en

Sources: [John O'Reilly](<https://devfeed.tech/sources/john-o-reilly.md>)

Topics: [MCP Server](<https://devfeed.tech/topics/mcp-server.md>), [Cloud Run](<https://devfeed.tech/topics/cloud-run.md>), [Kotlin](<https://devfeed.tech/topics/kotlin.md>), [Deployment](<https://devfeed.tech/topics/deployment.md>), [Google Cloud Platform (GCP)](<https://devfeed.tech/topics/google-cloud.md>)

Tags: [cloud-run](<https://devfeed.tech/tags/cloud-run.md>), [deployment](<https://devfeed.tech/tags/deployment.md>), [google-cloud](<https://devfeed.tech/tags/google-cloud.md>), [how-to](<https://devfeed.tech/tags/how-to.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [mcp](<https://devfeed.tech/tags/mcp.md>), [mcp-server](<https://devfeed.tech/tags/mcp-server.md>)

### AI overview

A tutorial on deploying a Kotlin-based MCP Server from the ClimateTraceKMP sample to Google Cloud Run. It covers building and publishing a container with the Jib Gradle Plugin, configuring the server for Cloud Run, and connecting to Claude Desktop, Claude mobile apps, and MCP Inspector.

### Source excerpt

I wrote a previous post about how to develop an MCP Server using the Kotlin MCP SDK. That was primarily based on local deployment (using stdio protocol)...a setup that Claude Desktop for example could only support at the time. With the announcement that Claude now supports access to remote MCP Servers (from desktop and mobile) I thought I'd take a look at deploying the MCP Server in the ClimateTraceKMP sample to Google Cloud Run.

## Using Google's Agent Development Kit for Java from Kotlin code

DevFeed: [Using Google's Agent Development Kit for Java from Kotlin code](<https://devfeed.tech/articles/using-google-s-agent-development-kit-for-java-from-kotlin-code-25197.md>)

Original publisher: [Read original article](<https://johnoreilly.dev/posts/kotlin-adk/>)

Published: 2025-07-10T23:00:00Z

Content type: tutorial

Language: en

Sources: [John O'Reilly](<https://devfeed.tech/sources/john-o-reilly.md>)

Topics: [AI Agent](<https://devfeed.tech/topics/ai-agent.md>), [Google](<https://devfeed.tech/topics/google.md>), [Artificial Intelligence](<https://devfeed.tech/topics/ai.md>), [Kotlin](<https://devfeed.tech/topics/kotlin.md>), [Java](<https://devfeed.tech/topics/java.md>), [Model Context Protocol](<https://devfeed.tech/topics/model-context-protocol.md>), [Kotlin Multiplatform](<https://devfeed.tech/topics/kotlin-multiplatform.md>)

Tags: [agent](<https://devfeed.tech/tags/agent.md>), [ai](<https://devfeed.tech/tags/ai.md>), [development](<https://devfeed.tech/tags/development.md>), [google](<https://devfeed.tech/tags/google.md>), [java](<https://devfeed.tech/tags/java.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [kotlin-multiplatform](<https://devfeed.tech/tags/kotlin-multiplatform.md>), [mcp](<https://devfeed.tech/tags/mcp.md>), [mcp-server](<https://devfeed.tech/tags/mcp-server.md>)

### AI overview

A tutorial on using Google's Agent Development Kit for Java from Kotlin code, demonstrated in a Kotlin Multiplatform sample. It covers configuring Gradle dependencies, selecting LLM providers, creating and running agents, adding MCP and local function tools, handling Kotlin suspend functions, and using the ADK developer UI.

### Source excerpt

Google's Agent Development Kit for Java is described as "an open-source, code-first Java toolkit for building, evaluating, and deploying sophisticated AI agents with flexibility and control". In this article we're going to see how it can be consumed in Kotlin code (specifically in the agents module in the ClimateTrace Kotlin Multiplatform sample).

## Initial exploration of using Koog for developing Kotlin based AI agents

DevFeed: [Initial exploration of using Koog for developing Kotlin based AI agents](<https://devfeed.tech/articles/initial-exploration-of-using-koog-for-developing-kotlin-based-ai-agents-25198.md>)

Original publisher: [Read original article](<https://johnoreilly.dev/posts/kotlin-koog/>)

Published: 2025-06-21T23:00:00Z

Content type: tutorial

Language: en

Sources: [John O'Reilly](<https://devfeed.tech/sources/john-o-reilly.md>)

Topics: [AI Agent](<https://devfeed.tech/topics/ai-agent.md>), [Kotlin](<https://devfeed.tech/topics/kotlin.md>), [MCP](<https://devfeed.tech/topics/mcp.md>), [Model Context Protocol](<https://devfeed.tech/topics/model-context-protocol.md>), [Kotlin Multiplatform](<https://devfeed.tech/topics/kotlin-multiplatform.md>), [Android Studio](<https://devfeed.tech/topics/android-studio.md>), [Jetpack Compose](<https://devfeed.tech/topics/jetpack-compose.md>), [IntelliJ IDEA](<https://devfeed.tech/topics/intellij-idea.md>)

Tags: [ai-agents](<https://devfeed.tech/tags/ai-agents.md>), [android-studio](<https://devfeed.tech/tags/android-studio.md>), [anthropic](<https://devfeed.tech/tags/anthropic.md>), [compose](<https://devfeed.tech/tags/compose.md>), [gemini](<https://devfeed.tech/tags/gemini.md>), [ide](<https://devfeed.tech/tags/ide.md>), [kmp](<https://devfeed.tech/tags/kmp.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [kotlin-multiplatform](<https://devfeed.tech/tags/kotlin-multiplatform.md>), [mcp](<https://devfeed.tech/tags/mcp.md>), [mcp-server](<https://devfeed.tech/tags/mcp-server.md>), [ollama](<https://devfeed.tech/tags/ollama.md>), [openai](<https://devfeed.tech/tags/openai.md>), [plugin](<https://devfeed.tech/tags/plugin.md>), [run-agent](<https://devfeed.tech/tags/run-agent.md>), [tool](<https://devfeed.tech/tags/tool.md>)

### AI overview

This article explores Koog, a Kotlin-based framework for building and running AI agents. It demonstrates an agent using Google Gemini, MCP servers, climate-emissions data, and Compose UI code added to an Android Studio project, and discusses support for multiple LLM providers and custom tools.

### Source excerpt

Koog, announced recently at KotlinConf, is a new Kotlin-based framework designed to build and run AI agents. This article will outline initial exploration of using Koog along with a number of configured MCP servers (specifically mcp-jetbrains which we'll use to control the IntelliJ/Android Studio IDE and also one based on the ClimateTraceKMP Kotlin Multiplatform (KMP) sample built using the Kotlin MCP SDK).