Google 發布了 `ADK for Kotlin` 和 `ADK for Android` 的 `0.1.0` 版本。
以後不只有 SDK、NDK,還有 ADK。
ADK for Kotlin 用在 Kotlin 後端和通用 JVM 場景,ADK for Android 用在 Android App 裡,主要處理端側模型和 App 內上下文。
在 Android 工程裡先加這個依賴:
bash 体验AI代码助手 代码解读复制代码dependencies {
implementation("com.google.adk:google-adk-kotlin-core-android:0.1.0")
}
如果是一般 Kotlin 後端或 JVM 專案,用的是 google-adk-kotlin-core。需要透過註解生成工具程式碼時,還要加 KSP processor:
bash 体验AI代码助手 代码解读复制代码dependencies {
implementation("com.google.adk:google-adk-kotlin-core:0.1.0")
ksp("com.google.adk:google-adk-kotlin-processor:0.1.0")
}
0.1.0 還是實驗版本。它現在更像 Demo 專案裡的嘗鮮依賴,不適合直接接正式業務。Agent 呼叫失敗以後回傳什麼、模型不可用時怎麼降級、工具有沒有權限,這些都要在 App 程式碼裡處理。
寫 Agent 時會用到 LlmAgent。一個 Agent 裡會放模型、名稱、描述、系統指令、工具和子 Agent。下面是一個簡化後的旅遊助理。
旅遊助理裡有一個雲端 orchestrator,它先理解使用者的旅遊問題,再把訂票確認、飯店資訊、租車資訊這類任務交給裝置上的子 Agent 處理。訂票確認可能來自使用者本機文件,這一步可以交給 Gemini Nano 這類端側模型解析。程式碼只看核心欄位:
bash 体验AI代码助手 代码解读复制代码val orchestrator = LlmAgent(
name = "trip_orchestrator",
model = Gemini(apiKey = apiKey, name = MODEL_NAME),
instruction = Instruction(
"""
You are a travel assistant.
Use get_trip_details to read the trip plan.
Delegate booking checks to local sub agents when needed.
""".trimIndent()
),
tools = listOf(GetTripDetailsTool(tripId)),
subAgents = listOf(carRentalPipeline, hotelPipeline),
// 其他路由限制參數先省略,具體語義要看官方原始碼和 demo
)
這段程式碼裡,model 決定目前 Agent 要呼叫哪個模型,instruction 決定它怎麼理解任務,tools 是可呼叫能力,subAgents 是它可以轉交任務的下游 Agent。官方範例裡還有一些 transfer 相關參數,這裡不按名稱展開說明,等真的看原始碼或 demo 時再確認。
以前在 App 裡接一個大模型,很多時候只是把使用者輸入送到雲端介面,再把回覆顯示出來。換成 Agent 之後,ViewModel 裡那些「先查行程、再判斷訂單、最後組回覆」的分支會往 Agent 端挪,App 端更像是在等一個最終的 UI State。
放到 Android 裡之後,工具呼叫會碰到執行緒和生命週期。比如工具裡要讀取本地行程檔案,就要處理檔案不存在和讀取耗時;如果訂單資訊來自本地資料庫,也不要在主執行緒裡直接查詢。
ADK for Kotlin 支援用 @Tool 和 @Param 描述函式工具。工具本質上是把本地函式暴露給 Agent,讓模型在合適的時候呼叫它。
比如把一個訂單查詢能力交給 Agent,先看服務類:
bash 体验AI代码助手 代码解读复制代码class TripService {
@Tool
fun getBookingStatus(
@Param("Booking id from the user's trip document")
bookingId: String
): String {
return repository.findBookingStatus(bookingId)
}
}
@Tool 和 @Param 只是描述工具,還不是完整接入。官方 Kotlin 範例裡會透過 google-adk-kotlin-processor 做 KSP 生成,然後才能在 Agent 裡使用類似 generatedTools() 的結果。
也就是說,如果程式碼裡寫成下面這樣還不夠:
bash 体验AI代码助手 代码解读复制代码dependencies {
implementation("com.google.adk:google-adk-kotlin-core:0.1.0")
ksp("com.google.adk:google-adk-kotlin-processor:0.1.0")
}
Android 工程還要配置 KSP 插件。實際專案裡一般會在根專案或版本目錄裡宣告 com.google.devtools.ksp,再在模組裡套用插件。KSP 版本要和 Kotlin 版本對齊,這裡不寫死版本,舊專案直接照搬很容易卡在 Gradle Sync。
再配置 Agent 時,generatedTools() 不是手寫出來的一般方法,而是註解處理後的產物。沒有 KSP 插件和 processor 這兩步,直接照抄這段程式碼大概率會編譯不過。
bash 体验AI代码助手 代码解读复制代码val bookingAgent = LlmAgent(
name = "booking_agent",
description = "Checks booking status from local trip data.",
model = Gemini(apiKey = apiKey, name = "gemini-2.5-flash"),
instruction = Instruction("Use tools to verify booking status."),
tools = TripService().generatedTools()
)
這裡的 @Param 不只是給開發者看的註解,它會影響模型理解參數含義。參數從哪裡來、格式是什麼、失敗時回傳什麼,都要寫清楚。
如果工具函式裡要讀本地行程檔案,這些邏輯仍然走原本的 Android 程式碼。Agent 只拿工具回傳的結果,不應該跳過檔案不存在、讀取失敗和權限拒絕這些分支。
這裡還有一個容易踩坑的地方:狀態。一個 Agent 問使用者補充資訊,另一個 Agent 要知道前面已經確認過什麼;工具呼叫失敗以後,後面的 Agent 也要知道這一步失敗了。否則上游吐了一個空結果,下游還繼續拼 prompt,最後使用者看到的就是一段像正常回答的幻覺回覆。
ADK 裡有 Session state 和 Memory service。Session state 更像短期狀態,服務於目前會話裡的上下文共享;Memory service 更偏長期記憶,可以保存跨會話的資訊。
在 Android 工程裡使用這些能力時,不要簡單理解成 SharedPreferences 或聊天紀錄。Agent 狀態可能包含使用者輸入、模型輸出、工具呼叫參數、本地資料摘要和錯誤資訊。哪些能落盤,哪些只能留在記憶體,哪些不能進日誌,需要先訂好規則。
我真的學不動了。
#Android #Kotlin #ADK #GeminiNano #AI