Files
agentik/docs/diagrams/03-multi-user-chat.md
T
subochev 25771a0c33
ci / JVM build + tests (push) Failing after 1m57s
docs(diagrams): agent architecture overview with pre-rendered SVG
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
2026-09-18 20:02:41 +03:00

4.8 KiB
Raw Permalink Blame History

03 — Multi-user chat с mention-detection

Точка 1 из планов. Один BaseAgent обслуживает N пользователей. Отвечает только когда addressed (mention или admin-команда).

Multi-user chat

PlantUML source (для редактирования; требует Graphviz dot для рендеринга):

@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

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

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'а

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.