У меня в разработке два проекта, связанных с HR. Чтобы проектировать их не по статьям, а по живому опыту, я решила пройти весь путь кандидата своими руками: как работает поиск, как устроен найм, как проходят собеседования с ИИ. Составила анкету, разместила её на hh.ru, откликнулась на вакансии в разных компаниях и потратила на это несколько недель. Больше всего материала дал ГигаРекрутер Сбера: за это время я прошла с ним серию интервью по разным позициям, от Team Lead LLM-инженера до CIO, и по каждому у меня сохранились логи с таймингами.
Девятого сентября, 14:47. Бот задаёт вопрос про метрики AI-трансформации: lead time, cycle time, дефектность, стоимость изменений. Читаю дальше и вижу, что в том же сообщении, без паузы, идёт ответ. Развёрнутый, на несколько абзацев, с моими цифрами и моими формулировками из предыдущих реплик. Только я его не писала.
С этого момента я стала записывать всё подряд. Ниже итоги по работе ГигаРекрутера.
Что это за система
ГигаРекрутер - AI-агент Сбера, который проводит первичные интервью с кандидатами вместо человека. По официальным данным, за первые месяцы 2026 года через него прошло больше 130 000 интервью, время от отклика до оценки сократилось с 23 до 3 часов. Пилот стартовал в сентябре 2025 года во внутреннем подборе, потом систему масштабировали.
Я четвёртый год проектирую диалоговых агентов, RAG-контуры и мультиагентные системы, которые работают в проде у клиентов. Когда чужая система ведёт себя странно, я делаю то же, что при аудите: восстанавливаю внутреннее устройство по внешнему поведению.
Ниже пять классов дефектов. Два относятся к информационной безопасности, три к оркестрации и надёжности. Оркестрацией я называю слой, который управляет последовательностью шагов агента: какое событие обработать сейчас, в каком состоянии находится диалог, что делать, если пришло два события сразу. По каждому дефекту даю наблюдение с реальным фрагментом диалога, реконструкцию причины на уровне архитектуры и инженерное решение.
Все пять классов известны и разобраны в литературе. Я описываю, как они проявляются в конкретном высоконагруженном продукте, с механизмами и таймингами. Публичного инженерного разбора именно ГигаРекрутера я не нашла: есть обзоры ИИ-рекрутеров и пользовательские жалобы, но не архитектурный анализ.
Архитектура по наблюдаемым признакам
Прежде чем разбирать дефекты, восстановлю, как устроен агент, чтобы было видно, в каком месте пайплайна что ломается.
Что видно снаружи. Вход через мессенджер, Telegram или Max, привязка к кандидату через шеринг контакта. Вопросы генерируются динамически под пару «вакансия плюс резюме»: они меняются от позиции к позиции и цепляются за конкретные строки профиля. На позицию CIO меня спросили про P&L и совет директоров, на позицию по безопасности GenAI - про кафедру в МИФИ и завершённость программы. Значит, на входе шага есть контекст вакансии и контекст резюме, и они подаются в модель как часть промпта. Ответы принимаются свободным текстом, каждый обрабатывается перед следующим вопросом. Значит, есть пошаговый цикл с сохранением истории диалога в контексте сессии. На выходе отчёт с рекомендацией для рекрутера. Значит, есть скоринговый слой, который оценивает ответы относительно требований вакансии.
Отсюда рабочая гипотеза о пайплайне одного шага:
[контекст вакансии] + [резюме] + [история диалога] + [текущий ответ]
│
▼
генерация: следующий вопрос + (вероятно) критерии оценки ответа
│
▼
скоринг ответа относительно требований
│
▼
отправка кандидату: должен уйти только следующий вопрос
Самое уязвимое место - последний шаг. В нём из нескольких сгенерированных полей должно уходить наружу одно. Именно здесь возникает первая находка.
Находка 1. Внутренний артефакт генерации в клиентском канале
Наблюдение. То, с чего я начала. В одном сообщении пришёл вопрос про метрики и следом готовый ответ на него. Фрагмент того, что прислал бот:
«...выстроить измерение эффекта трансформации — это отдельный контур. Я ввела два уровня метрик: инженерные и бизнесовые... Lead Time от постановки задачи до рабочего прототипа сократился примерно втрое. Cycle Time внутри итерации стал стабильным за счёт спецификации как единого источника правды... Степень автоматизации этапов PDLC: проектирование с LLM-оппонентом 80–90%, генерация кода из spec 70–80%...»
Несколько абзацев связного текста с моими цифрами и оборотами плюс детали, которых в моих репликах не было: проценты автоматизации по этапам, термин «канареечные релизы». Модель не процитировала меня, она сгенерировала правдоподобный ответ за меня на базе накопленного контекста сессии.
Я написала боту, что в сообщении склеились вопрос и ответ, и дала свой вариант заново. Интервью продолжилось как ни в чём не бывало.
Реконструкция причины. Вижу два правдоподобных механизма, и оба ведут к одному решению.
Первый. В пайплайне шага модель генерирует не только следующий вопрос, но и ожидаемый ответ, чтобы скорингу было с чем сравнивать реальную реплику кандидата. Приём разумный. Дефект в том, что оба поля, вопрос и эталон, оказались в одном текстовом блоке, и блок целиком ушёл в канал. Разделение «в сообщение идёт поле question, поле reference_answer остаётся служебным» не сработало.
Второй, более простой. Модели подали историю диалога как транскрипт и попросили следующий вопрос. Она сгенерировала вопрос и продолжила «за кандидата», потому что формат транскрипта к этому располагает, а стоп-последовательности или жёсткого разделения ролей не было. Кто работал с моделями до появления chat-форматов, узнает этот сбой.
В обоих случаях техническая первопричина одна: результат модели разбирается как плоский текст, а не как структура, и этот текст уходит в send_message целиком.
Классификация. По OWASP Top 10 for LLM 2025 это LLM05 Improper Output Handling, с поправкой, что категория задумана для случаев, когда нижестоящая система доверяет выводу модели без проверки. Здесь нижестоящая система - функция отправки. Частично сюда же ложится LLM07 System Prompt Leakage: наружу утекает не системный промпт, но служебная часть генерации. В отчёте Zscaler ThreatLabz за 2026 год похожий класс назван prompt data leakage, и одна из его форм - когда модель возвращает в ответе приватный контекст, который для этого не предназначался.
Последствие. Раскрывается внутренняя логика оценки: по эталону видно, что система считает сильным ответом. Кандидат, увидевший такой текст, может подогнать под него следующие реплики. И это признак, что граница между служебным и клиентским в пайплайне не жёсткая. Отсюда вторая находка.
Инженерное решение.
Просить у модели строго типизированный структурированный вывод: JSON с полями next_question, reference_answer, scoring_criteria. Через function calling или constrained decoding, не через «верни ответ в формате...».
Валидация схемы на выходе модели, например pydantic. Если структура не распарсилась, это ошибка шага, а не повод отправить сырой текст.
Явный контракт исходящего: в send_message передаётся только next_question. Остальные поля функции отправки физически недоступны. Разные слои, разные структуры данных.
Финальный guard перед отправкой: проверка, что исходящий текст не содержит служебных полей по сигнатуре, длине и маркерам. Дешёвая страховка от регрессий.
Находка 2. Изоляция сессий как зона риска
Статус: гипотеза. Чужих данных в своей сессии я не видела, сгенерированный текст из первой находки собран из моих ответов. Но первая находка ставит вопрос об изоляции ребром.
Если система генерирует контент за пользователя и способна донести его до исходящего сообщения, надо проверять, насколько жёстко разделены контексты кандидатов, идущих параллельно. При 130 000 интервью за несколько месяцев часть из них одновременны, и это критический контроль.
Механизм, который проверяется первым, называется cross-session leak: данные одной сессии попадают в промпт, память, результат инструмента или кэш другой. Возникает, когда контекст хранится в разделяемом объекте, переиспользуемом инстансе или общем буфере и не очищается по идентификатору сессии. В сентябре 2026 Check Point Research опубликовала разбор, где два разговора ChatGPT под разными аккаунтами получили скрытый канал связи через общий внутренний сервис, и в proof of concept модель достала данные из подключённой почты жертвы. Архитектурная слабость там та же: общий компонент между средами, которые должны были быть изолированы.
Классификация. OWASP LLM02 Sensitive Information Disclosure, в списке 2025 года эта категория поднялась с шестого места на второе. Последствие при наличии дефекта - персональные данные и ответы одного кандидата в диалоге другого.
Инженерное решение и как проверить.
Весь контекст диалога привязывается к session_id. Состояние сессии живёт в изолированном хранилище с ключом по сессии, не в разделяемом объекте процесса.
Явная инициализация и очистка контекста на границах сессии, без переиспользования буфера.
Тест на изоляцию: N параллельных сессий, в каждую подаётся уникальный маркированный секрет, автоматическая проверка, что маркер сессии A не появляется в выводе сессии B. Прогонять в CI при каждом изменении логики контекста.
На модельном слое stateless-вызовы: контекст передаётся явно на каждом шаге, сервер модели не держит состояние между запросами.
Находка 3. Переключение сценария без завершения предыдущего
Наблюдение. Интервью по позиции консультанта в стратегию SberAI дошло до вопроса про английский. В 15:11 я ответила. В 15:12, следующим сообщением, бот начал интервью по другой вакансии с нуля: «Получил Ваш отклик на позицию...». Ни «спасибо за интервью», ни подтверждения. Первый диалог оборвался, результат по нему не был зафиксирован явно.
Реконструкция причины. Событийная модель без управления состоянием сессии. Пришло событие «старт интервью по вакансии X», обработчик его подхватил, не проверив, что активна незавершённая сессия по вакансии Y. Нет гейта, который сопоставляет входящее событие с текущим состоянием диалога.
Типичная ошибка, когда сессия моделируется как поток сообщений без явной state machine, то есть без конечного автомата, где перечислены состояния и разрешённые переходы между ними. Нет состояний active, awaiting_answer, completed, нет правила перехода, есть только реакция на последнее событие.
Классификация. Управление состоянием диалога в мультисценарном агенте.
Последствие. Потеря результата первого интервью. Смешение контекстов двух вакансий с разными требованиями в оценке одного кандидата.
Инженерное решение.
Явная state machine сессии: состояния и разрешённые переходы. Старт новой сессии из состояния active запрещён без перехода через completed или suspended.
Очередь входящих событий вместо немедленной обработки: событие «новый отклик» при активной сессии встаёт в очередь, а не перебивает текущую.
Развилка на границе: при попытке старта новой сессии либо явная фиксация результата текущей, либо подтверждение приостановки. Решение записывается в состояние, а не остаётся неявным.
Изоляция контекстов вакансий: контекст сессии по вакансии X не должен быть виден оценке по вакансии Y даже при быстром переключении.
Находка 4. Решение вынесено раньше, чем состоялся заявленный этап
Наблюдение. По позиции Product Owner (MLOps) в 14:43 в чат hh.ru пришло приглашение пройти интервью с ГигаРекрутером, с формулировкой, что это ускорит рассмотрение. В 15:08 по той же вакансии пришёл отказ. Двадцать пять минут. Интервью не проводилось, ни одного вопроса по этой позиции бот не задал.
Реконструкция причины. Две несинхронизированные ветки процесса. Ветка A триггерится откликом и зовёт на интервью. Ветка B выносит решение по резюме. Кто именно принял решение в ветке B, снаружи не видно: это мог быть автоматический скоринг по формальным полям, а мог быть живой рекрутер, который не видел статус «приглашён на интервью». Для архитектуры разницы нет. Обе ветки работают независимо, и ни одна не проверяет состояние другой.
Значит, ветки не связаны общим статусом кандидата по вакансии. Нет объекта, где переход в «отказ» блокируется, пока обязательный этап «интервью» не в состоянии «завершено» или «пропущено по правилу».
Классификация. Согласованность бизнес-процесса и оркестрации. Не безопасность.
Последствие. Если интервью заявлено этапом, влияющим на решение, а решение выносится вне его, интервью не является механизмом оценки для части кандидатов. Открытый вопрос: по какой доле откликов решение принимается без обещанного этапа.
Инженерное решение.
Единый статусный объект «кандидат × вакансия» с явными этапами и гейтами. Переход в терминальное решение запрещён, пока обязательный этап не в терминальном состоянии.
Оркестратор процесса, сага или state machine на уровне заявки, вместо независимых обработчиков. Скоринг резюме - вход в процесс, не параллельная ветка с правом финального решения.
Если ранний отсев по резюме допустим по продуктовой логике, тогда приглашение на интервью не отправляется до прохождения этого отсева. Приглашение и отказ по одной вакансии в пределах минут - признак гонки, которую убирает единый статус.
Находка 5. Точки входа и обработка состояния
Наблюдение. Переходы по ссылкам-приглашениям 7, 8 и 9 сентября не поднимали сессию: команда /start принималась, интервью не запускалось. 9 сентября в 14:30 бот ответил «похоже, случилась небольшая техническая неполадка, попробуйте позже» и в ту же минуту запустил интервью. Вечером того же дня два /start по свежему приглашению остались без ответа. Это не только мой опыт: в феврале 2026 в открытом доступе описан случай, когда бот ответил на /start через четыре часа.
Реконструкция причины. Сбой инициализации сессии по deep link плюс отсутствие обработки этого сбоя как явного состояния. Возможные первопричины: истёкший или неверный токен из ссылки, отсутствие сессии на бэкенде под токен, таймаут инициализации, необработанное исключение в обработчике старта. Задержка в часы указывает на очередь или воркер, который не держит SLA и не имеет алертинга на переполнение.
Классификация. Доступность сервиса и наблюдаемость.
Последствие. Приглашённый кандидат не может начать и выпадает из воронки без следа. Без метрики успешности старта по приглашениям такие случаи не фиксируются: в аналитике это не «отказался», это отсутствие данных.
Инженерное решение.
Метрика «доля успешных стартов сессии по ссылке-приглашению», алерт на просадку.
Обработка сбоя старта как явного состояния с понятным ответом кандидату и путём восстановления, например перевыпуском ссылки, а не «попробуйте позже».
Идемпотентность старта: повторный переход по ссылке возобновляет сессию, а не создаёт конфликт состояний.
SLA на время отклика воркера, отдельный алертинг на очередь. Ответ через часы - это отказ обслуживания, даже если формально сообщение доставлено.
Сводка
Безопасность. Находка 1 - Improper Output Handling, подтверждённое наблюдение. Находка 2 - Sensitive Information Disclosure, гипотеза, требует проверки.
Оркестрация и надёжность. Находка 3 - управление состоянием диалога. Находка 4 - согласованность процесса. Находка 5 - доступность и наблюдаемость.
Находки 1 и 2 соотносятся с моделью угроз кибербезопасности ИИ, которую Сбер опубликовал в открытом доступе в июле 2026: во второй версии 37 угроз и 51 способ реализации, и модель прямо заявлена как применимая к генеративным, агентным и мультиагентным системам. То есть внутри компании есть документ, под который ложатся обе находки. Разрыв между темпом выката продукта и темпом харденинга - обычная ситуация для агентов, выведенных в прод быстро, и этот разбор показывает, как такой разрыв выглядит с точки зрения кандидата.
Типовые точки отказа диалоговых агентов
Все пять находок универсальны, они не специфичны для одного продукта. Если свести их к чек-листу проектирования:
Строгое разделение служебного и клиентского контента. Структурированный вывод модели, отбор полей, guard перед отправкой.
Изоляция состояния по session_id, stateless-вызовы модели, тест на межсессионную утечку в CI.
Явная state machine сессии вместо реакции на последнее событие.
Единый статус процесса с гейтами вместо параллельных веток с правом финального решения.
Наблюдаемость с первого дня: метрики старта, SLA воркеров, алертинг. Молчаливый отказ дороже явной ошибки.
Проверьте своего агента по этим пяти пунктам. Если хотя бы один из них закрыт договорённостями внутри команды, а не кодом, у вас та же архитектура, что описана выше, только пока без публичного разбора.
Контекст публикации
Находки я направила в доступный канал связи с командой до этой публикации. Разбор описывает поведение продукта на уровне механизмов и не содержит инструкций по эксплуатации. Полные логи по каждой находке с таймингами готова передать команде продукта.
Если вы строите диалоговых агентов и у вас есть свои наблюдения по этим классам дефектов, пишите в комментариях, соберём общую картину.
У вас похожая ситуация?
Расскажите, где в вашем отделе продаж теряются деньги. Разберём, что покажет аналитика именно вашей CRM
Обсудить задачу