Семь агентов: как это устроено внутри
Штатное расписание отвечает на вопрос «кто». Эта страница отвечает на вопрос «как» — и на второй, который задают сразу за ним: почему выпущенному ими тексту можно верить. Разбор по четырём осям: оркестрация и расписание, выбор моделей под ограничения контура, антигаллюцинаторный контур, себестоимость и след.
Оговорка, с которой стоит начать
Репозитории закрыты, публичных endpoint'ов у агентов нет — это решение владельца, а не отсутствие объектов. Поэтому ниже нет ни одной ссылки на код, и всё, что здесь есть, — решения и их основания: что выбрано, из чего выбиралось, чем это кончилось и во сколько обошлось. Проверяется такое одним способом — разговором, в котором открывается история коммитов. Числа на странице взяты из разборов операций министерства, а не из общих соображений.
1. Состав: кто чем занят
Семь автоматизаций, у каждой один предмет ведения и отдельная страница с описанием стоящей за ней службы. Ни одна не «умеет всё» — это архитектурное решение, а не стадия развития: агент широкого назначения отказывает целиком, а узкий — только своим куском.
| Агент | Что делает | Состояние |
|---|---|---|
| Аргус Разведка | Агентурная сеть в поисковой выдаче: ежедневный сбор сигналов из Яндекс.Поиска и Саджеста, скоринг ниш по трём осям (frontrun / community / content_demand), еженедельные снапшоты и сводки для портфельной стратегии порталов. | в проде |
| Геральд Инфооперации | Gap-анализ контента обслуживаемых площадок: находит дыры в освещении тем, предлагает планы публикаций и приносит черновики. Публикует не он — генерация всегда остаётся черновиком до решения человека. | формируется |
| Гермес Спецсвязь | Reverse-pull доставка уведомлений в Telegram из-под блокировок: серверные сервисы кладут донесения в очередь на публичном endpoint, доверенный вендор забирает и форвардит в канал спецсвязи. | в проде |
| Альфред Аппарат | Декларативный регламент подъёма служб: каждый обслуживаемый проект описывает своё расписание в scheduler.yaml, Альфред читает его и дёргает нужные службы через cron, GitHub Actions или Portainer-триггеры. | в проде |
| Нестор Аналитика | Ежедневные хроники для Дзен-канала: Selector отбирает повестку, Writer пишет, Critic разбирает выпуск на факты и сверяет каждый с Яндекс.Поиском, Audit фиксирует след. Недоверенные факты блокируются до правки. | в проде |
| Винсент Спецпродукция | Изготовление обложек по REST: шаблоны на HTML+CSS, рендер через headless Chromium, выдача PNG. Обслуживает Дзен-выпуски Нестора и любые SMM-каналы министерства. | в проде |
| Майкрофт Кадры | Реестр штата собирается обходом личных дел, а не ведётся руками: перекличка читает карточку в каждом деле и сводит её с реестром. Ежедневные донесения об изменениях, разбор ходатайств с записанным исходом у каждого, еженедельная аттестация всех дел и сторож, поднимающий тревогу на двух пропущенных тактах. | в проде |
2. Оркестрация: расписание принадлежит проекту, а не планировщику
Планировщик не хранит списка задач. Каждый обслуживаемый проект описывает
собственное расписание файлом scheduler.yaml у себя в
репозитории, а планировщик читает эти файлы и дёргает службы — через cron,
GitHub Actions или триггеры Portainer, смотря где живёт исполнитель.
Почему так. Расписание — свойство проекта, а не планировщика: при централизованном списке правка расписания требует захода в чужой репозиторий, и рано или поздно список расходится с тем, что проекты делают на самом деле. Декларативная раскладка снимает целый класс вопросов «почему это не запустилось»: ответ всегда в том же дереве, где лежит код задачи.
Чем это оплачено. Планировщик обязан переживать неполные и сломанные декларации: файл с ошибкой не должен ронять весь такт. Наблюдение за самими агентами устроено так же — единица министерства обязана называть себя в ответе на запрос состояния, и сторож поднимает тревогу на двух пропущенных тактах подряд, а не на первом: одиночный пропуск в сети шумит, два подряд — уже событие.
3. Выбор моделей: две модели дороже одной и дешевле ошибки
Разные модели на письме и на проверке
Writer — GigaChat-Max, Critic — YandexGPT с Яндекс.Поиском в роли независимого источника истины. Это не «на всякий случай»: первая итерация была single-pass, один генератор писал и сам себя вычитывал, и стабильно около 15 % выпусков уходили с искажениями — выдуманные точные числа, искажённые имена собственные, непереведённые фрагменты.
Модель себя не проверяет. Она перечитывает собственный вывод тем же аппаратом, которым его породила, и уверенно подтверждает выдуманное. Проверяющая ступень обязана быть другой моделью и обязана ходить в другой источник — в поиск, а не в собственную память. Цена решения названа прямо: удвоение задержки и удвоение стоимости. Качество после него перешло порог «можно публиковать без редактора».
Тир под задачу, а не «самая умная везде»
Дорогая модель ставится туда, где ошибка дорого стоит: разбор фактов, вычитка, решение о выпуске. Механика — отбор источников, классификация, однотипные короткие операции — идёт на дешёвой. Прежде чем поднимать класс модели, поднимается усилие на текущей: это чаще правильный ответ на «получается хуже, чем нужно», чем смена тира.
Ограничения контура заданы с первого дня
Часть внешних сервисов недоступна с российских серверов, часть — риск отключения. Отсюда три решения, принятые до первой строки кода, а не после первого отказа:
- Российский стек на сервере. GigaChat-Max и YandexGPT с обвязкой Яндекс.Поиска — на серверной стороне. Внешние модели вызываются только из внутреннего контура, никогда из production-VPS.
- Российское объектное хранилище вместо зарубежного CDN под prerender-статику.
- Reverse-pull вместо прямых вызовов. Telegram API недоступен с RU-хостера, поэтому серверные службы кладут донесения в очередь на собственном endpoint, а доверенный вендор во внутреннем контуре забирает очередь и форвардит. Уведомления переживают блокировку, потому что через неё никто не ходит.
Отказ модели — это успешный ответ, а не ошибка
Ловушка, на которой ломается обвязка, написанная «по коду возврата»: отказ приходит успешным ответом с признаком отказа внутри, транспорт при этом отработал штатно. Скрипт, проверяющий только код ответа, примет отказ за выполненную работу и положит в очередь пустоту. Поэтому у каждого вызова читается признак результата, а не статус соединения, и на отказ заведена явная ветка: либо запасной исполнитель, либо остановка с сигналом человеку. Автоматизация без обработанного отказа в расписание не ставится.
4. Антигаллюцинаторный контур
Главная беда LLM в новостной и справочной нише — не плохой слог, а уверенно выдуманное точное число. Контур из пяти ступеней, каждая отказуема отдельно:
- Selector отбирает повестку и умеет отказаться: если операционных тем в потоке меньше трёх, выпуск помечается маркером тонкого потока и не собирается вовсе. Ежедневность не является основанием выпускать пустое.
- Writer пишет черновик строго по отобранным источникам — не «по теме», а по конкретному набору материалов.
- Critic разбирает черновик на отдельные утверждения и верифицирует каждое отдельным запросом к поиску. Утверждения без достаточного подтверждения помечаются к блокировке — не к смягчению формулировки, а к блокировке.
- Auto-reprompt: при срабатывании критика Writer переписывает проблемный фрагмент. После двух неуспешных попыток вопрос уходит человеку — счётчик обязателен, иначе пара «писатель — критик» зацикливается на спорном факте.
- Audit фиксирует след (см. ниже). Публикует по-прежнему человек: генерация остаётся черновиком, пока её не подписали.
Тот же принцип действует и вне выпусков: у справочных порталов заведены картотеки фактов с валидаторами — в одном из них 87 файлов фактов, сверяемых с внешним API, и каждое расхождение оформляется протоколом, а не правится молча. У каждого утверждения помечен уровень источника: публикация издателя, фан-вики и личное наблюдение не смешиваются, и новые числа берутся только из первого.
5. Audit-JSON: след, который можно пройти заново
По каждому выпуску кладётся append-only запись: черновик → перечень утверждений → вердикт по каждому → ссылки-доказательства. Это даёт три вещи, ради которых он и заведён:
- Воспроизводимость. Спор «откуда взялось это число» решается не памятью, а записью: видно, что утверждал писатель, что нашёл критик и на чём основан вердикт.
- Эмпирику для правки промптов. Промпты правятся по накопленным отбраковкам, а не по впечатлению от последнего выпуска.
- Отделение отказа от поломки. Маркер в аудите отвечает, выпуск не собрался потому что нечего было выпускать или потому что служба упала. Снаружи эти два состояния неразличимы, и без маркера первое годами читается как второе.
6. Себестоимость и время
| Величина | Значение | Что в неё входит |
|---|---|---|
| Себестоимость выпуска | до 25 ₽ | оба вызова LLM, поисковые квоты фактчека, рендер обложки |
| Полный цикл генерации | ~2—3 минуты | от триггера до готового черновика в очереди |
| Страховочная вычитка | ~30 секунд | режим рецензии поверх готового выпуска |
| Запасная сборка выпуска | ~2 мин 44 с | режим, в котором страховка сама пишет выпуск из тех же источников |
Число «до 25 ₽» полезно не само по себе, а тем, что делает разговор об экономике конкретным: при работающей дистрибуции цена контента перестаёт быть ограничением, и узким местом становится не генерация, а доставка. Это вывод не из рассуждения, а из закрытого эксперимента — операция «ПОЛИГОН», где генерация работала, а дистрибуции не было, и потому не сработало ничего.
7. Двухрежимная страховка: рецензия и запасной писатель
Поверх основного конвейера стоит отдельный слой, запускаемый по расписанию через четверть часа после генератора. У него два режима, и второй важнее:
- Рецензия — генератор отработал: страховка вычитывает выпуск как выпускающий редактор и кладёт улучшенный вариант в очередь черновиком.
- Запасной писатель — генератор отказался (маркер пропуска в аудите), но источники собраны: страховка собирает резервный выпуск из тех же источников и помечает его как резервный. В очередь каждый день ложится хотя бы черновик, и ни один из них не публикуется без подписи.
Контракт вывода стандартизирован маркерами секций, обёртка разбирает их и раскладывает по путям; повторный запуск идемпотентен по существующим файлам. Это скучная часть, и она же — та самая, без которой ночной запуск превращается в утреннюю ручную работу.
Что из этого переносимо
- Разные модели на письме и на проверке, с разными источниками истины. Единственный слой, который реально снимает выдуманные числа.
- Право отказаться у первой же ступени. Ежедневность — не основание выпускать пустое.
- Счётчик попыток у auto-reprompt. Без него пара «писатель — критик» зацикливается.
- Признак результата вместо кода возврата. Отказ модели приходит успешным ответом.
- Append-only аудит на каждый выпуск. Отличает «нечего было выпускать» от «служба упала».
- Подпись человека на выходе. Ни один агент министерства не публикует сам.
Чего на этой странице нет и почему
- Ссылок на репозитории и на код — они закрыты решением владельца. Здесь только решения и основания.
- Публичных endpoint'ов агентов — их нет: службы работают во внутреннем контуре и наружу не смотрят.
- Имён обслуживаемых объектов — часть под грифом, часть под NDA.
- Цифр трафика и индексации — на сегодня они не замерены, а незамеренное здесь не приводится.