Files

2.6 KiB

Architecture

Multi-channel AI messaging platform. Telegram is the first adapter, not the definition of the system.

Layering

        CHANNEL LAYER
   +-------+-------+-------+
   |Telegram|Shopee |Lazada|
   |adapter |adapter|adapter|
   +-------+-------+-------+
              |
        APPLICATION CORE          (channel-agnostic message contract)
              |
     +--------+--------+
     |        |        |
  AI/Agent  n8n Tools  (integrations)
     |        |
  Memory  PostgreSQL
     |        |
  pgvector   (Phase 3)
     |
  LLM APIs (LiteLLM → OpenAI/OpenRouter)

Responsibilities

Layer Owns Must NOT own
Channel adapter (src/channels/*) Native event parsing, platform formatting/IDs, buttons, webhook setup Business rules, prompt construction, DB schema
Application core (src/core) Normalized message contract, capabilities flags Telegram-only assumptions
AI layer (src/ai) Prompt assembly, agent orchestration, memory/retrieval interfaces Platform transport
DB (src/db) Users, conversations, messages, migration Transient in-process state
n8n (src/integrations/n8n) Automation/tool calls with schema validation Core conversational state

Data flow (one message)

  1. Telegram POST → Hono webhook POST /webhook/<secret>.
  2. grammY parses the update → normalizeIncoming()IncomingMessage.
  3. db.saveExchange() upserts user, opens/reuses conversation, stores the user message.
  4. Agent.respond() builds system+business prompt (plus user-memory block when a summary exists), fetches recent history, calls LLM.
  5. Reply persisted via saveExchange() (assistant role), returned to grammY → Telegram.
  6. Agent.updateMemoryAsync() (fire-and-forget, never blocks the reply) writes lang + last_queries (FIFO-5) rule-based, and triggers the MemoSummarizer (cheap chatSmall call) when new facts appear → updated summary back into user_memory.

Key contracts

  • IncomingMessage / OutgoingMessage (src/core/messages.ts) — the single normalized shape every adapter translates to/from.
  • ChannelCapabilities — flags (supportsButtons, etc.) so the core never assumes a feature exists on every channel.
  • Provider/retriever/memory interfaces — defined now, no-op until justified (Phases 2/3).

Networking

  • The bot container joins the existing mem0_net (external) to reach mem0-postgres and litellm by container name.
  • Production webhook must be HTTPS: bot.digikedai.com via the DSM CF-tunnel → Traefik → this container (routing added in a later step; see docs/OPERATIONS.md).
  • PostgreSQL is never exposed publicly.