Начну с короткого рассказа, как я докатился до жизни такой ) Меня зовут Егор, мне 28. У меня нет диплома программиста, нет опыта работы в IT и нет ни одного коммерческого проекта в резюме. Зато я всю жизнь очень любил железо — буквально с детства, будучи ещё в детском саду, я чинил себе джойстики на Sega, а потом на PS1. В школьные годы открыл для себя сначала Ucoz, потом Wix, Tilda, WordPress, и уже к институту освоил React. Но так сложилось, что это для меня всегда было просто хобби — как и собирать себе датчики для дома: датчики влажности, открытия дверей и т.д. ))
Возможно, я бы мог стать программистом и зарабатывать приличные деньги, но учился в школе с военным уклоном, а после школы стал предпринимателем — занимались производством металлоконструкций и мебели ) После череды ссор с партнёром стал аккаунт-менеджером в Достависте, и отработал там славные 4 года (и по вечерам програмировал мечтал об магазине аля САМОКАТ ), что, собственно, и позволило мне отправиться в Грузию в 2021 году перезимовать и познакомиться с будущей женой.
Грузия, которая не случилась
Жили в Грузии, всё было кайф. Купил там квартиру не в центре Батуми, буквально на кредитку(было так дешево ), в начале 2022 года — до начала событий . Август 2025. Мы с женой (беременной, она грузинка) пошли в Турцию на визаран — так как ПМЖ мне не давали, а давали справку о том, что я «угроза нац. безопасности». На границе меня разворачивают — аргументируя тем, что я слишком долго туристом у них живу.
Месяц живу в Турции, жена быстро всё продаёт. В Россию не хочется — у меня повестки висят и ничего в России кроме родственников нет. Решили поехать туда, где паспорт по рождению ребёнка и не слишком дорого. Так и выбрали Бразилию.
Почему Бразилия
Так получилось, что приехав сюда я уже был месяца 3 без работы. Понимаю, что так бесконечно нельзя, начал думать — и обнаружил: Бразилия защищает внутренний рынок огромными импортными пошлинами. Электроника из Китая, которая стоит $5 на AliExpress, в Бразилии на полке стоит $15–30 после таможни. Это значит, что если производить что-то локально — можно конкурировать по цене с китайским импортом. В любой другой стране это немыслимо.
Но что делать? Выбор пал на агросектор. Бразилия входит в топ-3 мировых аграрных экономик. Кофе, соя, сахарный тростник, фрукты. Огромное количество мелких и средних ферм. Много частных домов с огородами. Люди довольно технологичные — смартфоны у всех, банкинг через приложения. Но IoT для агро — это пока территория дорогих решений: буквально тут самый банальный еле умный датчик стоит $30+. Так и выбрал нишу. К слову в декабре родили.

Выбор стека: Rust для всего
Я выбрал Rust для всего. Прошивка, приложение, сервер — один язык. производительно надежно , безопасно, и - Для embedded — Rust даёт no_std без аллокатора, гарантии памяти на этапе компиляции, и не нужен сборщик мусора
- Для приложения — Tauri v2: Rust-бэкенд + веб-фронтенд на Preact. Раз уж делать быстро, то на максимум
- Для сервера — Rust + Tokio + QUIC
Mesh-сеть: когда WiFi нет
Начал думать так датчик это не так сложно но главная проблема — датчики стоят в поле огороде, где нет WiFi. Решение: mesh-сеть на ESP-NOW. Я назвал свой протокол Dynamic Wave Batch — данные распространяются «волнами» по хопам, собираются в батчи и маршрутизируются динамически.
ESP-NOW — это протокол Espressif поверх WiFi physical layer. Без TCP/IP, . Устройства общаются напрямую друг с другом на расстоянии до 200 метров (500 м в long-range режиме).
Архитектура:
```
[LEAF] ──ESP-NOW──→ [LEAF] ──ESP-NOW──→ [ROOT] ──WiFi──→ [Сервер]
│ │ │
└── датчик └── датчик └── есть WiFi,
в поле в поле отправляет данные
```
Одно устройство (ROOT) имеет доступ к WiFi и отправляет данные на сервер. Остальные (LEAF) передают показания по mesh-цепочке до ROOT. То есть мы получаем высокую дальность почти как у LoRa, но дешевле и немного быстрее.
Многохоповая маршрутизация
Данные летят не напрямую к ROOT — они прыгают через промежуточные узлы. Каждый узел знает своё расстояние до ROOT до каждого соседа в хопах (wave) и выбирает ближайшего соседа как «родителя»:
Node C (hops=2) ──→ Node B (hops=1) ──→ ROOT A (hops=0)
│ │ │
├─ SensorData ──────>│ │
│<──── ACK ──────────┤ │
│ ├─ Forward ─────────>│
│ │<──── ACK ──────────┤
```
Каждый хоп подтверждается ACK — отправитель может сразу уснуть, не дожидаясь, пока данные доедут до ROOT. Есть запасной родитель на случай, если основной пропал. А скорость ESP-NOW позволяет прокинуть данные через 3–4 хопа за доли секунды — это не LoRa, где каждый пакет ползёт.
Бинарный протокол: каждый байт на счету
ESP-NOW даёт максимум 250 байт на пакет. Если пихать туда JSON — влезет пара полей. Поэтому я сделал собственный бинарный секционный формат:
/// Битовые флаги — какие секции включены в пакет pub const SENSOR_DATA: u8 = 0b00_0001; // данные датчиков pub const TIME_SYNC: u8 = 0b00_0010; // синхронизация времени pub const PARENT_INFO: u8 = 0b00_0100; // инфо о родителе pub const ROOT_INFO: u8 = 0b00_1000; // инфо о ROOT pub const RELAY_INFO: u8 = 0b01_0000; // relay-статус pub const OTA_INFO: u8 = 0b10_0000; // метаданные прошивки
Принцип простой: первый байт — битовая маска, дальше идут только нужные секции. LEAF в обычном режиме отправляет ~55 байт. В setup-режиме — всего ~26 байт. Сравните с JSON, где один ключ "humidity" уже 10 символов.
Выборы лидера
Кто становится ROOT? Тот, у кого лучше WiFi-сигнал. Но что если ROOT сломался или его унесли? Остальные должны сами выбрать нового.
Я реализовал алгоритм выборов:
pub enum ElectionState { Idle, // Всё хорошо, ROOT на месте Listening, // ROOT пропал — слушаем, может появится Collecting, // Не появился — собираем кандидатов WaitingConfirmation, // Выбрали — ждём подтверждения }
Критерии (в порядке приоритета): сила WiFi-сигнала → уровень батареи → MAC-адрес как tiebreaker. Есть защита от split-brain — когда два устройства одновременно думают, что они главные. Зона неопределённости по RSSI — если разница меньше порога, побеждает MAC.
Но можно и по-простому: пользователь через приложение назначает конкретное устройство ROOT-ом (is_designated флаг). Тогда автоматические выборы отступают — designated ROOT имеет приоритет, пока у него нормальный WiFi-сигнал. Удобно, когда знаешь, какой датчик стоит рядом с роутером.
Синхронизация сна и автономность
Датчик бесполезен, если его надо заряжать каждую неделю. Цель — месяцы автономной работы от LiPo.а как это сделать для этого нужно чтоб устройства умели спать и просыпатсья синхронно
Ключевые цифры:
- Deep sleep: 10 µA
- Active mode: 5 секунд раз в 15 минут = 0.56% duty cycle
- LEAF-нода на батарее 2000 мАч: ~5 месяцев
- ROOT (с WiFi): 2-3 недели
Все устройства спят 99.5% времени. Просыпаются раз в 15–30 минут, обмениваются данными за 5–10 секунд и снова в deep sleep.
Проблема: часы ESP32-C3 (RTC) дрейфуют — до 5% у дешёвого кварца. За 30 минут сна это 90 секунд ошибки. Устройства просто не встретятся в эфире.
Решение — компенсация drift:
struct DriftCompensation { accumulated_drift_ms: i32, // Накопленная ошибка estimated_error_ppm: i32, // Оценка частотной ошибки cycles_since_sync: u16, // Циклов с последней синхронизации }
ROOT при каждом пробуждении передаёт unix time. Узлы сравнивают со своими часами, считают drift в ppm и корректируют следующее пробуждение. Окно синхронизации — ±5 секунд.
Шифрование
Тут я сразу подумал о шифровании. Если бизнес пойдёт, то можно и камеры сделать, и другие датчики, и много чего ещё интересного — и всё это в единой mesh-сети. Но ESP-NOW по умолчанию передаёт данные открытым текстом, а IoT-устройства — любимая цель для атак. Я не хотел быть тем парнем, чьи датчики стали частью ботнета. Поэтому безопасность я закладывал с самого начала, а не прикручивал потом.
Как устройство впервые знакомится с приложением
Когда вы достаёте датчик из коробки, у него нет ни WiFi-пароля, ни ключей шифрования — ничего. Всё начинается с BLE (Bluetooth). И тут важно: даже самый первый контакт между приложением и устройством уже зашифрован.
Схема такая:
1. Приложение и датчик генерируют каждый свою пару ключей ECDH (эллиптическая кривая P-256)
2. Обмениваются публичными ключами по BLE
3. Каждая сторона математически вычисляет общий секрет — не передавая его по воздуху
4. Из этого секрета через SHA-256 получается сессионный ключ AES-256
После этого всё через BLE летит зашифрованным: WiFi-пароль, email владельца, JWT-токен для сервера, список соседей в mesh-сети. Формат каждого сообщения: [длина:2][nonce:12][шифротекст][тег:16]. Тег — это подпись, которая гарантирует, что данные не подменили по дороге.
Регистрация на сервере
Во время провизионирования приложение передаёт датчику JWT-токен. С этим токеном датчик потом регистрируется на сервере — сервер знает, что этот датчик принадлежит конкретному пользователю. Без токена — сервер просто не примет данные. Никакой чужой датчик не сможет подкинуть показания в вашу систему.
Аттестация устройств — как у Apple
Я реализовал систему аттестации, похожую на то, как Apple проверяет подлинность своих устройств. У каждого ESP32-C3 есть уникальный ID, прожжённый в eFuse на заводе — его нельзя изменить или скопировать. На базе этого ID генерируется уникальный ключ устройства.
Сервер может отправить challenge (случайное число), а устройство должно подписать ответ, включающий:
- уникальный ID из eFuse
- версию и хеш прошивки
- статус защиты (secure boot, шифрование flash, отключён ли JTAG)
Если кто-то склонирует прошивку на другой чип — подпись не совпадёт. Если подменит прошивку — хеш не совпадёт.
Шифрование mesh-трафика
Каждый пакет в mesh-сети шифруется AES-256-GCM. Ключ шифрования сети раздаётся при провизионировании — то есть тоже приходит по шифрованному BLE-каналу.
Критический момент — nonce (одноразовое число). AES-GCM категорически нельзя использовать с одинаковым nonce дважды — иначе атакующий сможет расшифровать трафик. Я собираю nonce из трёх частей:
```
┌────────────────┬────────────────┬────────────────┐
│ Boot Counter │ Sequence │ Device ID │
│ (4 байта) │ (4 байта) │ (4 байта) │
└────────────────┴────────────────┴────────────────┘
```
- Boot Counter — хранится во flash, увеличивается при каждой перезагрузке → nonce не повторится после ребута
- Sequence — счётчик в RAM, растёт с каждым пакетом → nonce не повторится в рамках одной сессии
- Device ID — последние 4 байта MAC → nonce не совпадёт между устройствами
Replay-защита
Каждый узел помнит последний boot_counter и sequence от каждого соседа. Если прилетает пакет со старыми значениями — он отбрасывается. Нельзя перехватить пакет и отправить его повторно.
Production lockdown
pub const SECURE_BOOT_ENABLED: u8 = 0b0000_0001; // подпись прошивки pub const FLASH_ENCRYPTION_ENABLED: u8 = 0b0000_0010; // шифрование flash pub const JTAG_DISABLED: u8 = 0b0000_0100; // отладка отключена pub const UART_SECURE_MODE: u8 = 0b0000_1000; // UART залочен pub const NVS_ENCRYPTED: u8 = 0b0001_0000; // хранилище зашифровано pub const DEBUG_DISABLED: u8 = 0b0010_0000; // дебаг отключён
Когда все флаги включены — устройство запечатано. Нельзя подключиться отладчиком, нельзя считать flash, нельзя подменить прошивку.
Вся криптография — pure Rust, no_std. Никаких openssl, никакого libc. Работает на микроконтроллере с 400 КБ RAM.
OTA: обновления через mesh
Как обновить прошивку датчика, который стоит в поле без WiFi?
Три пути:
1. WiFi → ROOT — ROOT скачивает прошивку с сервера
2. ROOT → LEAF по mesh — каскадная раздача, сначала ближайшим по RSSI
3. BLE-офлайн — пользователь скачивает прошивку в приложение, передаёт по Bluetooth
Flash-память разбита на разделы:
```
factory (1.3MB) — заводская прошивка, fallback
ota_0 (1.3MB) — основной слот
ota_1 (1.3MB) — запасной слот
```
Если новая прошивка не загрузилась 3 раза подряд — автоматический откат на factory. Устройство не превращается в кирпич.
Корпус
Ну тут все просто , ASA + TPU + 3д принтер ) а на и ацетоновая баня в конце


Приложение: Tauri + Preact
Для приложения я выбрал Tauri v2 — это как Electron, только бэкенд на Rust вместо Node.js, а фронтенд на любом веб-фреймворке. Приложение весит ~15 МБ вместо 200 МБ у Electron. Работает на macOS, Windows, Linux, а в перспективе — iOS и Android.
Фронтенд — Preact + Signals. Preact — это React на минималках (3 КБ), а Signals — реактивные сигналы без virtual DOM overhead. Локализация на 6 языков из коробки: русский, английский, португальский, испанский, немецкий, китайский.
Провизионирование в 3 клика
Самая первая задача — подключить новый датчик. Я хотел, чтобы это было максимально просто:
1. Нажми «Добавить устройство» — приложение сканирует BLE, находит все датчики с префиксом enddelIOT-
2. Выбери WiFi-сеть — приложение само сканирует доступные сети и показывает список. Если пароль уже сохранён — подставляет автоматически
3. Готово — приложение по BLE передаёт датчику зашифрованные WiFi-креды, JWT-токен, список соседей в mesh-сети, и датчик перезагружается уже в рабочем режиме
Под капотом за эти 3 клика происходит: ECDH-хендшейк → генерация сессионного ключа → шифрование AES-256-GCM → чанкованная передача данных (BLE MTU ограничен 244 байтами) → регистрация на сервере. Но пользователь этого не видит — для него это «нажал, подождал 5 секунд, работает».
Визуализация mesh-сети
Отдельный экран — интерактивная диаграмма mesh-топологии. Рисуется на Canvas:
- ROOT в центре, LEAF-ноды расположены кольцами по хопам
- Анимированные линии между узлами — показывают поток данных
- Цвет линий меняется по RSSI: зелёный = хороший сигнал, красный = на грани
- «Пульс» от ROOT наружу — визуализация волны синхронизации WaveBatch
- Дуги заряда батареи вокруг каждого узла
- Pan, zoom, тап по устройству для детальной информации
Можно назначить ROOT вручную, сменить роль устройства, задать приоритетного «родителя» — всё через UI.
Паспорт растения
Каждому датчику можно привязать профиль растения с диапазонами влажности: оптимальный, предупреждение, критический. После этого открывается «паспорт» — полная карточка:
- Текущая влажность с индикатором статуса (оптимально / сухо / залито)
- График влажности за 24 часа / 7 дней / 30 дней с пороговыми линиями
- Температура и уровень заряда
- Таймлайн поливов — приложение автоматически определяет полив, когда влажность резко прыгает вверх (>10%), и записывает историю

- Статистика: средняя частота поливов, последний полив

главный экран и некоторые настройки приложения

Home Assistant прямо из приложения
В настройках можно подключить свой MQTT-брокер: хост, порт, логин, пароль. Кнопка «Test Connection» проверяет связь. После включения — все датчики автоматически появляются в Home Assistant через auto-discovery. Управление интеграцией — из приложения, без правки конфигов.
Безопасность на уровне приложения
- ECDH-шифрование в Rust-бэкенде — тот же код, что и в прошивке. Один протокол на обоих концах
- TLS 1.2+ для всех HTTP-запросов (reqwest + rustls)
- JWT-токены с автоматическим рефрешем за 5 минут до истечения
- Offline-first: приложение кеширует устройства и токены, работает без интернета. При восстановлении связи — синхронизация
- Zeroize: чувствительные данные (ключи, пароли) зануляются в памяти после использования
Сервер: Axum + QUIC + вся обвязка
Сервер, как и всё остальное, на Rust. Но тут я не просто поднял REST API — я построил полноценную инфраструктуру с несколькими протоколами, очередями и real-time доставкой.
Два уровня связи
Датчики → сервер: ROOT-нода, у которой есть WiFi, отправляет данные по HTTPS (TCP + TLS 1.3). На ESP32-C3 я поднял TCP-стек через smoltcp + embedded-tls — полноценный HTTPS-клиент на микроконтроллере без операционной системы. Это надёжно и работает через любой роутер.
Приложение ↔ сервер: а вот тут QUIC — протокол от Google/Cloudflare поверх UDP. Быстрее TCP, встроенный TLS 1.3, мультиплексирование потоков. Для real-time обновлений в приложении это идеально. Я использую [tokio-quiche от Cloudflare](https://blog.cloudflare.com/async-quic-and-http-3-made-easy-tokio-quiche-is-now-open-source/) + второй вариант на Quinn.
Сейчас приложение временно подключается по WebSocket, потому что Railway.app (где хостится сервер) не поддерживает UDP. Код для QUIC уже написан и готов — ждёт хостинг с UDP.
Стек данных
```
[Датчик] → HTTPS/TCP → [Axum API] → [RabbitMQ] → [Worker] → [PostgreSQL]
↓
[Redis pub/sub] → [WebSocket] → [Приложение]
↓
[MQTT broker] → [Home Assistant]
```
- Axum 0.7 — веб-фреймворк. REST API + WebSocket на одном порте. Rate limiting через tower_governor, gzip-компрессия, CORS.
- PostgreSQL через sqlx — и тут фишка: sqlx проверяет SQL-запросы на этапе компиляции. Если ты опечатался в названии колонки — код не соберётся. Не в рантайме упадёт, а в cargo build.
- RabbitMQ — показания с датчиков не записываются в базу напрямую. Они падают в очередь, а worker забирает их батчами по 50 штук раз в секунду. Это развязывает приём данных и запись — сервер не тормозит, даже если база задумалась.
- Redis — кеш, real-time состояние устройств (онлайн/офлайн), pub/sub для мгновенной доставки обновлений в приложение.
Background-воркеры
На сервере крутятся несколько фоновых задач:
- SensorReadingsWorker — достаёт показания из RabbitMQ, пишет в PostgreSQL, рассылает по WebSocket и пробрасывает в MQTT
- MeshVisibilityWorker — отслеживает, какие устройства видят друг друга, строит карту топологии
- OfflineDetector — если устройство не вышло на связь дольше таймаута — помечает его офлайн и уведомляет приложение
- CleanupWorker — чистит старые данные, чтобы база не пухла бесконечно
Аутентификация
JWT-токены с HS256. Два способа входа: email + пароль (Argon2 хеширование) и Google OAuth — для мобильного приложения это удобнее. Пароли хешируются Argon2 — тот же алгоритм, что рекомендует OWASP.
Home Assistant и путь к open source
Отдельная тема — интеграция с Home Assistant. Сервер умеет пробрасывать показания в любой MQTT-брокер в формате Home Assistant auto-discovery:
```
homeassistant/sensor/enddel_{device_id}/humidity/config → конфигурация
enddel/{device_id}/humidity → значение
enddel/{device_id}/temperature → значение
enddel/{device_id}/battery → значение
```
Подключил — и датчики автоматически появляются в Home Assistant. Без ручной настройки.
И тут я думаю о более серьёзном шаге: в перспективе я хочу сделать серверную часть open source. Почему? Потому что когда речь идёт о датчиках, которые стоят у вас на участке и собирают данные — вы должны быть уверены, что ваши данные это ваши данные. Не мои, не облака, не третьей стороны. Открытый код сервера означает, что любой может развернуть его у себя, проверить, что он делает, и не зависеть от моего хостинга. Хочешь — используй мой облачный сервер. Не хочешь — подними свой. а с открытым сервером вся цепочка становится прозрачной.
Общение с клиентами: когда ты не говоришь на языке клиента
Предыстория: мечта о магазине
Когда я еще жил в грузии я активно програмировал себе магазин как и говорил выше и в том числе экспериментировал с чатиком хотел что то типо KRISP но бесплатно и с ллм . Тогда это был просто виджет для сайта + админка. Но фундамент заложился именно тогда. но теперь это пригодилось так как нужно понимать: мои клиенты — это бразильцы, а может и кто угодно, но точно не русскоговорящие. Им нужно как-то помогать, у них будут вопросы. Они увидят рекламу в Instagram, напишут — и что, мне с Google Translate сидеть? Это не работает, когда у человека не подключается датчик и он нервничает.
Поэтому я написал свою чат-систему — ecoChat. ( ТЕХНИЧЕСКОЕ НАЗВАНИЕ ТИПО ЭКОЛОГИЯ)
Архитектура
Три компонента:
- ecoChatWidget — виджет, который встраивается на сайт или в приложение. Клиент открывает чат и пишет на своём языке.
- ecoChatAdmin — админка для меня (Next.js, PWA). Вижу все чаты, отвечаю, управляю настройками. Поддерживает push-уведомления, работает с телефона.
- ecoChatServer — бэкенд на Go. WebSocket для real-time, PostgreSQL для хранения, Redis для кеша. Подключается к Instagram и WhatsApp — сообщения из мессенджеров падают в ту же админку.

LLM-переводчик
Ключевая фишка: каждое сообщение автоматически переводится через LLM. Клиент пишет на португальском — я вижу на русском. Отвечаю на русском — клиент получает на португальском. Перевод проходит через Qwen 3.5 4b no think через vllm на пк и тунелем черз ngrock , так же применются оптимизациии токенов (формат TOON экономит ~40%). Переводы кешируются в базе, чтобы не гонять повторные запросы.
Мультиагентный оркестратор
Раз уж я начал осваивать ллм я сделал — автоответчик. Когда меня нет онлайн (или просто не хочу отвечать на типовые вопросы), включается система из трёх AI-агентов: работающих на qwen 3.5 9b think

[Клиент] → [Оркестратор] → выбирает агента:
├─ PlantExpert — всё про растения
├─ DeviceSpecialist — настройка, проблемы, mesh
└─ SupportSpecialist — FAQ, приложение, контакты
```
Оркестратор (Supervisor Agent) анализирует сообщение клиента и определяет intent:
- plant_care — «какая влажность нужна для монстеры?» → PlantExpert
- device_setup — «как подключить датчик к WiFi?» → DeviceSpecialist
- troubleshooting — «датчик не отвечает» → DeviceSpecialist
- mesh_config — «как работает mesh-сеть?» → DeviceSpecialist
- общие вопросы → SupportSpecialist
Что умеют агенты
PlantExpert — встроенная база из 89 видов растений с порогами влажности, температуры, освещения. Умеет подбирать растения по условиям, сравнивать виды, давать рекомендации по уходу. Это не ChatGPT-обёртка — у него есть реальные данные о каждом растении.
DeviceSpecialist — умеет:
- Запросить через API список устройств пользователя и их статус
- Получить последние показания датчика в реальном времени
- Выдать пошаговую инструкцию по настройке
- Диагностировать проблемы (батарея, сигнал, mesh-связь)
- Объяснить как работает mesh-сеть и OTA
SupportSpecialist — FAQ из 49 вопросов по 8 категориям, информация о приложении, контакты. Отвечает на всё, что не попадает в две другие категории.
Всё это написано на Go с использованием моего форка Google ADK — [adk-go_openai](https://github.com/babasha/adk-go_openai). Оригинальный ADK от Google работает только с Gemini. Я написал кастомный OpenAI-совместимый адаптер, который позволяет подключать любую модель через OpenAI API: и — локальные модели через LM Studio или Ollama Vllm И так далее. Это значит, что агенты могут работать хоть на домашнем сервере без облака. Форк протестирован с Qwen 3.5 и Google Gemma 3.
и да промпты для агентов хранятся в базе данных — могу менять поведение без передеплоя.
Зачем это всё
Один человек не может быть 24/7 в чате. А AI-агент с доступом к реальным данным (показания датчиков, база растений, FAQ) может закрыть 80% вопросов без моего участия. И на любом языке.
ГЛАВА 2 Директор: AI, который управляет AI
Буквально месяц назад я вдохновился проектом [Open Claw](https://github.com/openclaw) и понял, что мои агенты — это хорошо, но им нужен руководитель. Так появился Директор — Level 2 агент, который наблюдает за работой всех остальных агентов и улучшает их.
Архитектура теперь трёхуровневая:
```
Level 0: [PlantExpert] [DeviceSpecialist] [SupportSpecialist]
↑ ↑ ↑
Level 1: [Оркестратор (РОП)]
↑ ↑ ↑
Level 2: [Директор]
```
Что делает Директор:
1. Анализ работы агентов. Директор собирает саммари всех чатов и анализирует: сколько эскалаций (клиент попросил живого человека), сколько пустых ответов, какие темы повторяются. Используется мощная модель (Claude/GPT-5.4 или типо того ), пока агенты работают на более лёгких.
2. Самостоятельная рефлексия. Перед каждым новым анализом Директор сначала оценивает, сработали ли его предыдущие директивы. Сравнивает метрики до и после: упал ли процент эскалаций, уменьшились ли пустые ответы. Если нет — пересматривает стратегию.
3. Автоматическая оптимизация промптов. Если Директор видит, что агент плохо справляется с определённой темой — он сам переписывает промпт этого агента. Промпты хранятся в базе данных с версионированием. Директор создаёт новую версию, сохраняет изменения и причину. Можно откатить в любой момент.
4. Автоматическое создание скиллов. Директор анализирует паттерны использования тулов за последние 7 дней. Если видит повторяющийся сценарий (например, «клиент спрашивает про доставку» 5+ раз) — автоматически создаёт новый скилл. Лимит: максимум 10 автоскиллов, не чаще 1 в день.
5. Event-triggered анализ. Директор не работает по расписанию — он реагирует на события. 3 эскалации за час? Директор запускает анализ. 5 пустых ответов за день? Анализ. Тулы падают с ошибками? Анализ. Cooldown 30 минут между триггерами, чтобы не гонять модель без толку.
6. Дайджесты. Раз в неделю и раз в месяц Директор генерирует сводный отчёт: что было, какие тренды, что улучшилось, что ухудшилось.
7. Identity. У Директора есть собственная «личность», которая кешируется и определяет тон и стиль рекомендаций. При первом запуске он создаёт identity с дефолтами и потом дорабатывает по мере обучения.
По сути, Директор — это замкнутый цикл улучшения: наблюдает → анализирует → выдаёт директивы → проверяет результат → корректирует. Без моего участия.
Что дальше
Сейчас март 2026. Я в Блумэнау, жду документы. Проекту ~5 месяцев без учета месенджера . Есть рабочие прототипы, весь стек написан, mesh работает. как только получу внж побегу делать ИП и отркывать старницу на местном Амазоне и аналогах , к тому моменту думю отполирую чат поддержки , и отсниму рекламу дай бог все получится ) ну если нет наверное придется идти тарелки мыть или даже не знаю )
PSS экомику бизнеса не стал описывать так как это большая тема с местными приколами , но если в кратце тот тут можно импортировать компоненты почти без импортного налого будучи бизнесом а налог примерно 100% , и то что тут продается за какие деньги приложу

