diff --git a/docs/diagrams/01-module-layers.md b/docs/diagrams/01-module-layers.md
new file mode 100644
index 0000000..e3b5bab
--- /dev/null
+++ b/docs/diagrams/01-module-layers.md
@@ -0,0 +1,158 @@
+# 01 — Слои модулей (целевое состояние)
+
+Целевая модульная структура agentik. Снизу вверх:
+**приложения → runtime → домен → абстракции → платформенные impl**.
+
+
+
+PlantUML source (для редактирования; требует Graphviz `dot` для рендеринга):
+
+```plantuml
+@startuml agentik-module-layers
+skinparam componentStyle rectangle
+skinparam ranksep 60
+skinparam nodesep 30
+skinparam packageStyle rectangle
+
+title agentik — слои модулей (целевое состояние)
+
+' --- Applications: entry points (thin wrappers) ---
+package "Applications\n(entry points, тонкие)" {
+ [Standalone\nHTTP+AG-UI+A2A] as Standalone
+ [AgentikCli\nREPL] as Cli
+ [AgentikAndroid\nCompose UI] as Android
+}
+
+' --- Agent runtime ---
+package "Agent Runtime\n(композиция, lifecycle)" {
+ [AgentCore\nBaseAgent] as AgentCore
+ [AgentBuilder\nDSL] as Builder
+}
+
+' --- Background work ---
+package "Background Work\n(event-driven triggers)" {
+ [BackgroundEvents\nbus + events] as Ev
+ [BackgroundScheduler\npolicy] as Sched
+}
+
+' --- Domain logic (generic, переиспользуется) ---
+package "Domain Logic\n(generic tools)" {
+ [LlmTools\nReflector/Reviewer/Miner] as LlmT
+ [McpBridge\nMCP-SDK → LiteTool] as Mcp
+ [Skills\nparse + store] as Skills
+}
+
+' --- Storage abstractions + impls ---
+package "Storage\n(abstractions)" as StoragePkg {
+ [StorageCore\ninterfaces] as StorageCore
+}
+
+package "Storage\n(JVM impls)" {
+ [StorageSqlite\nJDBC] as StorageSql
+ [StorageInmemory\ntests] as StorageInmem
+}
+
+package "Storage\n(Android impl)" {
+ [StorageSqliteAndroid\nRoom/sqlite] as StorageSqlA
+}
+
+' --- Memory backends ---
+package "Memory\n(abstractions)" {
+ [MemoryApi\nMemorySystem/MemoryTools] as MemApi
+}
+
+package "Memory\n(impls)" {
+ [MemoryMd\nHermes §-files] as MemMd
+ [MemoryVector\nJVector+JVM] as MemVec
+ [MemoryVectorAndroid\nONNX+ANN] as MemVecA
+}
+
+' --- LLM backends ---
+package "LLM\n(abstractions)" {
+ [LitertApi\nLiteLlm контракт] as Litert
+}
+
+package "LLM\n(impls)" {
+ [LitertOpenai\nHTTP] as LitertO
+ [LitertGoogle\nLiteRT JVM] as LitertG
+ [LitertAndroid\nLiteRT Android] as LitertA
+}
+
+' --- Inter-app protocol ---
+package "Inter-app" {
+ [Proto\nAgent/Conversation] as Proto
+ [A2AServer] as A2A
+}
+
+' --- Зависимости (приложения → runtime → домен → абстракции → платформенные импл) ---
+Standalone ..> Builder
+Cli ..> Builder
+Android ..> Builder
+
+Builder ..> AgentCore
+AgentCore ..> Proto
+AgentCore ..> StorageCore
+AgentCore ..> MemApi
+AgentCore ..> Litert
+AgentCore ..> Mcp
+AgentCore ..> Skills
+
+Sched ..> Ev
+AgentCore ..> Sched
+AgentCore ..> Ev
+
+Mcp ..> Litert
+LlmT ..> Litert
+
+MemMd ..> MemApi
+MemVec ..> MemApi
+MemVecA ..> MemApi
+
+StorageSql ..> StorageCore
+StorageInmem ..> StorageCore
+StorageSqlA ..> StorageCore
+
+LitertO ..> Litert
+LitertG ..> Litert
+LitertA ..> Litert
+
+Standalone ..> A2A
+Standalone ..> LitertO
+Standalone ..> LitertG
+Standalone ..> StorageSql
+Standalone ..> MemMd
+Standalone ..> MemVec
+Standalone ..> Mcp
+
+Android ..> LitertA
+Android ..> StorageSqlA
+Android ..> MemMd
+Android ..> MemVecA
+
+@enduml
+```
+
+## Что показывает
+
+- **Applications** — три точки входа: web-сервер, CLI REPL, Android-приложение. Каждое тонкое, не содержит бизнес-логики.
+- **Agent Runtime** — `BaseAgent` + `AgentBuilder` DSL. Вся композиция и lifecycle.
+- **Background Work** — `BackgroundEvents` (event-bus) + `BackgroundScheduler` (policy подписки). Event-driven, не interval-polling.
+- **Domain Logic** — generic переиспользуемые модули (`:llm-tools`, `:mcp-bridge`, `:skills`).
+- **Storage / Memory / LLM** — каждая с абстракцией и одним или несколькими impl (JVM-only или Android-only).
+- **Inter-app** — `:proto` контракты + `:a2a-server` для межагентного общения.
+
+## Текущее состояние vs целевое
+
+✅ Уже сделано (в этом цикле правок):
+- `:llm-tools` extracted
+- `:mcp-bridge` extracted
+- `BackgroundScheduler` стал event-driven
+- `ConversationLoop` стал отдельным компонентом (typealias `ChatConversation`)
+
+⏳ Не сделано:
+- `:agent-core` (выделить `BaseAgent` + builder в отдельный KMP-модуль)
+- `:background-events` (выделить events + scheduler — пока в `:standalone`)
+- `:storage-sqlite-android`
+- `:memory-vector-android`
+- `:litert-android`
+- `:agentik-android` (само приложение)
diff --git a/docs/diagrams/01-module-layers.svg b/docs/diagrams/01-module-layers.svg
new file mode 100644
index 0000000..53a2eca
--- /dev/null
+++ b/docs/diagrams/01-module-layers.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/diagrams/02-agent-composition.md b/docs/diagrams/02-agent-composition.md
new file mode 100644
index 0000000..317011e
--- /dev/null
+++ b/docs/diagrams/02-agent-composition.md
@@ -0,0 +1,127 @@
+# 02 — Agent Builder: композиция (целевое API)
+
+Как `AgentBuilder` собирает `BaseAgent` из компонентов. **Memory backend сам объявляет свои tools** — builder их авто-мержит. BackgroundScheduler подписан на события, не interval-poll.
+
+
+
+PlantUML source (для редактирования; требует Graphviz `dot` для рендеринга):
+
+```plantuml
+@startuml agent-composition
+skinparam componentStyle rectangle
+
+title Agent Builder — композиция (целевое API)
+
+' --- Builder ---
+rectangle "AgentBuilder" as Builder {
+ rectangle "llm: LiteLlm (обязательно)" as Llm
+ rectangle "storage: StorageBundle (обязательно)" as Storage
+ rectangle "memory: MemorySystem (обязательно)" as Mem
+ rectangle "soul: SoulProvider (default NoopSoul)" as Soul
+ rectangle "tools: List (авто-сборка из backends)" as Tools
+ rectangle "background: BackgroundConfig (default EmptyBg)" as Bg
+ rectangle "toolset: List (default empty)" as Ts
+}
+
+' --- Backends with their tool side-effects ---
+rectangle "MemoryMd" as MdMem {
+ interface "MemorySystem" as MemSys
+ interface "List" as MdTools
+ note right
+ MemoryMd.exposesTools() →
+ memory_save / memory_read /
+ memory_list / memory_delete
+ end note
+}
+
+rectangle "McpRegistry" as McpReg {
+ interface "List" as McpTools
+ note right
+ McpRegistry.namedTools →
+ server__tool1, server__tool2,
+ ...
+ end note
+}
+
+rectangle "BackgroundEvents" as Events {
+ interface "MutableSharedFlow" as Flow
+ note right
+ Эмитится из:
+ - CompactionCoordinator
+ - ToolDispatcher
+ - ConversationLoop.close()
+ end note
+}
+
+rectangle "BackgroundScheduler" as Sched {
+ interface "policy: trigger + debounce" as Policy
+ note right
+ Подписан на Events.
+ НИКАКОГО interval-polling.
+ end note
+}
+
+' --- Получаемый Agent ---
+rectangle "BaseAgent\n(impl: ConversationLoop)" as Agent {
+ rectangle "send / interrupt / events" as API
+ rectangle "BackgroundScheduler\nподписка" as Sub
+}
+
+' --- Стрелки зависимостей ---
+Builder --> Llm
+Builder --> Storage
+Builder --> Mem
+Builder --> Soul
+Builder --> Tools
+Builder --> Bg
+Builder --> Ts
+
+MdMem --> Mem : implements
+MdMem --> MdTools : exposes
+
+McpReg --> McpTools : exposes
+
+Bg --> Events : subscribes-to
+Bg --> Sched : holds
+
+Tools <-- MdTools : auto-merge
+Tools <-- McpTools : auto-merge
+
+Builder --> Agent : build()
+Agent --> API
+Agent --> Sub
+
+@enduml
+```
+
+## Целевой Kotlin DSL
+
+```kotlin
+val agent = agentBuilder {
+ // Обязательные
+ llm(OpenAiLlm.fromEnv()) // или LitertAndroid.onDevice(context)
+ storage(SqliteStorage(path)) // или SqliteStorage.android(context)
+ memory(MemoryMd(root = "~/memory")) // или MemoryVector(embedding = HttpEmbedding(...))
+
+ // Опциональные
+ soul(FileSoul("~/SOUL.md")) // или HttpSoul(url), NoopSoul()
+ background {
+ // triggers: OnClosing (reflection+mining), OnCompaction(minTurns=10, mining=true)
+ // event-driven, не interval
+ }
+ tools {
+ // memoryMd.exposesTools() + mcpRegistry.namedTools авто-подцепляются
+ +FileReadTool(root = "/data")
+ }
+ toolset {
+ +MemoryToolsToolset(memoryMd)
+ }
+}.build()
+```
+
+## Ключевые решения
+
+- **`MemoryBackend.exposesTools()`** — backend декларирует свои tools. Не «подставить любой backend», а «backend сообщает что он умеет». Это убирает coupling «какие tools совместимы с какими backends».
+- **Builder требует только `llm + storage + memory`** как обязательные. Всё остальное — опционально с разумными default'ами (`NoopSoul`, `EmptyBackground`, `empty toolset`).
+- **`BaseAgent`** — реализация `ConversationLoop` через builder. Конструктор принимает все нужные компоненты. **Один и тот же `BaseAgent` в `:standalone`, `:agentik-cli`, `:agentik-android`** — отличается только wiring через builder.
+- **BackgroundScheduler подписан на `BackgroundEvents`** — это даёт event-driven по умолчанию. `OnEvery(n)` interval-режим — опциональный fallback (не default).
diff --git a/docs/diagrams/02-agent-composition.svg b/docs/diagrams/02-agent-composition.svg
new file mode 100644
index 0000000..c6891e0
--- /dev/null
+++ b/docs/diagrams/02-agent-composition.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/diagrams/03-multi-user-chat.md b/docs/diagrams/03-multi-user-chat.md
new file mode 100644
index 0000000..607af1d
--- /dev/null
+++ b/docs/diagrams/03-multi-user-chat.md
@@ -0,0 +1,129 @@
+# 03 — Multi-user chat с mention-detection
+
+Точка 1 из планов. Один `BaseAgent` обслуживает N пользователей. Отвечает только когда addressed (mention или admin-команда).
+
+
+
+PlantUML source (для редактирования; требует Graphviz `dot` для рендеринга):
+
+```plantuml
+@startuml multi-user-chat
+skinparam componentStyle rectangle
+skinparam participantPadding 15
+skinparam boxPadding 10
+
+title Multi-user chat с mention-detection (точка 1 из планов)
+
+' --- Участники ---
+actor "User A" as UA
+actor "User B" as UB
+actor "User C\n(админ)" as UC
+participant "Telegram /\nSlack /\nMatrix" as Channel
+participant "AgentRuntime\n(BaseAgent)" as Runtime
+participant "MentionDetector" as Detector
+participant "SoulProvider" as Soul
+participant "MemorySystem\n(MdMemory)" as Memory
+participant "LlmBackend\n(LiteLlm)" as Llm
+
+' --- Сценарий ---
+UA -> Channel : "@bot, что нового?"
+UB -> Channel : "люблю котов"
+UC -> Channel : "/bot status"
+Channel -> Runtime : событие чата
+
+' --- Внутри Runtime ---
+Runtime -> Detector : isMentioned(message, botName)
+
+note right of Detector
+ variants:
+ - SimpleMentionDetector (regex: @bot)
+ - LlmMentionDetector (mini-classifier)
+ - AdminCommandDetector (/command)
+end note
+
+Detector --> Runtime : MatchResult{isMentioned, isCommand}
+
+alt isMentioned или isCommand
+ Runtime -> Soul : read()
+ Runtime -> Memory : prefetch(query, topK)
+ Runtime -> Llm : send(system + history + memory + user)
+ Llm --> Runtime : response + tool_calls
+ Runtime -> Memory : save(decision)
+ Runtime --> Channel : ответ в нужный канал/thread
+else NOT mentioned и NOT command
+ Runtime -> Runtime : drop (если не админ)
+ note right
+ Не отвечаем, но возможно:
+ - запоминаем факт (memory-only update)
+ - summary на long conversation
+ end note
+end
+
+@enduml
+```
+
+## Ключевые модули (что нужно будет добавить)
+
+### `MentionDetector` interface
+
+```kotlin
+interface MentionDetector {
+ data class Result(
+ val isMentioned: Boolean,
+ val isAdminCommand: Boolean,
+ val isPrivateMessage: Boolean, // DM — всегда отвечаем
+ )
+
+ fun detect(message: ChatMessage, botName: String): Result
+}
+```
+
+Имплементации:
+- `SimpleMentionDetector` — regex `@bot`, `/command` (дешёво, latency ~0)
+- `LlmMentionDetector` — маленькая классификация через тот же LLM (точнее, но +1 LLM-вызов на каждое сообщение)
+- `HybridMentionDetector` — fast regex → fallback на LLM только если ambiguous
+
+### `ChatAdapter` interface
+
+```kotlin
+interface ChatAdapter {
+ val channel: String // "telegram" / "slack" / "matrix"
+ suspend fun listen(onMessage: (ChatMessage) -> Unit): Job
+ suspend fun reply(messageId: String, text: String, threadId: String? = null)
+ suspend fun isAdmin(userId: String): Boolean
+}
+```
+
+Имплементации per platform. Каждая адаптирует формат platform → `ChatMessage`.
+
+### Конфигурация builder'а
+
+```kotlin
+agentBuilder {
+ llm(...)
+ storage(...)
+ memory(...)
+ soul(...)
+ background { ... }
+ chat {
+ mentionDetector = HybridMentionDetector(regex = "@bot|@Agent", llmClassifier = false)
+ chatAdapter = TelegramChatAdapter(token = "...")
+ // На каждое сообщение:
+ // 1. mentionDetector.detect()
+ // 2. если isMentioned || isAdminCommand || isPrivate → process
+ // 3. иначе — опционально memory-only save (тихий режим)
+ }
+}
+```
+
+## Что это даёт
+
+- Один `BaseAgent` обслуживает чат целиком (один LLM, одна память — общий контекст команды)
+- `@bot` — explicit invocation, не «agent отвечает на всё подряд»
+- `/bot status` / `/bot clear-memory` — admin-команды (отдельный канал, без LLM)
+- DM — всегда отвечает (это личное обращение)
+- В групповом чате без mention — agent может **молча учить** (memory update без ответа). Полезно для «запомнил что Вася любит котов».
+
+## Текущее состояние vs целевое
+
+⏳ Ничего из этого нет. Сейчас `:standalone` — это HTTP API, к которому подключаются clients. Для multi-user chat нужен новый `:chat-adapter-telegram` (или -slack / -matrix) модуль + `MentionDetector` interface.
diff --git a/docs/diagrams/03-multi-user-chat.svg b/docs/diagrams/03-multi-user-chat.svg
new file mode 100644
index 0000000..8cce72a
--- /dev/null
+++ b/docs/diagrams/03-multi-user-chat.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/diagrams/04-sub-agents.md b/docs/diagrams/04-sub-agents.md
new file mode 100644
index 0000000..34d8d59
--- /dev/null
+++ b/docs/diagrams/04-sub-agents.md
@@ -0,0 +1,119 @@
+# 04 — Sub-agents + A2A между агентами
+
+Точки 2 и 3 из планов. Orchestrator-агент spawn'ит sub-агентов с изолированным контекстом. Независимые агенты общаются через A2A.
+
+
+
+PlantUML source (для редактирования; требует Graphviz `dot` для рендеринга):
+
+```plantuml
+@startuml sub-agents-and-a2a
+skinparam componentStyle rectangle
+
+title Sub-agents + A2A между агентами (точка 2+3 из планов)
+
+' --- Orchestrator ---
+rectangle "OrchestratorAgent\n(BaseAgent + tools)" as Orch {
+ rectangle "ConversationLoop\n(main user)" as MainConv
+}
+
+' --- Sub-agent spawn ---
+rectangle "subAgent(\n task: String,\n config: AgentConfig\n): Flow" as SpawnAPI
+note right of SpawnAPI
+ Spawn API — НЕ отдельный модуль,
+ а convenience поверх BaseAgent:
+ val sub = agent.spawnChild(config) {
+ systemPrompt = "..."
+ tools = [ReadTool, WriteTool]
+ memory = EmptyMemory // изолированно
+ }
+ sub.events.collect { ... }
+end note
+
+' --- Дочерний агент (изолированный контекст) ---
+rectangle "SubAgent\n(изолированный scope)" as Sub {
+ rectangle "ConversationLoop\n(child)" as SubConv
+ rectangle "backgroundScope\n(lifecycle scoped)" as SubBg
+}
+
+' --- A2A между независимыми агентами ---
+rectangle "Agent A\n(BaseAgent)" as AgentA
+rectangle "Agent B\n(BaseAgent)" as AgentB
+rectangle "A2A Server\n(:a2a-server)" as A2ASrv
+
+AgentA -> A2ASrv : POST /\n(application/json)
+A2ASrv -> AgentB : dispatch(message)
+AgentB --> A2ASrv : response
+A2ASrv --> AgentA : SSE / JSON-RPC
+
+' --- Стрелки ---
+Orch -> SpawnAPI : calls
+SpawnAPI -> Sub : creates with custom config
+Sub -> SubBg : has its own
+Orch -> Orch : main flow continues
+Sub --> Orch : Flow emits\n(Started / ToolCalled / ToolResult /\nAssistantMessage / Done / Failed)
+
+Orch -> A2ASrv : can also delegate to remote agent
+
+@enduml
+```
+
+## Sub-agents API
+
+```kotlin
+sealed interface SubAgentEvent {
+ data class Started(val taskId: String) : SubAgentEvent
+ data class AssistantMessage(val text: String) : SubAgentEvent
+ data class ToolCalled(val toolName: String, val args: JsonObject) : SubAgentEvent
+ data class ToolResult(val toolName: String, val result: String) : SubAgentEvent
+ data class Done(val taskId: String, val finalResult: String) : SubAgentEvent
+ data class Failed(val taskId: String, val error: String) : SubAgentEvent
+}
+
+interface BaseAgent {
+ // ... existing methods ...
+
+ /**
+ * Spawn дочерний агент с изолированным контекстом (memory, system prompt,
+ * tools). Возвращает Flow событий жизненного цикла + результата.
+ * Cancellation родителя НЕ отменяет sub-agent — sub-agent живёт до Done/Failed.
+ */
+ fun spawnChild(config: SubAgentConfig): Flow
+}
+
+data class SubAgentConfig(
+ val systemPrompt: String,
+ val tools: List = emptyList(),
+ val memory: MemorySystem = EmptyMemory(),
+ val model: LiteLlm? = null, // если null — делит LLM родителя
+ val maxTurns: Int = 10,
+ val timeoutMs: Long = 60_000,
+)
+```
+
+## Зачем изолированный scope
+
+Sub-agent получает **свою копию контекста**, не делит memory с родителем. Это критично:
+- `research_subagent` — должен исследовать тему, не отвечать на основные сообщения пользователя
+- `summarize_subagent` — суммаризировать документ, не трогать основной диалог
+- `code_review_subagent` — ревьюить PR, не видеть разговор
+
+Если нужно расшарить контекст — это explicit через `sharedMemory: SharedMemoryHandle` параметр, не default.
+
+## A2A между независимыми агентами
+
+Уже есть `:a2a-server` модуль (см. `standalone/build.gradle.kts` — `implementation(libs.a2a.server)`). Использовался для AG-UI/A2A протокола в `:standalone`. Можно переиспользовать для межагентного общения.
+
+Сценарий: orchestrator-agent не может сам решить задачу → делегирует remote-агенту через A2A → получает response → продолжает. Это уже работающая инфраструктура.
+
+## Текущее состояние vs целевое
+
+✅ Уже есть:
+- `:a2a-server` подключён
+- `BaseAgent.spawnChild` — **не существует**, но `ConversationLoop` уже умеет создавать изолированный scope через свой `agentScope` — нужна только обёртка
+
+⏳ Не сделано:
+- `SubAgentConfig` + `Flow` API
+- `EmptyMemory` (null-object для изолированного scope)
+- Lifecycle management (parent dies → child должен complete or be cancelled?)
+- Сериализация sub-agent state для отладки (event log)
diff --git a/docs/diagrams/04-sub-agents.svg b/docs/diagrams/04-sub-agents.svg
new file mode 100644
index 0000000..f1ef972
--- /dev/null
+++ b/docs/diagrams/04-sub-agents.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/diagrams/05-android-stack.md b/docs/diagrams/05-android-stack.md
new file mode 100644
index 0000000..fb3c8d8
--- /dev/null
+++ b/docs/diagrams/05-android-stack.md
@@ -0,0 +1,171 @@
+# 05 — Android Agent Stack
+
+Что меняется vs `:standalone`. Цель: `BaseAgent` тот же самый, но platform-impl разные (Storage, LLM, Vector Memory, MCP).
+
+
+
+PlantUML source (для редактирования; требует Graphviz `dot` для рендеринга):
+
+```plantuml
+@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)
+
+Если не нужны все фичи сразу — минимум:
+
+```kotlin
+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 не убил его при выключении экрана. Это добавляет сложности:
+
+```kotlin
+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)
diff --git a/docs/diagrams/05-android-stack.svg b/docs/diagrams/05-android-stack.svg
new file mode 100644
index 0000000..93e224b
--- /dev/null
+++ b/docs/diagrams/05-android-stack.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/diagrams/README.md b/docs/diagrams/README.md
new file mode 100644
index 0000000..989567d
--- /dev/null
+++ b/docs/diagrams/README.md
@@ -0,0 +1,64 @@
+# agentik — диаграммы архитектуры
+
+PlantUML-схемы для обсуждения будущей структуры (Android agent, multi-user chat, sub-agents, A2A). Это **целевое состояние**, не текущее.
+
+## Файлы
+
+Каждый `.md` содержит:
+- Краткое описание (что показывает)
+- **Пред-рендеренный SVG** (``) — гарантированно показывается **везде**
+- PlantUML source в ` ```plantuml ` блоке — для редактирования (требует Graphviz `dot` для рендеринга)
+- Дополнительный markdown-текст (что нужно сделать, текущее vs целевое)
+
+| Файл | Что показывает |
+|---|---|
+| [01-module-layers.md](./01-module-layers.md) | Целевая модульная структура (приложения → runtime → домен → абстракции → платформенные impl). Что в каком слое и кто от кого зависит. |
+| [02-agent-composition.md](./02-agent-composition.md) | Как `AgentBuilder` собирает `BaseAgent` из компонентов. Memory backend сам объявляет свои tools. BackgroundScheduler подписан на события (НЕ interval-poll). |
+| [03-multi-user-chat.md](./03-multi-user-chat.md) | Сценарий: чат с N пользователями, mention-detection, админ-команды, agent отвечает только когда addressed. |
+| [04-sub-agents.md](./04-sub-agents.md) | Orchestrator spawn'ит sub-agent с изолированным контекстом, получает `Flow`. A2A между независимыми агентами через `:a2a-server`. |
+| [05-android-stack.md](./05-android-stack.md) | Что меняется на Android: on-device LLM (NNAPI), Room/sqlite, ONNX-based vector memory, foreground-service для MCP subprocess. |
+
+## Почему SVG + PlantUML source
+
+PlantUML требует Java + (для component/class/deployment диаграмм) Graphviz `dot`. Если `dot` не установлен — рендерер падает с ошибкой "Executable dot does not exist".
+
+Решение: **пре-рендерим в SVG один раз** и вставляем как `
`. Диаграмма гарантированно показывается в любом markdown-viewer (GitHub, IntelliJ, VSCode, GitLab) без зависимостей. PlantUML source в code block остаётся для редактирования.
+
+## Как редактировать диаграмму
+
+1. Меняешь PlantUML-source в ` ```plantuml ` блоке `.md` файла.
+2. Ре-рендеришь SVG:
+ ```bash
+ mkdir -p /tmp/plantuml-work && chmod 777 /tmp/plantuml-work
+ cp docs/diagrams/*.md /tmp/plantuml-work/
+ docker run --rm -v /tmp/plantuml-work:/work plantuml/plantuml -tsvg /work/*.md
+ cp /tmp/plantuml-work/*.svg docs/diagrams/
+ ```
+3. Проверяешь что SVG обновился:
+ ```bash
+ ls -la docs/diagrams/*.svg
+ ```
+4. Коммитишь оба файла: `.md` (source) и `.svg` (rendered).
+
+Требует Docker (или локального PlantUML+Graphviz). `apt install graphviz` для Arch/Manjaro.
+
+## Контекст
+
+Текущий код движется в эту сторону:
+- `:llm-tools` extracted ✅
+- `:mcp-bridge` extracted ✅
+- `BackgroundScheduler` стал event-driven ✅
+- `ConversationLoop` стал отдельным компонентом ✅
+
+Не сделано (см. детали в каждом .md):
+- `:agent-core` (выделить `BaseAgent` + builder)
+- `:background-events` (выделить events + scheduler)
+- `:storage-sqlite-android`, `:memory-vector-android`, `:litert-android`
+- `:agentik-android` (само приложение)
+- `MentionDetector` interface + adapters для multi-user chat
+- `BaseAgent.spawnChild` + `Flow`
+
+Подробнее:
+- `STANDALONE-REVIEW.md` — что плохо в текущем коде
+- `MEMORY-DESIGN.md` — детали memory архитектуры
+- `STANDALONE.md` — текущий standalone