一个 KMP 核心的 Agent 框架,意味着什么
做 Kotlin 的人这两年大概都有个心结。
AI Agent 的浪潮一波接一波,但翻开源码一看——LangChain、CrewAI、AutoGen,清一色 Python。想在自己熟悉的 Kotlin 生态里搭一套 Agent,要么自己拿 HTTP 客户端手搓,要么用 Python 写个服务再从 Kotlin 调,中间隔着进程和序列化的双重麻烦。
9 月 9 日,Google 把这个空缺补上了:Agent Development Kit (ADK) for Kotlin 1.0 正式 GA。
而且这次不是简单地把 Python 版翻译一遍——它的底层是一个 Kotlin Multiplatform (KMP) 核心。
这个细节很关键,后面细说。
先看它到底是个什么东西
ADK for Kotlin 的定位很清楚:与后端模型、会话存储、记忆系统完全解耦。
说人话就是:Agent 的逻辑用 Kotlin 写一遍,模型可以接 Gemini,也可以接别的;会话存内存、存 Room、还是存云端,随你换。
1.0 版本已经和 ADK Python / Java 版功能对齐,把 Python 生态里那些成熟的多智能体模式搬了过来:
- 层级多智能体:Agent 可以链式编排,把任务委派给专门的子 Agent
- 上下文压缩:历史对话太长时自动摘要,把 token 控制在窗口内
- Human-in-the-loop:敏感操作可以暂停,等用户确认后再继续执行
- 会话可恢复:Agent 交互状态能序列化保存,跨会话恢复
- Java 互操作:现存的 Java 应用可以直接调用 Kotlin 写的 Agent
- Vertex AI 集成:企业级的 Session、RAG Memory、Memory Bank 服务
这里有一条我觉得特别值得说的:上下文压缩。
写过 AI Chat 的人都懂,多轮对话的历史管理是个绕不开的活儿。做滑动窗口会丢信息,全量塞进去会爆 token。ADK 把它做成了框架内置能力,不用自己造轮子。
技术亮点:为什么说它是"Kotlin 原生"
这是我觉得 ADK for Kotlin 最有意思的地方。
用注解定义工具,编译期生成 schema
Python 的 Agent 框架普遍靠运行时反射来解析函数签名、生成工具描述。ADK for Kotlin 走了另一条路——用 KSP(Kotlin Symbol Processing)在编译期生成。
你的代码写起来就是普通的 Kotlin 函数:
class InfrastructureDiagnosticsService {
@Tool
suspend fun getServiceMetrics(
@Param("Target service or database cluster") serviceName: String,
@Param("Time window in minutes") windowMinutes: Int? = 15,
): ServiceMetrics {
// 查监控后端:Datadog、Prometheus、Cloud Monitoring
return ServiceMetrics(
serviceName = serviceName,
cpuUsagePercent = 91.4,
connectionPoolUsagePercent = 98.5,
p99LatencyMs = 2450,
errorRatePercent = 4.2,
)
}
}
编译期 KSP 会自动生成 generatedTools() 扩展函数。
这意味着三件事:类型安全(schema 和函数签名不会对不上)、支持 suspend 函数(协程天然融入)、零运行时反射(启动快、体积小,对 Android 尤其友好)。
对写惯了编译期校验的 Kotlin 开发者来说,这个设计取向应该会很有共鸣——能在编译期发现的问题,就别拖到运行时。
Skill 机制:渐进式披露
ADK 里有个叫 Skill 的概念,我觉得设计得挺巧。
你把标准作业流程写成 SKILL.md 放在 resources 里:
---
name: database-incident-triage
description: Standard operating procedure for diagnosing database latency spikes.
allowed-tools: [getServiceMetrics, fetchRecentDeployments, notifyOnCall]
---
# Database Incident Triage SOP
1. **Telemetry**: Call `getServiceMetrics` to inspect CPU, latency, and pool saturation.
2. **Correlation**: Call `fetchRecentDeployments` to check for recent changes.
3. **Safety Rules**: Never restart primary nodes during peak hours.
4. **Notify**: Broadcast diagnosis to `#production-alerts`.
Agent 只在需要时才把这份 SOP 加载进上下文,附带的资源文件(比如 assets/mitigation_rules.txt)也是按需拉取。
官方管这叫 progressive disclosure——token 花在刀刃上,别一上来就把所有知识灌给模型。
上手实战:一个数据库故障诊断 Agent
官方给的示例很实在。假设线上数据库告警了,我们要个 Agent 来帮忙分诊:
object IncidentTriageDemoAgent {
val rootAgent = LlmAgent(
name = "incident_triage_agent",
model = Gemini(name = "gemini-3.8-flash"),
instruction = Instruction(
"""
You are an SRE on-call diagnostic assistant.
1. Load the matching triage SOP using `load_skill`.
2. Follow the playbook steps strictly.
3. Use your diagnostics tools to inspect telemetry and notify the team.
""".trimIndent()
),
// 编译期生成的函数工具(零反射)
tools = InfrastructureDiagnosticsService().generatedTools(),
// 动态技能工具集
toolsets = listOf(SkillToolset(NewFileSystemSource(resolveSkillsDir()))),
)
}
跑起来:
fun main() = runBlocking {
val runner = InMemoryRunner(
agent = IncidentTriageDemoAgent.rootAgent,
appName = "IncidentTriageApp"
)
val alert = "ALERT [P1]: Database latency spike detected on 'users-postgres-cluster'!"
val events = runner.runAsync(
userId = "oncall-sre",
sessionId = UUID.randomUUID().toString(),
newMessage = Content.fromText(Role.USER, alert)
).toList()
for (event in events) {
event.content?.parts?.firstOrNull()?.text?.let { println("Agent: $it") }
}
}
注意这里用的是 runBlocking + 流式事件——协程是这套框架的一等公民,不是硬塞进去的。
Agent 接到告警后会自动走完一套流程:加载 SOP → 调 getServiceMetrics() 发现连接池饱和 98.5% → 调 fetchRecentDeployments() 定位到 25 分钟前的一次部署 → 推送诊断到告警频道 → 建议回滚。
这就是一个完整的工具调用 + 领域知识 + 自主决策的闭环。
Android 端侧:不只有云端
如果你做移动端,ADK for Kotlin 的 Android 扩展可能更让你兴奋。
移动端 AI 的难点在于平衡:云端推理能力强,但延迟、隐私、离线可用性都是问题。ADK for Kotlin 1.0 给了一套模块化的 Android 方案:
- LiteRT-LM:端侧跑小模型
- ML Kit(beta):本地推理能力
- Firebase AI Logic:云端 + 端侧的混合编排
- Room 持久化:会话历史存 SQLite,进程被杀也不丢
- AppSearch 索引记忆:端侧全文检索的记忆服务
- FileArtifactService:生成的文件(对账单、回执)直接落本地存储
官方那个"金融助手"示例把这些串起来了:
fun createAndroidRunner(applicationContext: Context, agent: LlmAgent): InMemoryRunner {
return InMemoryRunner(
agent = agent,
appName = "AndroidFinancialApp",
// SQLite 持久化:进程死亡也能恢复会话
sessionService = RoomSessionService.fromContext(applicationContext),
// 端侧全文索引记忆
memoryService = AppSearchMemoryService.fromContext(applicationContext),
// 应用私有文件存储
artifactService = FileArtifactService.fromExternalFilesDir(applicationContext)
)
}
而且它把 HITL 做得很实用。转账这种敏感操作,定义工具时加个标记就行:
@Tool(
name = "transferFunds",
description = "Transfers money to another account. Requires explicit user approval.",
requireConfirmation = true
)
fun transferFunds(
@Param("Recipient account ID") recipientId: String,
@Param("Amount in USD") amount: Double
): String { /* ... */ }
Agent 执行到这里会自动暂停,等用户在 UI 上点确认再继续。
这一条对做金融、医疗类 App 的同学,基本是刚需。
对 KMP 开发者意味着什么
回到开头说的那个"KMP 核心"。
ADK for Kotlin 的核心引擎是跨平台的,跟模型后端、会话存储、记忆系统全都解耦。这个架构选择的含义是:Agent 的业务逻辑可以共享。
想象一下:你的 Agent 编排逻辑、工具定义、SOP 技能文件,在 Android 上能跑,在服务端 JVM 上也能跑,未来如果 iOS 侧也支持,那就是一套代码三端复用——这不就是 KMP 一直在讲的故事吗。
结合我们之前聊的 Kotlin 2.4.20(Swift export 的 sealed class 映射、跨语言继承),Kotlin 在跨端 + AI 这两条线上的拼图,今年开始明显拼上了。
对做 AI Chat 客户端的开发者来说,还有个更直接的启发:框架级的能力(会话持久化、上下文压缩、HITL)已经有成熟实现了,不用再从零造。
怎么开始
加依赖就行:
dependencies {
// 核心引擎 + KSP 处理器
implementation("com.google.adk:google-adk-kotlin-core:1.0.0")
ksp("com.google.adk:google-adk-kotlin-processor:1.0.0")
// Android 端侧扩展(可选)
implementation("com.google.adk:google-adk-kotlin-mlkit-android:1.0.0-beta")
implementation("com.google.adk:google-adk-kotlin-litertlm:1.0.0")
implementation("com.google.adk:google-adk-kotlin-firebase-android:1.0.0")
}
官方资源:
- 📖 文档与入门:adk.dev
- 🐙 GitHub:github.com/google/adk-kotlin
- 📱 Android 指南:Building Android agents with ADK
- ☕ Java 互操作示例:ADK Kotlin Java sample
小结
ADK for Kotlin 1.0 的意义,我觉得不在于它又多了个 Agent 框架,而在于:
Kotlin 生态终于有了一套编译期安全、协程原生、跨端可复用的 Agent 开发方案。
它没有把 Python 的套路硬搬过来,而是按 Kotlin 的语言特性重新设计了一遍——KSP 代替反射、协程代替回调、KMP 核心代替单平台实现。
对做 KMP 的人来说,这是个值得认真看看的东西。
参考资料:Announcing ADK for Kotlin 1.0 - Google Developers Blog(2026-09-09,作者 Guillaume Laforge)
