AIARTICLE

ADK for Kotlin 1.0 brings AI agents inside the Android app

Google finalized version 1.0 of the Agent Development Kit for Kotlin, with parity to the Python and Java core and on-device extensions that run agents directly on the phone.

ADK for Kotlin 1.0 brings AI agents inside the Android app
Image: Alan Andrade

Google announced on the Google Developers Blog, on September 9, 2026, the general availability of ADK for Kotlin 1.0, the Agent Development Kit aimed at those writing AI agents in Kotlin, Java, and Android. The version moves out of experimental status (0.1.0 had been the first step) and arrives, according to the post signed by Developer Advocate Guillaume Laforge, with full feature parity relative to the ADK 1.0 Core (the foundation that already existed in Python and Java).

The message for builders is direct: instead of treating the app as a dumb client that just calls an LLM API and parses JSON by hand, ADK offers the orchestration loop (tool calling, multi-agent, human-in-the-loop, session persistence) as an idiomatic Kotlin library, both on the server and on the device.

Compile-time generated function calling

The most interesting technical differentiator for Kotlin devs is how ADK handles tools. Defining a function exposed to the model is done with @Tool and @Param annotations on regular methods, and the schema the LLM sees is generated via KSP (Kotlin Symbol Processing) at compile time, not at runtime.

In practice this means three things the post emphasizes: type-safe schemas, support for suspend fun (coroutine functions), and zero runtime reflection. Anyone who has suffered with libraries that build schemas via reflection knows the cost of that in an Android app, where reflection weighs on startup time and gets in the way of R8/ProGuard. Generating everything at build time is the right choice for mobile.

The pattern looks like this: you declare a service with annotated methods and KSP creates the generatedTools() extension for you.

kotlin
class InfrastructureDiagnosticsService {
    @Tool
    suspend fun getServiceMetrics(
        @Param("Target service or database cluster") serviceName: String,
        @Param("Time window in minutes") windowMinutes: Int? = 15,
    ): ServiceMetrics {
        // queries Datadog, Prometheus, Cloud Monitoring...
    }
}

In the agent, tools are added declaratively via tools = InfrastructureDiagnosticsService().generatedTools().

Skills and progressive disclosure to avoid blowing the context

Besides executable tools, ADK separates out what it calls skills: procedural knowledge and domain playbooks loaded on demand through a SkillToolset. The idea, in the example of a database incident triage agent, is not to hardcode SRE guidelines into the code, but to place them in a SKILL.md file under src/main/resources/skills/, with the procedure steps and the allowed-tools list.

The point that deserves attention is the progressive disclosure mechanism: auxiliary resources (for example, a mitigation_rules.txt with the rule to never restart primary nodes during peak hours) are only fetched by the model when it needs them, keeping token usage lean. For those who pay per token and struggle with context windows, this is an architectural decision that matters more than it seems: the full playbook doesn't clog the prompt on every turn.

In the post's example, the agent receives a P1 latency alert, loads the triage skill, calls getServiceMetrics() (which returns 98.5% connection pool saturation), correlates it with fetchRecentDeployments(), points to the deploy-9842 deploy from 25 minutes earlier ("Add unindexed batch query...") as the root cause, and posts the diagnosis to the #production-alerts channel, suggesting an immediate rollback. It's a scripted scenario built for the demo (the numbers are hardcoded in the service), but it illustrates well the structured autonomous loop the framework runs.

What changes on Android: on-device and native persistence

The part that really sets ADK for Kotlin apart from the Python/Java SDKs is the Android-first extensions. The framework is built on a Kotlin Multiplatform (KMP) core that's agnostic to model backend, session provider, or memory system, and on top of that it connects standard Android architecture components:

| Need | ADK for Kotlin extension | |---|---| | On-device running models | LiteRT-LM and ML Kit (beta) | | Hybrid cloud/local workflows | Firebase AI Logic | | Session persisted across process restarts | Room (SQLite) via RoomSessionService | | Indexed memory with full-text search | AppSearch via AppSearchMemoryService | | Generated files (receipts, statements) | Android storage via FileArtifactService |

In the example of a financial assistant using Gemini 3.8 Flash via Firebase AI, the runner is assembled by wiring these services together in a few lines:

kotlin
fun createAndroidRunner(context: Context, agent: LlmAgent) = InMemoryRunner(
    agent = agent,
    appName = "AndroidFinancialApp",
    sessionService = RoomSessionService.fromContext(context),
    memoryService = AppSearchMemoryService.fromContext(context),
    artifactService = FileArtifactService.fromExternalFilesDir(context),
)

What this replaces is the manual effort of wiring chat history into SQLite, long-term memory, and artifact persistence, surviving process death (when Android kills the app in the background). Running the agent on-device with LiteRT-LM also opens the door to privacy and offline use, something a 100% cloud-based agent doesn't deliver.

Human-in-the-loop for sensitive actions

An agent that moves money can't act alone, and ADK handles this natively. Just mark the tool with requireConfirmation = true:

kotlin
@Tool(
    name = "transferFunds",
    description = "Transfers money. Requires explicit user approval.",
    requireConfirmation = true
)
fun transferFunds(@Param("Recipient account ID") recipientId: String, @Param("Amount in USD") amount: Double): String

When the model decides to call this tool, ADK pauses execution and issues a synthetic confirmation request. The UI intercepts that request, shows the confirm button, and, on the next turn, returns a FunctionResponse with CONFIRMED_KEY = true to resume and execute the transfer. It's the two-turn confirmation pattern, with session serialization and resumability built in. The post itself notes: the example is illustrative and wasn't designed to meet compliance requirements.

When it's not worth it (and how to get started)

ADK for Kotlin makes sense for those already living in the JVM/Android ecosystem who want idiomatic agents without carrying Python in the production stack. On the server side, there's integration with Vertex AI (VertexAiSessionService, VertexAiRagMemoryService, VertexAiMemoryBankService) and first-class interoperability with Java, meaning you can call a Kotlin agent from inside an existing Java application.

Where to weigh things before adopting: it's a freshly launched 1.0 framework, some extensions are still in beta (ML Kit on-device, for example), and orchestration remains coupled to the Google ecosystem (Gemini, Firebase, Vertex AI). Those who need vendor neutrality or have already standardized on LangChain/another multi-language runtime may not want to migrate just for language convenience. And the cost of running the model (whether cloud tokens or on-device battery and memory) remains a problem for the builder, not the framework.

To try it out, the dependencies go in build.gradle.kts:

kotlin
dependencies {
    implementation("com.google.adk:google-adk-kotlin-core:1.0.0")
    ksp("com.google.adk:google-adk-kotlin-processor:1.0.0")
    // optional Android extensions
    implementation("com.google.adk:google-adk-kotlin-firebase-android:1.0.0")
    implementation("com.google.adk:google-adk-kotlin-litertlm:1.0.0")
}

The code, examples, and documentation are in the github.com/google/adk-kotlin repository and at adk.dev.

Translated from the Brazilian Portuguese original · Read the original

View profile →