AI-агенты на Kotlin Multiplatform: полное руководство 2026 | AiManual
AiManual Logo Ai / Manual.
23 Фев 2026 Гайд

Практическое руководство: разработка AI-агентов на Kotlin Multiplatform для Android, iOS, Web и Desktop

Пошаговая инструкция по созданию кроссплатформенных AI-агентов на Kotlin Multiplatform с локальными LLM. Актуальные инструменты и библиотеки на 2026 год.

Почему Kotlin Multiplatform для AI-агентов — это не просто мода, а вынужденная необходимость

В 2026 году писать отдельные кодовые базы для Android, iOS, Web и Desktop для одного AI-агента — это все равно что вручную настраивать каждый микросервис. Тратишь 80% времени на борьбу с платформенными причудами, а не на логику самого агента. Kotlin Multiplatform (KMP) обещает один код для всех платформ. Звучит как рай для разработчика, пока не пытаешься запихнуть туда модель Mistral-7B или GPT-4 Mini, которая весит 4 ГБ.

Проблема в двух словах: AI-агенты требуют сложной логики (планирование, цепочки мыслей, работа с инструментами), но при этом должны быть легкими, чтобы работать на iPhone 15 Pro и старом Android-смартфоне одновременно. Плюс, каждый магазин приложений имеет свои правила по обработке данных и размеру бандла. Пишешь на Python? Забудь о мобильных устройствах. Используешь Flutter? Готовься к сложной интеграции нативных AI-библиотек. KMP — это попытка взять лучшее от обоих миров: общую бизнес-логику на Kotlin и платформенную оптимизацию там, где это критично.

Архитектурный выбор: что оставить в common, а что выкинуть в platform

Самая большая ошибка — пытаться все запихнуть в общий код. Упаковывать вызовы к нейросетям, работу с камерой или доступ к файловой системе в common модуль — верный путь к хрупкому и неподдерживаемому коду. Вместо этого разделяй логику агента (что он делает) от исполнения (как он это делает).

  • Common (Kotlin Multiplatform): State-машина агента, планировщик задач, обработка промптов, управление памятью (что обсуждали с пользователем), логика выбора инструментов. По сути, мозг без рук и ног.
  • Platform-specific (Android, iOS, JS, Desktop): Всё, что касается железа и операционки: запуск моделей (инференс), доступ к сенсорам, запись в файлы, UI-рендеринг. Для работы с локальными LLM в 2026 году это чаще всего означает использование платформенно-оптимизированных рантаймов вроде MLC-LLM или Llama.cpp через Kotlin/Native или C-interop.
💡
Зачем так усложнять? Представь, что твой агент должен проанализировать фото документа, извлечь текст, найти ответ в локальной базе знаний и заполнить веб-форму. Common-часть решает, в какой последовательности это делать и как интерпретировать ответы. Нативная часть на Android делает снимок через CameraX, на iOS — через AVFoundation, а в вебе — через HTML5 Media API. Общая логика цепочки действий едина.

1 Настройка проекта: не повторяй моих ошибок с Gradle

Создавая новый проект в IntelliJ IDEA с плагином KMP, ты получаешь шаблонный build.gradle.kts. Он сломан для AI-проектов из коробки. Почему? Потому что не включает зависимости для работы с большими бинарными файлами (моделями) и нативными библиотеками.

Вот как надо делать. Сначала создаем структуру модулей:

// settings.gradle.kts
pluginManagement {
    repositories {
        mavenCentral()
        google()
        gradlePluginPortal()
    }
}

include(":shared")  // Общая логика агента
include(":androidApp")
include(":iosApp")
include(":desktopApp")
include(":webApp")

В build.gradle.kts общего модуля :shared добавляем необходимые зависимости. На февраль 2026 года актуальны:

  • Kotlinx Serialization 2.1.0 — для работы с промптами и ответами моделей в JSON.
  • Kotlinx Coroutines 1.9.0 — асинхронность, без этого никуда.
  • KMP-обертка для Model Context Protocol (MCP) SDK 0.5.0 — если твой агент должен работать с внешними инструментами и данными (базы данных, API, файлы). MCP стал стандартом де-факто для подключения инструментов к агентам.
  • Ktor Client 3.8.0 — для общения с облачными API моделей (если используешь гибридный подход).

Ошибка №1: Не добавляй тяжелые зависимости для инференса моделей (типа TensorFlow Lite) в commonMain. Они будут тянуться на все платформы и взорвут размер бандла. Вместо этого объяви expect/actual интерфейсы для инференса, а реализацию сделай в каждом целевом модуле.

2 Дизайн ядра агента: забудь о монолитных промптах

Самый примитивный агент — это одна большая функция, которая получает промпт и возвращает ответ от LLM. Он сломается при первой же сложной задаче. Современный агент — это stateful-система с памятью, планировщиком и набором инструментов. В common модуле определяем ключевые компоненты.

Основной цикл агента может выглядеть так (упрощенно):

// shared/src/commonMain/kotlin/com/youraibot/core/Agent.kt
class TaskPlanningAgent(
    private val llmClient: LLMClient, // expect interface
    private val toolRegistry: ToolRegistry,
    private val memory: AgentMemory
) {
    suspend fun execute(goal: String): Result {
        // 1. Планировщик разбивает цель на шаги
        val plan = planner.createPlan(goal)
        
        // 2. Исполнитель выполняет каждый шаг, используя инструменты
        for (step in plan.steps) {
            val tool = toolRegistry.getTool(step.toolName)
            val observation = tool.execute(step.parameters)
            memory.addObservation(observation)
            
            // 3. Рефлексия: оцениваем, движемся ли к цели
            if (shouldReplan(observation)) {
                return execute(adjustedGoal) // репланируем
            }
        }
        return Result.success(memory.getFinalResult())
    }
}

Это концептуальная схема. Для реальной работы изучи наше руководство по проектированию современных AI-агентов, где разобраны паттерны ReAct, Planner-Executor и потоковая память.

3 Интеграция моделей: локальные vs облачные, бинарные артефакты и боль

Здесь собака зарыта. В common модуле объявляем интерфейс LLMClient:

// shared/src/commonMain/kotlin/com/youraibot/core/LLMClient.kt
expect class LLMClient {
    suspend fun generate(prompt: String, options: GenerationOptions): String
    suspend fun generateStreaming(prompt: String): Flow
}

// Параметры генерации
data class GenerationOptions(
    val maxTokens: Int = 512,
    val temperature: Float = 0.7f,
    val stopSequences: List = emptyList()
)

А теперь actual реализации. Для Android (в модуле :androidApp) используем, например, TFLite с загруженной моделью Qwen2.5-Coder-3B-Instruct (актуальная на 2026 компактная модель для кода). Для iOS тот же llama.cpp, но собранный под arm64. Для Desktop (JVM) можно использовать более тяжелые модели через ONNX Runtime. Для Web — здесь самое сложное: либо WebGPU + ONNX WebAssembly, либо fallback на облачный API.

💡
Модели не включаются в APK или IPA напрямую — они весят гигабайты. Вместо этого при первом запуске приложение должно скачивать оптимизированную для данной платформы версию модели (GGUF или другого формата) из твоего CDN. И да, тебе нужен механизм резюмирования и докачки. Пользовательский опыт на кону.

4 Интерфейс: Compose Multiplatform или нативные экраны для каждого?

Compose Multiplatform в 2026 году стабилен для Android, Desktop и Web. Для iOS он все еще считается experimental, но уже работает. Если твой агент требует сложных, анимированных интерфейсов с графиками состояний — можешь рискнуть. Но если нужен нативный look-and-feel на iOS, готовься писать UI на SwiftUI и связывать его с KMP через Kotlin/Native кпдф.

Логику представления (ViewModel) все равно выноси в common. А вот реализацию Composable-функций — в соответствующие модули :compose-ui (для общих экранов) или в платформенные модули.

// shared/src/commonMain/kotlin/com/youraibot/presentation/ChatViewModel.kt
class ChatViewModel(
    private val agent: TaskPlanningAgent
) : ViewModel() {
    val uiState: StateFlow = ...
    
    fun onUserMessageSent(text: String) {
        viewModelScope.launch {
            val agentResponse = agent.execute(text)
            // Обновляем состояние
        }
    }
}

// :compose-ui/src/commonMain/kotlin/com/youraibot/ui/ChatScreen.kt
@Composable
expect fun ChatScreen(viewModel: ChatViewModel)

5 Тестирование: как отлаживать агента, который ведет себя по-разному на Snapdragon и Apple Silicon

Юнит-тесты для common логики — стандартно. Интеграционные тесты — ад. Поведение LLM недетерминировано, а еще оно зависит от точности вычислений с плавающей точкой на разных процессорах. Решение: мокировать LLMClient и тестировать только логику принятия решений агентом. Для тестов, близких к реальности, используй симуляторы.

Например, для тестирования навыка автоматизации Android (как в нашем обзоре touch-контроля) потребуется эмулятор или реальное устройство. Настрой CI/CD, который запускает такие тесты на ферме устройств.

6 Сборка и деплой: когда App Store спрашивает, что за бинарные файлы в твоем приложении

Включение предобученных моделей в бандл требует пояснений для ревьюеров магазинов. Готовь документацию о том, как модель используется, какие данные обрабатывает (желательно, локально) и откуда она скачана. Используй ресурсные папки для мелких моделей (до 100 МБ) и внешнее скачивание для больших.

Для подписи нативных библиотек (.so, .dylib) на Android и iOS потребуется корректно настроить задачи сборки в Gradle. На этом этапе многие сдаются и переходят на облачные API. Не сдавайся.

Чего точно делать не надо: грабли, на которые мы все наступали

  • Не храни промпты как строки в коде. Выноси их в ресурсы или отдельные конфигурационные файлы. Менять промпт для улучшения агента должно быть так же просто, как редактирование JSON.
  • Не игнорируйте квоты памяти на iOS. Локальная LLM, работающая в фоне, может быть убита системой. Используй background tasks и правильно обрабатывай приостановку состояния.
  • Не рассчитывай на одинаковую производительность инференса. Модель, которая генерирует 20 токенов в секунду на MacBook M3, на среднем Android будет выдавать 2-3 токена. Проектируй UX с индикаторами прогресса и возможностью прерывания длительных операций.
  • Не пренебрегай обновлением моделей. За год выходят более качественные и эффективные версии. Заранее продумай в приложении механизм обновления моделей без переустановки всего апка. (Спойлер: это сложно).

Вопросы, которые тебе зададут на тех-интервью (и правильные ответы)

ВопросКороткий ответЧто сказать подробнее
Как организовать потоковую генерацию текста из общей модели на всех платформах?Kotlin Flow в common, платформенные драйверы моделей должны поддерживать поточную отдачу токенов.Объясни разницу между blocking вызовом модели и callback-based streaming API на разных платформах. Покажи, как обернуть нативный callback в Flow.
Какой инструмент выбрать для создания агента, если не хочешь писать всё с нуля?В 2026 году посмотри на open-source фреймворки из нашего обзора AI-агентов недели, а также на OpenAI Agent SDK для Java.Большинство фреймворков написаны на Python. Для KMP придется либо искать Java/Kotlin аналоги, либо писать свои обертки.
Можно ли вообще обойтись без сервера для сложного агента?Да, но с оговорками. Локальные модели на устройствах стали мощнее, но для сложных цепочек с поиском в интернете или обработкой больших PDF все равно нужен прокси-сервер.Объясни гибридную архитектуру: легкий агент на устройстве + облачные функции для тяжелых операций. Это баланс между приватностью и функциональностью.

И последнее. Самый важный навык в разработке AI-агентов на KMP — не знание Kotlin, а умение разбивать задачу на общие и платформенные части. Начинай с простого агента с одной облачной моделью, выноси логику в common, затем заменяй облачный вызов на локальные реализации одну за другой. Так не сойдешь с ума. А когда заработает, вспомни, что есть еще архитектура на основе BPMN для бизнес-процессов. Но это уже совсем другая история.

Подписаться на канал