PlantUML diagrams for future agent architecture (Android, multi-user chat, sub-agents, A2A): - 01-module-layers.md — целевая модульная структура - 02-agent-composition.md — AgentBuilder DSL + MemoryBackend.exposesTools() - 03-multi-user-chat.md — mention-detection sequence - 04-sub-agents.md — spawnChild + Flow<SubAgentEvent> + A2A - 05-android-stack.md — что меняется на Android vs Standalone Каждый .md включает пред-рендеренный SVG (показывается во всех markdown viewers без PlantUML plugin) + PlantUML source в code block (для редактирования). SVG нужен потому что PlantUML требует Graphviz dot для рендеринга — без него IntelliJ/VSCode выдают ошибку. Регенерация SVG после правки PlantUML-source: docker run --rm -v "$PWD:/work" plantuml/plantuml -tsvg /work/docs/diagrams/*.md
5.9 KiB
05 — Android Agent Stack
Что меняется vs :standalone. Цель: BaseAgent тот же самый, но platform-impl разные (Storage, LLM, Vector Memory, MCP).
PlantUML source (для редактирования; требует Graphviz dot для рендеринга):
@startuml android-agent-stack
skinparam componentStyle rectangle
title Android Agent Stack — что меняется vs Standalone
' --- Android side ---
package "Android Application" {
[MainActivity\n(Compose)] as Activity
[AndroidAgentRunner\n(workmanager / service)] as Runner
[AndroidAgentBuilder] as AndroidBuilder
}
package "Android-specific impls" {
[StorageSqliteAndroid\n(Room/sqlite)] as StorageA
[MemoryVectorAndroid\n(ONNX runtime + ANN)] as MemVecA
[LitertAndroid\n(NNAPI delegate)] as LitertA
[SoulFileAndroid\n(context.filesDir)] as SoulA
[McpRegistry\nstdio: ProcessBuilder] as McpA
}
' --- Shared (KMP) ---
package "Agent Runtime (shared)" {
[AgentCore\nBaseAgent] as AgentCore
[AgentBuilder] as Builder
}
package "Domain (shared)" {
[LlmTools\ncommonMain] as LlmT
[BackgroundEvents\ncommonMain] as Ev
[McpBridge\njvmMain] as McpB
[Skills\ncommonMain] as Skills
}
package "Memory (shared impl)" {
[MemoryMd\n(commonMain)] as MemMd
[MemoryApi\ninterfaces] as MemApi
}
' --- Зависимости ---
Activity --> Runner
Runner --> AndroidBuilder
AndroidBuilder --> AgentCore
AndroidBuilder --> StorageA
AndroidBuilder --> MemVecA
AndroidBuilder --> LitertA
AndroidBuilder --> SoulA
AndroidBuilder --> McpA
AgentCore --> LlmT
AgentCore --> Ev
AgentCore --> McpB
AgentCore --> Skills
AgentCore --> MemMd
' --- Главные отличия от Standalone ---
note right of LitertA
On-device inference.
LiteRT с NNAPI delegate →
работает на CPU/GPU/NPU
прямо на устройстве, без сети.
vs Standalone: HTTP-only
(OpenAI-compatible).
end note
note right of StorageA
android.database.sqlite
через Room или сырой API.
vs Standalone: JDBC +
Sqlite-JDBC driver
(только JVM).
end note
note right of MemVecA
JVector JVM-only. На Android
нужна альтернатива —
ONNX Runtime + какой-нибудь
ANN (Annoy/HNSW).
Или пока без vector memory,
только MemoryMd.
end note
note right of McpA
MCP через ProcessBuilder
на Android работает, но
subprocess lifecycle
сложнее (foreground service
нужен для долгого subprocess).
end note
@enduml
Что общего с :standalone
BaseAgent, BackgroundScheduler, LlmTools, McpBridge, Skills, MemoryMd — всё KMP (commonMain). Android-agent = :standalone с другим wiring'ом. Не нужно переписывать agent logic.
Что другое
| Компонент | :standalone (JVM) |
:agentik-android (Android) |
Сложность |
|---|---|---|---|
| Storage | :storage-sqlite (JDBC + Sqlite-JDBC) |
:storage-sqlite-android (Room или raw) |
Низкая — тот же StorageBundle interface |
| LLM | :litert-openai (HTTP), :litert-google (LiteRT JVM) |
:litert-android (LiteRT Android, NNAPI delegate) |
Средняя — нужен новый модуль |
| Vector memory | :memory-vector (JVector) |
:memory-vector-android (ONNX Runtime + HNSW/Annoy) |
Высокая — JVector JVM-only, нужна альтернатива |
| SOUL provider | FileSoulProvider (path) |
SoulFileAndroid (context.filesDir) |
Низкая |
| MCP | McpRegistry (ProcessBuilder, stdio subprocess) |
Тот же McpRegistry, но subprocess в foreground service |
Средняя — нужен Android service |
| Embedding | HttpEmbeddingClient (HTTP) |
Тот же ИЛИ on-device (ONNX) | Средняя |
Минимальный Android agent (v1)
Если не нужны все фичи сразу — минимум:
val agent = androidAgentBuilder(context) {
llm(LitertAndroid.onDevice(context, modelPath = "/data/local/tmp/model.litertlm"))
storage(SqliteStorage.android(context, "agent.db"))
memory(MemoryMd.root(context.filesDir.resolve("memory")))
soul(FileSoul(context.filesDir.resolve("SOUL.md")))
background {
// OnClosing + OnCompaction работают так же как на JVM
}
}
Без MCP, без vector memory (только MemoryMd на файлах), только on-device LLM. Достаточно для off-line агента.
Foreground service для MCP
Если нужны MCP-серверы (например, локальный file-system MCP) — subprocess нужен foreground service чтобы Android не убил его при выключении экрана. Это добавляет сложности:
class McpForegroundService : Service() {
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
startForeground(NOTIFICATION_ID, notification)
val proc = ProcessBuilder(command, args).start()
// ... route stdio to McpLiteToolAdapter ...
return START_STICKY
}
}
Пока можно без этого (только если MCP нужен на Android).
Текущее состояние vs целевое
✅ KMP-ready:
:llm-tools(commonMain, платформо-агностик):mcp-bridge(jvmMain — Android-вариант через:mcp-bridge-android):skills(commonMain):memory-md(commonMain):proto(commonMain)
⏳ Не существует:
:storage-sqlite-android:memory-vector-android:litert-android:agentik-android(само приложение):agent-core(выделить BaseAgent + builder):background-events(выделить events + scheduler)