Ухвалені рішення
Рішення, які ми зафіксували (див. Відкриті питання — що ні).
| Тема | Рішення |
|---|---|
| Позиція | Greenfield — не портуємо 1.x; стара реалізація лише як референс |
| Хмарна стратегія | Hetzner-first; AWS за тригером. Запуск 100% на Hetzner; managed-сервіси AWS (S3/SES/RDS/KMS) впроваджуємо по одному лише на реальний сигнал масштабу/надійності. Компют ніколи не покидає Hetzner. Див. Хмарну стратегію |
| Топологія кластера | Три нодпули: виділений tainted control-plane (1 dev / 3 prod-HA) · core (завжди онлайн, HPA) · workers (ефемерні Job-и, scale-to-zero). Див. Кластер і ноди |
| Автоскейлинг | HPA (репліки api/app/admin) + VPA (right-size requests, in-place на k3s ≥1.33) + cluster-autoscaler (ноди на пул; workers 0→N). Без KEDA для MVP |
| Тенант | = team (суб'єкт білингу, володіє агентами/ключами; соло-юзер = команда з одного) |
| Топологія застосунків | 4 застосунки: api · app · admin · worker. Немає runner, немає окремого runtime-застосунку — ефемерний агент = образ api; worker = руки на вимогу |
| Шаровість | 8 груп, залежності лише вниз (суворий інваріант) |
| Ім'я L1-групи | platform → перейменовано на system (= usage · setting · notification · llm · file) |
| Auth | Drop Cognito → власна JWT (issuer = Core) в user/auth; та сама схема мінтить короткоживучі runtime session tokens для worker (один механізм) |
| k8s-примітив | Native k8s Jobs, ttlSecondsAfterFinished для scale-to-zero. Без KEDA/Knative для MVP |
| Виконання браузера | In-worker — образ worker містить Playwright + Chromium і запускає браузер in-pod на задачу. Без окремого пулу Browserless (простіше: один застосунок, повна ізоляція; trade-off = важчий образ + холодний старт Chrome на задачу) |
| Черга | BullMQ на Redis |
| Сховище даних | DynamoDB → Postgres |
| LLM | Bedrock → Claude API (system/llm); ретайр openai |
Resend на MVP → AWS SES на обсягах (змінювано за notification/email) | |
| Знання | LightRAG бібліотека, окремим Python-сервісом; agent/knowledge = тонкий gateway |
| Файли | system/file (managed-файли поверх infra/storage); влив runtime artifacts |
| Позиція billing | Top sink; setting читає team.planId (інверсія), billing ніхто не імпортує |
| publicApi | Розпущено → rate-limit у core, доставка вебхуків у notification, ключі в user/apiKey |
| orchestrator | Мозок — живе в agent, не в runtime |
| mcp | Лишається в setup (транспорт-експозиція, не здатність system) |
| Tool-канал worker'а | = MCP. worker — це ефемерний MCP-сервер; api — це MCP host, який реєструє його на ready, від'єднує на release. Транспорт = MCP поверх ініційованого worker'ом (реверсного) WebSocket (варіант A — зберігає «no pod IP / no inbound to the worker»; trade-off = невеликий кастомний MCP-транспорт замість стокового Streamable-HTTP). MCP sampling вимкнено; одна модель тулів для brain-MCP · worker-MCP · connector-MCP. Див. Use → протокол · Канал інструментів (контракт дроту) |
| Коротка пам'ять | Робочий контекст регідратується з Postgres на кожному кроці (мозок ефемерний) + running summary, що зберігається на чаті + вікно із захищеними head/tail; компакція = дешевий pre-prune tool-result'ів → memory-flush у agent/memory → підсумовування середини дешевою допоміжною моделлю. Snapshot system-промпта тримає prefix cache теплим. Коротка пам'ять ≠ довга пам'ять. Див. Коротка пам'ять |
| Тип агента | У агента є тип (standard / concierge), і одна декларація каже, що цьому типу дозволено; її читають і кожен шлях запису, і інтерфейс, а не по копії кожен. Тип призначає лише сервер — ніколи не з DTO і не з маніфеста пакета. Див. Склад |
| Системний промпт | Шаруватий: платформена база + вказівки щодо інструментів + душа агента дослівно. Душа — один шар, а не весь промпт; усе, що залежить від ходу, збирається в іншому місці. Див. Склад |
| Значення секретів | Ніколи не покидають систему. Жоден ендпоінт їх не віддає, а пакет несе лише імена ключів. Запис зливається зі своїм scope, а не замінює його. Див. Секрети |
| Автозапуск | Один глобальний обхідник раз на 60 с на всіх агентів — ніколи не таймер на агента, — тому дозрілий тік спрацьовує рівно один раз на весь парк. Тік — це повноцінний хід, тому в інтервалу є підлога у 10 хвилин, що перевіряється на шляху запису: доки немає обліку споживання, ця підлога і є єдиним обмеженням витрати. Зайнятий агент пропускається, а не переривається; тік із NO_REPLY не пише нічого. Див. Автозапуск |
| Скасування ходу | Хід скасовує закриття сокета (закрита вкладка, перезавантаження, кнопка «стоп»); SPA-навігація — навмисно ні. Зупинений хід зберігає доставлене з позначкою «зупинено», хід з помилкою не зберігає нічого. Див. Модель рантайму |
| Історія чату | Лише курсорна пагінація — непрозорий курсор, limit ≤ 200; жоден виклик не віддає тред цілком. Один тред на (агента, канал, людину): «почати заново» проводить риску всередині нього, а не відкриває другий, і нотатки агента цю риску переживають. Консьєрж — звичайний рядок Agent, тому його листування зберігається як будь-яке інше. Див. Сховище |
| Розмітка в чаті | Відповідь моделі рендериться з білого списку типів вузлів, а не «HTML плюс санітайзер»: жодного v-html, жодних картинок і сирого HTML, посилання — лише http/https/mailto та оголошені внутрішні шляхи |
| Власний автозапуск агента | Вміст — завжди; частота і ввімкненість — лише в ході, який відкрила людина, ніколи у власному тіку: небезпечною була петля, а не правка. Прискорення обмежене (≤ 60 хв, ≤ 3 за 24 год), ніколи не йде нижче підлоги і гасне арифметикою, а не тим, що хтось має спрацювати. Разовий рядок викреслюється після виконання; спорожнілий список повертає частоту і лишає агента ввімкненим. Див. Автозапуск |
| Руки | Чи може агент підняти воркер — це колонка в агента, за замовчуванням none, і реліз її ніколи не розширює. Які інструменти дістануться цьому воркеру — це грант, за замовчуванням порожній: воркер без інструментів, а не воркер з усіма. Нічого не провіжиниться, доки модель справді не викличе інструмент воркера; одне доручення просить один раз; а інструменти приїжджають у наступний хід, а не в той, який їх підняв. Див. Руки |
| Архівація проти видалення | Консьєрж може заархівувати агента розмовою і повернути його з архіву; видалити не може ніколи. Межа — зворотність: архівацію розвертає один рух, а видалення забирає листування, нотатки, навички і секрети агента. Видалення — за людиною, у кабінеті, за підтвердженням, яке називає агента на ім'я. Див. Склад |
| Що хід пам'ятає | Один композитор, один виклик за хід в обох мозків, що повертає і шари промпта, і префікс повідомлень, і витрачене — бо торгувати одним шаром проти іншого може лише той, хто бачить суму. Одна стеля на все; закріплений порядок витіснення (персона → останній обмін → зведення → нотатки → витяги → глибше вікно), у якому перші два не ріжуться ніколи. Рахується у знаках, бо блок їде в кожному ході. Див. Пам'ять |
| Запис у пам'ять | У нотатки є стеля, і довша відхиляється, а не підрізається. Усе, що пише нотатку, зобов'язане її переіндексувати — нотатка, яку не можна згадати, найгірший вид поломки, бо нічого не падає, — а видалення нотатки прибирає її вектор, щоб людина, яка видалила нотатку, не лишилася з агентом, який її досі пам'ятає. Пригадування за змістом побудовано і не запускалося жодного разу: ключа ембеддингів не задає жодне середовище, тому нотатки йдуть за датою. Див. Пам'ять |
| Засновник | Найраніший обліковий запис стає адміністратором платформи один раз, і це фіксує рядок «інсталяцію засновано», а не правило «підвищувати найранішого, коли адміністраторів немає» — друге тихо віддало б роль того дня, коли відкличуть останнього адміністратора. Усі видачі після цього — команда в оболонці; ні ендпоінта, ні кнопки немає. Див. Роль адміністратора |
| Запис промптів | Вимкнено за замовчуванням, по агенту, вмикає власник агента — у промпті лежить чиєсь листування і написані про людину нотатки, тому погоджуватися має той, чий це текст. Зберігається 7 днів. Читається лише в панелі. Історія роботи агента — зворотний розмін: увімкнена за замовчуванням, дешева, зберігається 30 днів, і промпта в ній немає ніколи. Див. Що агент робив |
| Контролери і гейтвеї | Контролер залежить від сервісу; йому не можна імпортувати ні *Gateway, ні щось із data/. Залишене на ревʼю, це розповзлося по шістьох контролерах при зеленому гейті; тепер перевірка меж таке відхиляє. Порядок груп береться з конфігурації кожного застосунку, тому один скрипт обслуговує всі. Див. Як ми це будуємо |
| Прийом пакета | Обмежений за оголошеним і виміряним розміром (25 МБ завантаження · 20 000 записів · 128 МБ у розпакованому вигляді), лише STORE/DEFLATE, у кожної відмови код, а не фраза, і весь імпорт атомарний. Див. Імпорт та експорт |
| Канали | Окремого застосунку gateway немає — канали живуть усередині api, за транспортно-незалежним швом. agent/channel/channel тримає таблицю прив'язок, вбудовуваний токен і міст до оркестратора і не знає жодного протоколу; провід лежить у підслайсі на транспорт (agent/channel/bridle). Api — це рантайм агента, а не хаб: він сам дзвонить НАЗОВНІ у /ws/agent Bridle, тому назовні не відкривається нічого. Зовнішня розмова — та сама розмова, просто з іншим channel: та сама таблиця, те саме вікно, та сама компакція. Відвідувач не суб'єкт: хід виконується від власника агента, у його команді, через ту саму перевірку членства, що й в учасника, а ідентифікатор відвідувача — лише channelUserId. У такого ходу немає рук, і він нічого не пише в довгу пам'ять. Токен для браузера випускає лише учасник команди, він спливає (15 хв за замовчуванням, стеля 24 год) і несе id агента в sub — хаб не перевіряє, для якого агента випущено токен, тому перевіряємо ми. Див. Склад і AGNT2-222 |
| Анонім → упізнаний | ЗЛИВАТИ, за квитком, який пред'явив сам браузер, зі слідом і з відміною. Рішення власника від 28 серпня 2026, ухвалене з названим і свідомо прийнятим ризиком: людина, яка писала анонімно, а потім прийшла упізнаною, отримує свої минулі розмови без жодних підтверджень. Підстава — тільки наш підпис: злиття відбувається лише там, де браузер пред'являє в ОДНОМУ обміні і новий квиток, і той, яким він був досі, і обидва вийшли з JWT, підписаного цим api. Ніколи за поштою, введеною в чаті (чужу адресу може написати будь-хто), і ніколи за іменем чи телефоном: упізнаною людину робить лише externalId, який надіслав її власний сайт зі своїм ключем, сервер серверу (AGNT2-234). Чотири відмови, і всі мовчазні для відвідувача: та сама людина, різні команди, ніхто не упізнаний, і минуле, яке сайт уже називав на ім'я. Прийнятий ризик у тому, що анонімний ідентифікатор живе у браузері — спільний комп'ютер або гостьовий режим приклеять чужу розмову, а це показ чужого листування, — тому злиття викуплене двома умовами, від яких рішення невіддільне: лишається СЛІД (LeadMerge: хто, до кого, які розмови і коли), видимий словами на екрані лідів; і його може СКАСУВАТИ учасник команди, повернувши рівно ті розмови, які переїхали, і нічого зі сказаного після. Скасування позначає запис, а не видаляє його: «було і скасували» і «цього не було» — різні відповіді. Ручки, що зливає двох лідів за id, немає і бути не повинно: підпис через ручку не пред'явиш. Див. AGNT2-236 | | Власні навички агента | Агент може НАПИСАТИ навичку; увімкнути її може лише людина. Навичка — це інструкція, тож помилкова змінює поведінку агента з усіма, з ким він говорить, і вказати на фразу, яка це спричинила, неможливо — тому доказ, який вирішив питання про нотатки пам'яті («хай пише вільно, черга, яку ніхто не розбирає, все одно нічого не робить»), тут дає протилежну відповідь. Це не черга: навичка потрапляє до спільного списку команди з позначкою, який агент її написав, і не підключена до жодного агента, включно з автором — той самий стан, у якому починає навичка, написана ЛЮДИНОЮ. Вона ні на що не впливає і не їде в пакет, доки її не підключать, а на екрані самого агента видно, що він написав, — щоб рішення стояло перед тим, хто його ухвалює. Пишеться всередині ходу, а не окремим проходом після: прохід коштує виклику моделі на кожну розмову заради висновку «нічого», а навичку, на відміну від довгої нотатки, зазвичай просять уголос — і людина поруч, щоб почути, як її названо. У власному тіку відмова, бо там нікому це почути; відвідувачу сайту інструмент не видається взагалі — це забезпечує здатність, під якою він зареєстрований, а не перевірка всередині нього. Правити й видаляти навичку агент не може. Див. AGNT2-270 |
Принципи розміщення
infra= адаптери ·setup= експозиція/framework (без здатності) ·system= сервіси-здатності.systemvsruntime= стан/здатність vs механізм/дія.- членство в
system= L1-лист, що використовується багатьма шарами (тримати суворо). - ламати ребра вгору через інверсію (порт, подія або читання через Prisma), не ламаючи шар.