docs(diagrams): agent architecture overview with pre-rendered SVG
ci / JVM build + tests (push) Failing after 1m57s
ci / JVM build + tests (push) Failing after 1m57s
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
This commit is contained in:
@@ -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<NamedTool> (авто-сборка из backends)" as Tools
|
||||
rectangle "background: BackgroundConfig (default EmptyBg)" as Bg
|
||||
rectangle "toolset: List<ToolsetContribution> (default empty)" as Ts
|
||||
}
|
||||
|
||||
' --- Backends with their tool side-effects ---
|
||||
rectangle "MemoryMd" as MdMem {
|
||||
interface "MemorySystem" as MemSys
|
||||
interface "List<NamedTool>" as MdTools
|
||||
note right
|
||||
MemoryMd.exposesTools() →
|
||||
memory_save / memory_read /
|
||||
memory_list / memory_delete
|
||||
end note
|
||||
}
|
||||
|
||||
rectangle "McpRegistry" as McpReg {
|
||||
interface "List<NamedTool>" as McpTools
|
||||
note right
|
||||
McpRegistry.namedTools →
|
||||
server__tool1, server__tool2,
|
||||
...
|
||||
end note
|
||||
}
|
||||
|
||||
rectangle "BackgroundEvents" as Events {
|
||||
interface "MutableSharedFlow<CompactionEvent|ToolCallEvent|LifecycleEvent>" 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).
|
||||
Reference in New Issue
Block a user