ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

KMP全栈开发:从Android到AI Agent,一套Kotlin代码统治后端与智能体

KMP全栈开发:从Android到AI Agent,一套Kotlin代码统治后端与智能体 1. 从 Android 到 AI Agent一套 Kotlin 代码到底能省多少事KMPKotlin Multiplatform在 2026 年已经不只是“Android 跨平台工具”这么简单了。它现在能覆盖移动端、后端服务甚至 AI Agent 的运行环境。而 Koog 这个纯 Kotlin 的 Agent 框架出现后Android 开发者终于不用为了写一个智能体去硬啃 Python 生态了。你可以用同一套 Kotlin 代码库让 Android App 里跑一个本地 Agent同时后端 Ktor 服务也复用同一份 Agent 核心逻辑连工具定义都不用写两遍。这篇文章适合谁如果你已经有 Kotlin 或 Android 基础想搞清楚 KMP 怎么把 Android、后端、AI Agent 三端串起来那这篇就是给你写的。我会从 Gradle 多模块骨架开始给出 Koog Agent 配置和 Ktor 路由的可复制片段然后带你本地启动、接口联调把端到端链路跑通。过程中踩过的坑我也会标出来比如 expect/actual 的依赖顺序、Android dex 包体积暴涨这些。核心检索词先摆出来KMP 全栈开发、Kotlin AI Agent、Koog 框架、Ktor 后端、Android 智能体。你不需要先学 Python也不需要把 Agent 部署到云端才能跑。下面直接进入工程化落地。2. TaoToken 前置给 Koog Agent 配一个可用的模型入口Koog 本身是 Agent 编排框架它不绑定具体模型供应商。你要让 Agent 真正跑起来需要一个兼容 OpenAI 接口的模型服务入口。TaoToken 提供的就是这个入口——它的 API 地址是https://taotoken.net/api兼容 OpenAI 的/v1/chat/completions格式Koog 的OpenAIModelAdapter可以直接对接。为什么在 KMP 全栈场景里提这个因为你的 Agent 可能同时跑在 Android 端和 JVM 后端。Android 端如果直连模型 API需要处理密钥管理和网络权限后端则更适合集中管理密钥和限流。TaoToken 的接口两边都能用Android 端通过 Ktor Client 调用后端通过 Ktor Server 转发或直连代码复用度很高。你需要先拿到一个 API Key。访问https://taotoken.net/api-keys创建密钥注意这个 Key 只显示一次复制后存到环境变量里不要硬编码进代码。后端用System.getenv(TAOTOKEN_API_KEY)读取Android 端用BuildConfig字段注入避免提交到 Git。模型选择上Koog 的OpenAIModelAdapter需要指定model参数。TaoToken 支持的模型列表可以在https://taotoken.net/models查看选一个适合 Agent 工具调用的就行。如果你只是验证链路先用默认模型跑通后面再换。注意API Key 不要写进build.gradle.kts的明文字段也不要在 Android 端用local.properties以外的方式存储。后端用环境变量Android 用BuildConfiggradle.properties本地覆盖。3. 可复制配置Gradle 多模块骨架 Koog Agent Ktor 路由3.1 Gradle 多模块骨架先建一个 KMP 项目模块划分如下shared放 commonMain 的 Agent 核心和工具声明server放 JVM 后端的 Ktor 路由androidApp放 Android 入口。settings.gradle.kts里声明模块rootProject.name KmpAgentStack include(:shared) include(:server) include(:androidApp)shared/build.gradle.kts里配置 KMP 目标和 Koog 依赖plugins { kotlin(multiplatform) version 2.1.0 kotlin(plugin.serialization) version 2.1.0 } kotlin { jvm() androidTarget() sourceSets { val commonMain by getting { dependencies { implementation(org.jetbrains.kotlinx:kotlinx-coroutines-core:2.1.0) implementation(org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.0) implementation(ai.koog:koog-core:1.0.0) implementation(ai.koog:koog-agent:1.0.0) } } val jvmMain by getting { dependencies { implementation(io.ktor:ktor-client-core:3.1.0) implementation(io.ktor:ktor-client-cio:3.1.0) implementation(io.ktor:ktor-client-content-negotiation:3.1.0) implementation(io.ktor:ktor-serialization-kotlinx-json:3.1.0) implementation(ai.koog:koog-model-openai:1.0.0) } } val androidMain by getting { dependencies { implementation(io.ktor:ktor-client-okhttp:3.1.0) implementation(org.jetbrains.kotlinx:kotlinx-coroutines-android:2.1.0) } } } }这里有个关键点koog-model-openai放在jvmMain和androidMain各自声明不要放commonMain。因为模型适配器依赖平台 HTTP 客户端放 common 会导致编译期找不到实现。3.2 Koog Agent 配置在shared/src/commonMain/kotlin/com/agent/agent/CoreAgent.kt里定义 Agent 核心。Koog 的 Agent 构建用 DSL工具通过注解声明package com.agent.agent import ai.koog.agent.Agent import ai.koog.agent.AgentConfig import ai.koog.agent.llm.ModelAdapter import ai.koog.agent.tool.ToolCallExecutor import ai.koog.agent.tool.annotation.Tool import ai.koog.agent.tool.annotation.ToolParam import kotlinx.serialization.Serializable Serializable data class WeatherResult(val city: String, val temperature: Int, val condition: String) object AgentTools { Tool(name get_weather, description 获取指定城市的实时天气) suspend fun getWeather( ToolParam(description 城市名称, required true) city: String ): WeatherResult { return WeatherResult(city, (15..30).random(), listOf(晴, 多云, 阴).random()) } } class CoreAgent( private val modelAdapter: ModelAdapter, private val toolExecutor: ToolCallExecutor, private val config: AgentConfig AgentConfig.default() ) { private val agent Agent.builder() .model(modelAdapter) .tools(AgentTools) .config(config) .build() suspend fun chat(message: String): String { return agent.run(message) } }AgentConfig里可以调maxIterations和temperature。工具调用场景建议maxIterations设 10 以上temperature设 0.2 到 0.7 之间。3.3 Ktor 路由在server/src/main/kotlin/com/agent/server/AgentServer.kt里写 Ktor 入口package com.agent.server import ai.koog.model.openai.OpenAIModelAdapter import ai.koog.agent.tool.ToolCallExecutor import com.agent.agent.CoreAgent import com.agent.agent.AgentTools import io.ktor.server.application.* import io.ktor.server.engine.* import io.ktor.server.netty.* import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* import io.ktor.serialization.kotlinx.json.* import io.ktor.server.plugins.contentnegotiation.* import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json Serializable data class ChatRequest(val message: String) Serializable data class ChatResponse(val success: Boolean, val reply: String?, val error: String? null) fun main() { val apiKey System.getenv(TAOTOKEN_API_KEY) ?: error(TAOTOKEN_API_KEY not set) val modelAdapter OpenAIModelAdapter( apiKey apiKey, baseUrl https://taotoken.net/api/v1, model gpt-4o ) val toolExecutor ToolCallExecutor(AgentTools) val agent CoreAgent(modelAdapter, toolExecutor) embeddedServer(Netty, port 8080) { install(ContentNegotiation) { json(Json { prettyPrint true; ignoreUnknownKeys true }) } routing { get(/health) { call.respond(mapOf(status to ok)) } post(/api/chat) { val req call.receiveChatRequest() try { val reply agent.chat(req.message) call.respond(ChatResponse(true, reply)) } catch (e: Exception) { call.respond(ChatResponse(false, null, e.message)) } } } }.start(wait true) }baseUrl填https://taotoken.net/api/v1Koog 的 OpenAI 适配器会自动拼/chat/completions。如果你用其他兼容接口改这个地址就行。4. 验证请求本地启动与接口联调4.1 启动后端先设置环境变量再跑 Gradleexport TAOTOKEN_API_KEY你的Key ./gradlew :server:run看到Responding at http://0.0.0.0:8080就说明 Ktor 起来了。先测健康检查curl http://localhost:8080/health返回{status:ok}说明服务正常。4.2 调 Agent 接口发一个带工具调用的请求curl -X POST http://localhost:8080/api/chat \ -H Content-Type: application/json \ -d {message:北京今天天气怎么样}如果 Koog 正确识别了get_weather工具你会看到类似这样的返回{ success: true, reply: 北京今天天气晴气温 24 度。 }这说明 Agent 完成了“接收消息 → 决定调用工具 → 执行工具 → 生成回复”的完整链路。如果返回success: false先看error字段常见的是 API Key 无效或模型名不对。4.3 Android 端联调Android 端复用shared模块的CoreAgent但模型适配器换成 Android 平台的 Ktor Client。在androidApp里初始化val modelAdapter OpenAIModelAdapter( apiKey BuildConfig.TAOTOKEN_API_KEY, baseUrl https://taotoken.net/api/v1, model gpt-4o ) val agent CoreAgent(modelAdapter, ToolCallExecutor(AgentTools))然后在 Compose 界面里调agent.chat(input)把结果渲染到聊天列表。Android 端需要INTERNET权限如果要用通知工具再加POST_NOTIFICATIONS。5. 本篇常见错排查5.1 expect/actual 编译报错 “cannot find symbol”这个坑我踩过。原因是commonMain里声明了expect函数但jvmMain的actual实现引用了 Ktor而 Ktor 依赖只加在了commonMain或加错了 source set。正确做法是commonMain只放纯 Kotlin 逻辑平台相关依赖全部放jvmMain和androidMain。检查build.gradle.kts里jvmMain的dependencies块确保ktor-client-cio和koog-model-openai都在里面。5.2 Android dex 包体积暴涨引入 Ktor 和 Koog 后APK 从 5MB 涨到 18MB 是常见现象。原因是 JVM 运行时带进了大量 Android 不需要的类。解决方案有两个一是用packaging排除无用资源android { packaging { resources { excludes listOf( /META-INF/AL2.0, /META-INF/LGPL2.1, /META-INF/INDEX.LIST, /META-INF/io.netty.* ) } } }二是 Android 端用ktor-client-okhttp替代ktor-client-cioOkHttp 在 Android 上体积更小、性能更好。5.3 Koog 工具调用不触发如果 Agent 一直不调工具只返回纯文本先检查Tool注解的name和description是否清晰。Koog 把工具描述发给模型描述太模糊模型就不会调。另外确认AgentConfig里enableTools是truemaxIterations至少设 5。如果还不行把temperature降到 0.2 再试。5.4 Ktor 路由返回 415 Unsupported Media Type这个通常是ContentNegotiation没装或call.receive的类型不对。确认install(ContentNegotiation) { json(...) }在routing之前并且ChatRequest加了Serializable。如果客户端发的是text/plain也会 415用curl时记得加-H Content-Type: application/json。5.5 API Key 读取失败后端用System.getenv(TAOTOKEN_API_KEY)如果你在 IDE 里直接跑main环境变量可能没传进去。在 IntelliJ 的 Run Configuration 里手动加环境变量或者用./gradlew :server:run从终端启动。Android 端用BuildConfig字段在build.gradle.kts里加android { buildConfigField(String, TAOTOKEN_API_KEY, \${project.findProperty(TAOTOKEN_API_KEY)}\) }然后在gradle.properties里写TAOTOKEN_API_KEY你的Key这个文件不要提交到 Git。6. 继续跑通你的 KMP Agent 链路到这里你已经有了一个能跑的 KMP 全栈骨架shared模块里的 Koog Agent 核心server模块的 Ktor 路由androidApp的 Compose 界面。三端复用同一份工具定义和 Agent 逻辑模型入口统一走 TaoToken 的兼容接口。接下来你可以做几件事。如果你要长期做编码类 Agent比如让 Agent 帮你写 Kotlin 代码、调工具、跑测试可以看看 Coding Plan 的配置方式它更适合高频工具调用场景。如果你只是想先验证模型对话和工具调用是否正常直接打开模型对话页面发几条消息确认接口通不通。如果你要管理多个项目的 API Key或者给团队分配不同权限的密钥去 API Keys 页面创建和管理就行。接入文档里有 Ktor、Koog 和 OpenAI 兼容接口的详细参数说明遇到路由或适配器问题可以先翻文档。链路跑通之后下一步就是把AgentTools里的模拟实现换成真实 API 调用比如天气接口、搜索接口然后观察 Koog 在多轮工具调用下的表现。
返回列表