Архітектура
Огляд системи
AgentCore — це мультиканальна платформа AI-асистента, що зʼєднує messaging-канали (WhatsApp Cloud API, Telegram) з RAG-базою знань у межах відділу та HITL-воркфлоу схвалення.
┌─────────────┐ ┌─────────────┐
│ WhatsApp │ │ Telegram │
│ Cloud API │ │ (Grammy) │
└──────┬──────┘ └──────┬──────┘
│ │
▼ ▼
┌──────────────────────────────────┐
│ Fastify Server │
│ routes, auth, RBAC, dept scope │
└──────────────┬───────────────────┘
│
┌──────────┼──────────┬──────────────┐
▼ ▼ ▼ ▼
┌────────┐ ┌───────┐ ┌────────────┐ ┌────────────┐
│ Agent │ │ HITL │ │ Memory │ │ WebSocket │
│ Runner │ │Approve│ │ Extraction │ │ Events │
└───┬────┘ └───┬───┘ └─────┬──────┘ └─────┬──────┘
│ │ │ │
▼ ▼ ▼ ▼
┌──────────────────────────────────────────────────┐
│ PostgreSQL 16 + pgvector │
│ Redis 7 (BullMQ queues + rate-limit store) │
└──────────────────────────────────────────────────┘
Конвеєр повідомлень
ADR-001 робить agent-tasks основною межею виконання для вхідних повідомлень. Канальні воркери — це транспортні адаптери: вони нормалізують вхідні повідомлення, зберігають записи user/conversation/message, створюють AgentTask і ставлять його в чергу. Вони більше не володіють RAG/HITL-логікою.
- Канал отримує повідомлення через WhatsApp Cloud API-webhook або Telegram polling/webhook.
- Inbound-черга каналу (
wa-inboundабоtg-inbound) нормалізує транспортний payload. - Inbound-воркер знаходить або створює користувача й розмову, зберігає повідомлення користувача, створює
AgentTaskі ставить у чергуagent-tasks. - Agent runner worker обробляє задачу:
inject_profile: завантажує system prompt простору імен і контекст employee profile.rag_search: запускаєOpenAiRagPipelineв api-режимі або fallback-адаптер, обраний простором імен у test/adapter-режимі.generate: форматує відповідь для каналу.confidence_check: керує injection-guard, тригерами ескалації персони, класифікацією намірів, confidence fallback та обходом матриці довіри.
- Результат маршрутизації зберігається як рядки
AgentToolCallі один із:- автовідправка через
wa-outboundабоtg-outbound; - створення pending
Approvalі перехід розмови вawaiting_approval; - відправка persona-escalation-повідомлення і перехід розмови в
escalated.
- автовідправка через
- Після схвалення approved/edited відповідь ставиться у outbound-чергу каналу.
- Memory extraction запускається після налаштованого інтервалу повідомлень.
- WebSocket-події бродкастять lifecycle задачі в реальному часі (
agent-task.created,.started,.tool-call,.completed,.failed) із department-фільтрацією при кожній доставці.
Архітектура компонентів
Fastify-застосунок (src/app.ts)
App-фабрика реєструє компоненти в такому порядку:
- OpenAPI: Swagger і Swagger UI (
/docs) з/api/v1як префіксом API-сервера. - Плагіни безпеки: Helmet, CORS по точних origin, глобальний rate limit, JWT-автентифікація та
departmentScope. - Middleware: audit-logger, idempotency і структурований error handler.
- Фонові воркери: ingestion, memory extraction та agent-runner черги.
- Маршрути: health, auth, knowledge, approvals, traces, namespaces, me, conversations, departments, users, roles, audit, RAG draft, employee profiles, intents, agent tasks, plugins, document templates і notifications — під
/api/v1. - Канали: WhatsApp Cloud API плагін і Telegram плагін — під
/api/v1. - Моніторинг: Bull Board admin UI (
/admin/queues) і WebSocket event-бриджі (/ws/agent-tasks,/ws/notifications).
Плагінна система
Fastify-плагіни надають:
authenticatedecorator — JWT verification hook (тільки Bearer-заголовок; WebSocket використовує first-message auth handshake);departmentScopedecorator — локальний для запитуDepartmentScopeзforDepartment(request.user);knowledgeIngestionQueue— BullMQ-черга обробки документів;memoryExtractionQueue— BullMQ-черга екстракції профілів;agentTasksQueue— BullMQ-черга обробки agent tasks;channelService— абстракція конфігурації каналів, наразі на env-змінних;broadcastAgentTaskEvent— WebSocket-бродкаст-хелпер, що повторно перевіряє namespace-department-доступ перед кожною відправкою;pluginRegistry— реєстр namespace integration plugins з вбудованими OpenDataBot і webhook-плагінами;- notification-хелпери — персистентні per-user сповіщення та доставка через WebSocket.
Архітектура черг (BullMQ + Redis)
| Черга | Призначення | Concurrency |
|---|---|---|
agent-tasks | Обробка agent tasks через адаптери | конфігурується |
knowledge-ingest | Парсинг документів, чанкінг, ембединги | 1 |
memory-extraction | Екстракція employee profile з чатів | 1 |
wa-inbound | Обробка повідомлень WhatsApp | конфігурується |
wa-outbound | Відправка повідомлень WhatsApp | конфігурується |
tg-inbound | Обробка повідомлень Telegram | конфігурується |
tg-outbound | Відправка повідомлень Telegram | конфігурується |
Черга agent-tasks використовує 3 retry з exponential backoff (base delay 2s). Таймаут для кожного адаптера: api — 30s, claude_local/codex_local — 300s, ollama — 120s. Stalled-job detection автоматично ретраїть задачі, якщо воркер помирає.
Усі черги використовують exponential-backoff retry. Воркери gracefully шатдаунять на SIGTERM/SIGINT.
Agent Runner та adapter layer
Agent runner — це канонічний pipeline обробки повідомлень. Він зберігає кожну задачу в AgentTask, пише прогрес по кроках у AgentToolCall і генерує чернетки через pluggable adapter-інтерфейс (AgentAdapter). Кожен простір імен вибирає свій адаптер через поле config.agentRunner.activeAdapter.
Доступні адаптери:
| Адаптер | Бекенд | Таймаут |
|---|---|---|
api | OpenAI SDK (chat.completions.create) | 30s |
claude_local | Claude CLI (claude --print) | 300s |
codex_local | Codex CLI (codex exec --json) | 300s |
ollama | Ollama HTTP API (OpenAI-сумісний) | 120s |
Модель даних: кожна задача створює AgentTask з вкладеними AgentToolCall, що трекають inject_profile, rag_search, generate, confidence_check і всі adapter-level виклики з runner. Токени, вартість і тривалість трекаються по задачі.
Див. Конфігурація для per-namespace налаштування адаптера.
Ізоляція відділу
ADR-002 централізує department-доступ у src/lib/department-scope.ts.
forDepartment(user)повертаєDepartmentScope.scope.directWhere()застосовується до Prisma-моделей з прямимdepartmentId.scope.nestedWhere('namespace')охоплює моделі на кшталтAgentTaskчерез повʼязані простори імен.scope.departmentIdвикористовується у raw SQL-фільтрах RAG.- Admin-користувачі отримують крос-департаментний доступ; усі інші ролі обмежені
departmentIdз JWT.
Fastify-плагін у src/plugins/department-scope.ts декорує автентифіковані запити полем request.departmentScope. REST-маршрути, RAG-пошук, agent runner та WebSocket-бродкасти використовують той самий scope-примітив. Регресійний набір у tests/department-isolation.test.ts перевіряє list, detail, mutation, RAG, analytics та WebSocket isolation.
Потік даних: ingestion знань
Upload → Parse (PDF/DOCX/TXT/Image) → PII Scrub → Chunk → Embed → Synthetic Q&A → Store
Деталі — у Knowledge & RAG.
Потік даних: RAG-запит
User Query → Injection Guard → Intent Classify → Embed Query
→ Vector Search (chunks + questions) + Keyword Search
→ Hybrid Score + Rank → Top-K Assembly
→ LLM Generation (with system prompt + history + profile)
→ PII Restore → Confidence Check → Bypass or HITL
Деталі — у Knowledge & RAG.
Ключові дизайн-рішення
Namespace isolation
Кожен відділ володіє простором імен з власним system prompt, persona-конфігом, правилами ескалації та матрицями довіри. Неглобальні користувачі бачать тільки namespace-scoped дані у межах свого ефективного відділу.
Дворівневий захист PII
- Ingestion time: незворотний scrub перед збереженням чанків та embeddings.
- Conversation time: зворотне AES-256-GCM шифрування з
PII_ENCRYPTION_KEY; LLM бачить плейсхолдери, у відповіді користувача вихідні значення відновлюються.
Матриця довіри
Per-intent tracking автономності. Після достатньої кількості успішних схвалень для наміру система автовідправляє відповіді (з налаштовуваним семплінгом для постійного контролю).
Гібридний retrieval
Поєднує vector і keyword search для recall. За замовчуванням 65% vector і 35% keyword; vector-бюджет розділений між content chunk embeddings та synthetic question embeddings.