Улучшения: агент · голос · архитектура
Ночь 16→17.07.2026 · всё найдено по коду (здесь — имена файлов; полные пути со строками — в ночных отчётах анализа, дам по запросу).
Топ-находки ночи (обсудить в первую очередь)
Голос обходит защитные механизмы ядра
Текстовый канал проходит конвейер гейтов: blocklist, «красная кнопка» (отключение бота), secondary-гейт для клиник с политикой «новых пациентов — оператору», фильтр устаревших сообщений. Голос заходит через /chat напрямую — ни один из этих гейтов на звонки не действует. Пример последствия: клиника нажала «красную кнопку» — бот молчит в чатах, но продолжает отвечать по телефону.
api.py (путь /chat) vs gateway/handler.py (стадии 1.2/1.25/1.55) · M → мульти (на 40 клиник рассинхрон политик умножится)
Fail-open конфигурации клиники
Загрузчик клиники при отсутствующем YAML молча возвращает пустой дефолтный конфиг — агент стартует «клиникой-призраком» без каталога услуг и правил. При этом один clinic_id из прод-списка ядра не имеет файла конфига в репо, а /chat без явного clinic_id подставляет дефолт "test". Три мелочи, складывающиеся в тихий сценарий «бот работает не той клиникой и никто не заметил».
clinic_loader.py (fail-open + прод-список), api.py (default "test") · S–M (fail-fast + валидатор схемы + обязательный clinic_id) · → мульти → он-премис
Четыре копии конвейера сообщений
handle_inbound / handle_inbound_stream / /chat / /chat/stream синхронизируются вручную — уже расходились (фиксы «зеркалить» PD-531/535/572). Плюс в голосе роутинг «префикс → бекенд» продублирован 4 раза (воркер + token-server). Каждый новый канал/режим умножает риск.
gateway/handler.py + api.py; voice: 04-воркер + token_server · L (аккуратная консолидация) · → мульти
Секрет-гигиена
Реальный shared-secret LLM-прокси закоммичен в нескольких .env.example и в доках двух репо; LLM-прокси ходят по HTTP с секретом в заголовке; пароли инфраструктуры зашиты в компоузы; ключ наблюдаемости светится в CI. Пока это «своё облако» — терпимо; при передаче кода заказчику (он-премис) — стоп-фактор.
детали в разделе D · M (ротация + secrets-менеджмент + TLS на прокси) · → он-премис
Перевод звонка — blind, без возврата
Если в клинике не взяли трубку — busy и hangup, пациент потерян на самом дорогом шаге. Warm transfer (мост с брифингом оператора) + очередь + «мы перезвоним» — прямой прирост конверсии и обязательный элемент для «горячей линии страны».
voice: 04-воркер (transfer-механика), asterisk dialplan · M · → мульти
A. Ядро / агент
| Что | Зачем | Усилие |
|---|---|---|
| Пробросить гейты (blocklist/red-button/secondary/staleness) в /chat-путь api.py, gateway/handler.py | единое поведение каналов (топ-1) | M |
| Fail-fast загрузки клиники + JSON-schema валидатор YAML (26 файлов — копипаста) clinic_loader.py, clinics/* | конец «клиник-призраков», защита от дрейфа 40 конфигов | M → мульти |
| Таймзона клиники вместо московского хардкода (5+ мест: 4 модуля + api + SQL напоминаний) tools/crm.py, medflex_plugin.py, confirmation_scheduler.py, agents/booking.py, api.py, db/booking_confirmation_runs.py | без этого ни одна не-московская клиника не работает корректно | S → мульти |
| Нормализация телефонов → E.164 (сейчас только +7) identity.py, crm/ident_plugin.py | испанский номер не пройдёт identity | S → мульти |
| Кэши без TTL/лимитов: слоты, пациенты, брони (in-memory; инцидент уже был) tools/crm.py, crm/routing_adapter.py, tools/booking_patient.py | память, устаревшие слоты, потеря при рестарте | M |
| Стабильные id слотов (сейчас нумерация от порядка выдачи) tools/crm.py, ident_plugin.py | гонки: «Вариант 2» ≠ тот же слот при повторном вызове | M |
| Контекст-переменные (8+ штук, класс багов «протечки между ходами», PD-356) tools/crm.py + agents/* | свести в единый turn-контекст | L |
| Молчаливый фолбэк чекпойнтера на память при недоступном Postgres graph.py | диалог «забывается» без алерта — сделать громким | S |
| Слоты из CRM: N+1 запрос на врача; без специализации — опрос всех врачей crm/ident_plugin.py | latency и нагрузка на CRM; для cross-clinic умножится | M → мульти |
| print()-отладка в проде; /graph без авторизации tools/crm.py, ident_plugin.py, api.py | логи/поверхность | S |
| Перенос на связке «новая бронь + заявка админу на отмену» открывает окно двойной записи tools/crm.py, action_queue | риск двойных визитов; бэкстоп на чтение-CRM инертен | M |
B. Голос
| Что | Зачем | Усилие |
|---|---|---|
| Warm transfer + возврат звонка при неответе клиники (топ-5) 04-воркер, dialplan | конверсия горячей линии | M |
| DID из атрибутов SIP-участника вместо парсинга имени комнаты; убрать env-прибитую клинику 04-воркер, dialplan, livekit-sip | фундамент «номер страны/клиники» — сейчас DID теряется | M → мульти |
| Свести 4 копии роутинга «префикс→бекенд» в один источник (отдавать из ядра) 04-воркер + token_server | расползание конфигов; дубликаты-опечатки уже есть | M |
| Филлер: стартовать с задержкой ~300–500мс и отменять при раннем первом чанке llm-адаптер | сейчас филлер играет даже при мгновенном ответе — лишняя пауза | S |
| Язык как параметр voice-runtime (STT/TTS/нормализация/диктовка per язык) voice_runtime + YAML ядра | испанский/английский; сейчас язык прошит | L → мульти → он-премис |
| Приветствие-WAV не перебивается голосом пациента (отдельный трек) 04-воркер (preroll) | заговорил поверх приветствия — оно не остановится | S–M |
| PD-419 (перебивания) и PD-482 (филлеры на приветствиях) — в коде не начаты, barge-in на дефолтах SDK 04-воркер | два верхних тикета голосового UX | M |
| Локальный STT-плагин (faster-whisper) как альтернативный стек новый плагин по образцу существующих | блокер он-премиса №1 + независимость от облака | L → он-премис |
| FAQ-кэш: эмбеддинги через сетевой вызов перед решением — рассмотреть локальную модель semantic_faq_cache | latency + автономность | M |
| Монки-патчи SDK (3 места) — заменить на официальные хуки при апгрейде livekit-agents 04-воркер, tts_factory | хрупкость к обновлениям | M |
| Телефонные конфиги (dispatch rule, транк) не воспроизводимы из репо — сделать IaC deploy/notes → код | сейчас поднимается руками по заметкам | S–M → он-премис |
C. Hub / флот
| Что | Зачем | Усилие |
|---|---|---|
| Пиновка версии ядра при деплое (сейчас клонится свежий main) hub deploy-механика | воспроизводимость; без этого 40 клиник = 40 «снежинок» | S–M → он-премис |
| Bulk-деплой волнами + rollback hub | обновить 40 клиник ≠ 40 кликов | M–L → мульти |
| Персистентные сессии админов (сейчас in-memory: рестарт = разлогин всех) hub auth | операционка флота | S–M |
| Роли «оператор сети / супервайзер страны» (сейчас админ = ровно 1 клиника) hub admin-модель | центральный колл-центр сети | M → мульти |
| Деплой-auth: фронт шлёт токен query-параметром, бэк ждёт заголовок (PD-598/599); токен в URL попадает в логи hub фронт+API | сломано и небезопасно | S |
| Мёртвый функционал: страница качества бьёт в несуществующие ручки; внутренняя дока описывает удалённые API hub фронт/доки | гигиена, ложные ожидания | S |
| GitHub-auth на каждый запрос (2 внешних вызова, без кеша) + деплой клоном с github.com hub auth/deploy | rate limit, зависимость рантайма от GitHub | M → он-премис |
| Автосинк промптов: снять молчаливый try/except вокруг sync_all hub lifespan | провал синка станет видимым (красный деплой), а не тихим — июльский инцидент ловился бы сразу | S |
D. Безопасность
| Что | Факт | Усилие |
|---|---|---|
| Ротация скомпрометированного прокси-секрета | реальный секрет закоммичен в .env.example (5+ файлов) и доках двух репо | S + ротация → он-премис |
| TLS на LLM-прокси | сейчас HTTP, секрет в заголовке открытым текстом через интернет | S–M |
| Пароли инфраструктуры из компоузов → env/secrets | слабые дефолтные креды БД и сервисов наблюдаемости (PD-295) | M |
| Общий API-ключ на весь флот клиник | один ключ пациентской поверхности для всех инстансов | M |
| HTTPS на hub-nginx, security-заголовки, rate-limit | сейчас :80 без TLS за периметром | M |
| deploy-лог может содержать секреты .env; GitHub-токен в localStorage | hub | S–M |
| SSH-деплой со StrictHostKeyChecking=no | MITM-поверхность деплоя | S |
| Роль-гвард только на клиенте (вкладки суперадмина) | сервер не проверяет роль на части ручек | M |
E. Процессы и поставка
| Что | Зачем | Усилие |
|---|---|---|
| Релизный «дистрибутив»: пин версий тройки репо + миграции + промпты (см. развилку №5) | воспроизводимость, он-премис, откаты | M–L → он-премис |
| Прибить теги docker-образов (сейчас местами :latest, включая медиа-стек) | невоспроизводимые окружения | S |
| Интеграционный smoke тройки (core+hub+voice) в CI | совместимость версий сейчас никем не проверяется | M |
| Док-гниль: голосовые STATUS/DEMO_GUIDE/HOWTO описывают апрельское состояние | онбординг, ложные инструкции | S |
| Единый дамп «эффективной конфигурации» голоса (env-флаги + YAML двухслойно, сумму не видно) | дебаг конфигураций за минуты, а не раскопки | S–M |
| Судья по сессиям (PD-501) — доводить: рубрика для живых диалогов + запись скоров | качество на потоке; любая миграция LLM без evals невозможна | M → он-премис |
Быстрые победы (можно в ближайший спринт)
- Таймзона вместо московского хардкода (5+ мест) + E.164-телефоны — разблокирует любую не-РФ клинику. S
- Fail-fast загрузки конфига клиники + обязательный clinic_id в /chat. S
- Филлер с задержкой 300–500мс. S — минус лишняя пауза на каждом быстром ответе.
- Снять молчаливый try/except с синка промптов. S — провал станет видимым сразу.
- Громкий алерт на фолбэк чекпойнтера в память. S
- Ротация прокси-секрета + TLS на прокси. S–M
- Деплой-auth хаба (заголовок vs query) + убрать токен из URL. S
- Пин версии ядра при деплое клиники. S–M
- Валидатор YAML клиник в CI. S–M
- IaC для dispatch rule/транка голоса. S–M
Вопросы на созвон
- Согласны, что топ-1 (голос обходит гейты) — первый приоритет надёжности? Кто берёт?
- Какие 3–5 «быстрых побед» берём в ближайший спринт и кто владелец каждой?
- Кто владелец секрет-ротации и TLS на прокси — до любых разговоров о передаче кода наружу?
- PD-419/PD-482 (перебивания и филлеры) — планируем в голосовой спринт или откладываем осознанно?
Тикеты, где уже есть контекст: PD-295, PD-356, PD-419, PD-469, PD-482, PD-501, PD-531/535/572, PD-598/599. Полные отчёты с path:line — в ночных отчётах анализа (17.07), дам по запросу.