Google ADK for Kotlin 1.0: A Practical Guide to Production AI Agents

Google ADK for Kotlin 1.0: A Practical Guide to Production AI Agents

Google Agent Development Kit (ADK) for Kotlin 1.0 reaches general availability in September 2026, bringing Google’s agent-building framework to Kotlin Multiplatform and Android-first development. The release is aimed at developers who need more than a chat interface: multi-agent workflows, tool execution, approval steps, resumable sessions, local inference, cloud models, and deployment through Vertex AI Agent Platform. This guide explains how to choose ADK for Kotlin, structure an agent application, persist sessions, handle human confirmation safely, and decide when Python or JavaScript ADK remains the better option.

Artificial Neural Network with Chip
Image: mikemacmarketing / photo on flickr via Wikimedia Commons (CC BY 2.0)
Neural network   Midjourney and Grok
Image: Midjourney; prompt suggested by Grok via Wikimedia Commons (Public domain)

What ADK for Kotlin is designed to solve

An AI agent is an application that can interpret a request, decide which action to take, call tools, inspect results, and continue until it reaches a useful outcome. A production agent also needs boundaries. It must know which tools are available, which actions require user approval, how to recover from an interrupted run, and where conversation state is stored.

ADK for Kotlin provides a structured runtime for those concerns. Instead of placing model calls, tool definitions, and application state directly inside UI code, you define agents and compose them into workflows. Kotlin’s type system is useful here because tool inputs, outputs, configuration objects, and domain models can be represented explicitly. Kotlin Multiplatform also makes it possible to share orchestration and business logic across Android, iOS, desktop, and server targets while keeping platform-specific integrations separate.

The framework is particularly relevant when an Android application needs to combine local capabilities with cloud services. For example, a field-service app could use on-device LiteRT-LM for quick classification, ask a cloud model to produce a detailed repair plan, search local AppSearch indexes for manuals, and require a technician to approve any action that changes a work order.

ADK Kotlin versus Python and JavaScript ADK

ADK Kotlin is usually the best choice when Kotlin is already the application’s primary language or when Android is a central product surface. It fits naturally with Jetpack architecture, coroutines, Room, AppSearch, Compose, WorkManager, and Kotlin Multiplatform shared modules. It also reduces the boundary between the agent runtime and the rest of an Android application. A tool can call an existing repository, access a platform service through an interface, or return a strongly typed domain result without requiring a separate service written in another language.

Choose Python ADK when the agent is primarily a backend or data workflow. Python has a broad ecosystem for data processing, evaluation, machine learning, notebooks, scientific computing, and server-side integrations. It is often the better option for agents that operate over large document collections, connect to internal data platforms, or need extensive experimentation before being embedded in a mobile product.

JavaScript or TypeScript ADK is a strong fit for web applications, Node.js services, serverless routes, and teams that want a shared language between a browser interface and a backend. It is also convenient when the agent must integrate with JavaScript-native APIs or existing Next.js infrastructure.

These choices are not mutually exclusive. A common architecture uses ADK Kotlin on the client for offline or user-facing tasks and ADK Python or JavaScript on a server for long-running workflows. The client can submit a structured request, display progress, collect confirmation, and reconnect to a server-side run. The important design decision is to assign each agent to the environment where its data, latency, security, and operational requirements make the most sense.

Defining tools with Kotlin annotations

Tools are the controlled actions an agent can invoke. In ADK Kotlin, an annotated function can expose a capability to the model while keeping the implementation in ordinary Kotlin code. A simplified example might look like this:

class OrderTools(
    private val orders: OrderRepository
) {
    @Tool(description = "Find an order by its customer-visible order number")
    suspend fun findOrder(orderNumber: String): OrderSummary {
        require(orderNumber.length in 6..24)
        return orders.findByNumber(orderNumber)
            ?: throw ToolException("Order was not found")
    }
}

The annotation is not a replacement for validation. Tool implementations should validate every argument, enforce authorization, apply timeouts, and return a bounded result. Do not expose a raw database query, unrestricted HTTP client, shell command, or payment mutation as a general-purpose tool. Give each tool a narrow purpose and define what happens when it fails.

Tool descriptions matter because the model uses them to choose actions. Describe the user-visible purpose, required identifiers, side effects, and important limitations. Separate read-only tools from mutating tools. For example, previewRefund should be distinct from issueRefund. This makes confirmation flows easier to implement and makes audit records more meaningful.

Multi-agent orchestration

A single agent can become difficult to control when it handles planning, retrieval, domain rules, and execution at once. ADK Kotlin supports compositions in which specialized agents perform separate responsibilities. A coordinator might route a request to a retrieval agent, a policy agent, and an action agent. The coordinator then combines their results or asks for another step.

Use specialization to establish clear boundaries, not simply to create more model calls. A useful arrangement may include:

  • Router agent: classifies the request and selects the appropriate workflow.
  • Research agent: searches approved sources and returns citations or structured findings.
  • Decision agent: applies business rules and produces a proposed action.
  • Execution agent: invokes narrowly scoped tools after required approval.

For predictable processes, prefer explicit workflow steps over unrestricted delegation. A coordinator can require the research agent to finish before the decision agent starts, then pause before execution. This produces clearer traces, simpler retries, and more reliable tests than allowing every agent to call every other agent.

Human-in-the-loop confirmation

Confirmation is essential whenever an agent can send messages, modify records, spend money, publish content, delete data, or trigger an external process. The agent should produce a proposed action rather than silently performing it. The application displays the proposal, the affected resource, and the relevant parameters. The user can approve, reject, or edit the request.

A safe confirmation flow uses a durable action identifier. Store the proposed action and its parameters on the server or in protected application storage, then bind the user’s approval to that identifier. Do not trust a client to resend arbitrary tool arguments after displaying a preview. On approval, reload the stored proposal, reauthorize it, check whether the underlying data has changed, and execute it once with an idempotency key.

On Android, confirmation can be represented as a state in a Compose UI or as a notification that deep-links back into the application. The agent run should pause rather than block a thread. When the user responds, the workflow resumes with an explicit approval result. This is especially important for mobile applications, where the process may be interrupted by background limits, navigation, connectivity changes, or device restarts.

Session persistence with Room and AppSearch

Agent sessions should not depend on an in-memory process. Android can terminate an application at any time, so conversation history, workflow state, pending confirmations, tool results, and retry metadata need durable storage. Room is the usual choice for structured session data. Store normalized records such as sessions, messages, events, tool calls, approvals, and checkpoints. Include timestamps, schema versions, run identifiers, and a status field for each resumable operation.

AppSearch complements Room when the application needs fast local search across conversation content, notes, documents, or cached agent results. Keep Room as the source of truth and index selected fields in AppSearch. This prevents the search index from becoming the authoritative workflow database while still allowing users to find previous discussions quickly.

Persist events rather than only the latest transcript when debugging and recovery matter. An event record can capture that a tool was requested, arguments were validated, approval was required, approval was granted, and the tool completed. This event history supports audit views, replay tests, and recovery after a crash.

Resumability and interrupted runs

Resumability means an agent can continue from a known checkpoint instead of restarting from the beginning. A checkpoint should identify the workflow, current step, model response, pending tool call, tool result, and any required user input. Design every side-effecting step to be idempotent. If a network timeout occurs after a remote system accepted a request, a retry must not create a duplicate record or charge.

Kotlin coroutines make asynchronous execution convenient, but cancellation must be treated as a normal condition. Tie coroutine scopes to the lifecycle of the workflow rather than a screen. For longer operations, use an application-level worker or server-side execution service. When the UI reconnects, it should read the persisted run state and render the current status instead of assuming that the prior process is still alive.

On-device LiteRT-LM and ML Kit options

On-device inference is useful for privacy, low latency, offline operation, and predictable costs. LiteRT-LM can support local language-model tasks such as classification, extraction, short rewriting, or constrained assistant interactions, depending on the device and model requirements. Keep local prompts compact, cap output length, and define a fallback when the model is unavailable or too slow.

ML Kit is often a better choice for focused perception tasks than a general language model. Text recognition, barcode scanning, translation, language identification, and document-related features can be handled with specialized APIs. A production agent can use ML Kit to extract text from a photo, then pass the structured result to an ADK agent for reasoning.

Do not assume that local inference is automatically safer. Models and prompts shipped in an application can be inspected, and local outputs still require validation. Keep secrets and privileged operations on a trusted server. Use on-device models for tasks where their capabilities and threat model are appropriate.

Firebase AI Logic hybrid workflows

Firebase AI Logic is useful when an Android application needs a managed connection to cloud model capabilities while retaining Firebase-oriented application infrastructure. A hybrid workflow might first run a local model for intent detection, use AppSearch to retrieve relevant content, and then call a cloud model for a more capable response. The application can also route requests based on connectivity, sensitivity, latency, or model cost.

Use explicit routing policies instead of silently switching models. Record which model handled each step, whether data was sent to the cloud, and which safety or filtering settings were applied. For sensitive data, remove unnecessary fields before transmission and keep cloud calls behind server-controlled authorization where possible.

Vertex AI Agent Platform for production deployment

Vertex AI Agent Platform is the natural target for agents that need managed cloud execution, centralized observability, scaling, evaluation, and integration with enterprise data. A Kotlin mobile client can remain focused on interaction and local capabilities while the platform runs long-lived or privileged workflows.

Separate the mobile session from the server execution session. Use authenticated user identity, tenant boundaries, structured request schemas, and server-side authorization. Stream progress to the client when useful, but make the server’s persisted state authoritative. Add traces for model calls, tool calls, latency, token usage, retries, approvals, and failures. Before release, evaluate representative tasks, adversarial prompts, invalid tool arguments, interrupted workflows, and duplicate requests.

Production patterns that scale

  • Keep tools narrow, typed, validated, authorized, and observable.
  • Require confirmation for consequential side effects.
  • Persist workflow state and use checkpoints for resumability.
  • Use idempotency keys for retries and external mutations.
  • Prefer deterministic orchestration around model calls.
  • Use Room for structured state and AppSearch for local discovery.
  • Route tasks between LiteRT-LM, ML Kit, Firebase AI Logic, and Vertex AI according to capability and risk.
  • Store model and tool metadata for debugging and compliance.
  • Test tool failures, stale data, denied approvals, cancellation, and offline operation.
  • Keep secrets and privileged decisions on trusted infrastructure.

ADK Kotlin 1.0 is most compelling when an agent is part of a Kotlin application rather than a detached chatbot. Its value comes from connecting typed agent logic with Android lifecycle handling, local persistence, on-device processing, and cloud orchestration. Python and JavaScript ADK remain strong choices for backend-heavy and web-focused systems. In many production architectures, the best answer is a split: Kotlin for the Android experience and local intelligence, and a server-side ADK deployment for durable, privileged, and highly scalable work.

Comments

Popular posts from this blog

Grok Bot - a step closer to AGI

Tencent Hy4 Preview: Open 770B MoE Built for Real Work

Microsoft MAI-Image-2.6 and MAI-Image-2.6-Flash for Developers: Choosing the Right Production Image Model