The Jerusalem PostRussian attack on Ukrainian city kills 12, a day after Trump eases diesel sanctions on MoscowPunchCross River shuts 20 unapproved schoolsESPN DeportesEl Atlético se complica y el Alavés le empata con un penaltiESPNSources: Bama TE Ford expected to play after surgery for broken armRTP Desporto"Foi uma graçola." Varandas responde ao primeiro-ministro com referência à corrupçãoInquirer6,000 openings up in Eastern Visayas job fairScreen RantCasting Transformers 8: 10 Actors Who Could Lead Michael Bay & Steven Spielberg's New MovieFootball ItaliaChivu: ‘Inter happy to see internationals in action, uncertainty over Parma’BBC NewsVerstappen beats Ferraris to Singapore poleABC NewsChrista Pike released from hospital following botched execution, attorneys sayCBS NewsMultiple people, including 2 children, killed in reported mass shooting in ErieБи-би-сиВ Запорожье 20 погибших в результате удара на следующий день после снятия санкций США с российского дизеля
The Daily Newsstand · Free, Always
Saturday, October 10, 2026

Контент‑завод в Telegram: как ИИ‑агенты ведут шесть площадок за одного человека

Translate

Я веду Telegram‑канал про ИИ и ещё пять площадок: Instagram, Facebook, Threads, YouTube и свой сайт. Раньше на один пост уходил час: найти новость, проверить цифры, написать текст, подобрать картинку и переделать его под каждую соцсеть. Полгода назад я собрал для этого «контент‑завод»: набор ИИ‑агентов, который живёт в обычной группе Telegram. Ниже рассказываю, как он устроен внутри, какие решения сработали и где остались слабые места. Все цифры взяты из логов и файлов состояния.

Схема в одном абзаце

Завод слушает новостные Telegram‑каналы. Каждую новость оценивает модель, и интересные приходят в тему «Идеи» с кнопками. Я нажимаю «Интересно» или надиктовываю голосом своё мнение. Писатель ищет первоисточники, пишет пост моим стилем, проверяет факты и присылает превью в тему «Посты». После «Опубликовать» пост уходит в канал, а для каждой соцсети и для сайта готовится своя версия текста.

Почему Telegram, а не веб‑панель

Мне не нужен ещё один интерфейс. Группа с темами уже даёт ленту, кнопки, голосовые сообщения и работу с телефона. Вся работа с заводом занимает несколько нажатий там, где я и так провожу день.

Один процесс и никакой базы данных

  • Всё работает в одном процессе на Python: сервис systemd с перезапуском при падении. Кода около 10,9 тысячи строк, из них писатель занимает 3,5 тысячи, разведчик новостей — 3,4 тысячи.

  • Внутри через asyncio.gather крутятся четыре задачи: фоновые циклы разведчика, обработчик событий Telethon, локальный HTTP‑сервер и догоняющий цикл каждые 20 секунд.

  • Разведчик и писатель делят одну пользовательскую сессию Telethon. Сначала это были два процесса с общей сессией, и Telegram регулярно рвал её ошибкой AuthKeyDuplicatedError. Объединение в один процесс эту ошибку убрало.

  • Кнопки принимает отдельный бот через Bot API: длинный опрос getUpdates, только callback_query.

  • Состояние хранится в JSON и JSONL: ждущие идеи, черновики, история решений, уже виденные новости. Запись атомарная: временный файл и затем os.replace. Состояние кросс‑постинга дополнительно защищено flock. После перезапуска ждущие идеи и посты восстанавливаются с диска.

Базу данных я не завёл намеренно. Состояние маленькое, писатель один, а файлы легко читать глазами, когда что‑то пошло не так.

Откуда берутся новости

Источники — 13 Telegram‑каналов. Их слушает events.NewMessage, без опроса по таймеру. Для RSS есть цикл раз в 5 минут, но сейчас список RSS пуст. Сообщения короче 20 символов отбрасываются сразу.

Одна и та же новость приходит из нескольких каналов, поэтому дубли отсекаются в два шага:

  1. точное совпадение: MD5 от нормализованного текста (нижний регистр, без пробелов по краям);

  2. нечёткое совпадение: difflib.SequenceMatcher(...).ratio() > 0.80 со всем, что пришло за 7 дней.

Ещё одна деталь: два канала часто публикуют одну новость с разницей в секунды. Пока первая копия ещё в обработке, вторая проходит проверку на дубль. От этой гонки спасает отдельный набор заголовков «в работе». Всего завод разобрал 4299 новостей.

Оценка новостей: модель вместо весов

Каждую новость модель оценивает числом от 0 до 100. В промпт она получает 15 последних новостей, которые я отметил «Интересно», и 15 последних, которые я пропустил. Пока моих решений меньше 20, всем ставится нейтральная оценка 50. От 70 баллов новость получает метку «🔥 Hot«, ниже 30 — молча пропускается.»

Эмбеддинги и веса слов не понадобились: двадцати‑тридцати моих собственных решений в промпте хватило. По истории: 236 новостей модель пропустила сама, 193 я отметил «Интересно», 13 пропустил вручную. Больше половины потока отсеивается до того, как я его вижу.

Карточка новости в теме «Идеи»: краткий пересказ, источник и оценка

Карточка новости в теме «Идеи»: краткий пересказ, источник и оценка

От идеи к черновику

У карточки три кнопки: «Интересно», «Skip» и «Block» для источника. Дальше я выбираю канал и режим: «Как есть» или «С комментарием». Комментарий удобнее надиктовать голосом. Голос распознаётся через OpenAI API, модель whisper-1 с явным русским языком. Последний шаг — выбор площадок галочками.

Выбор площадок для публикации кнопками

Выбор площадок для публикации кнопками

Писатель проходит цепочку: поиск источников, генерация, чистка, самопроверка, проверка фактов. На поиске у модели есть WebSearch и WebFetch плюс список доверенных и сомнительных доменов. Стиль задаёт файл с инструкцией для канала и файл с постоянными фактами обо мне. В промпт также попадают до двух «эталонных» постов, пять последних опубликованных и подборка образцов.

Как правки становятся правилами

Это главное, ради чего завод вообще стоило строить. Когда я нажимаю «Переписать» и надиктовываю правку, отдельный шаг разбирает её в формат «плохо / почему / хорошо» или отвечает SKIP, если правка разовая. Замечания о тоне попадают в файл тональных правок, замечания о структуре — в файл запрещённых приёмов. Кнопка «💎 Эталон» добавляет пост в образцы и записывает, что в нём удалось. Каждая правка целиком сохраняется в журнал, а общие для всех каналов правила лежат отдельно.

В результате одно и то же замечание не приходится повторять дважды: в следующий раз оно уже есть в промпте.

Проверка фактов предупреждает, а не исправляет

Из готового текста выписываются числа, даты, имена, цитаты и цены. Каждый пункт сверяется с найденными источниками или через поиск. Ответ — либо FACTS_OK, либо список расхождений.

Автоматически пост при этом не правится, и это сделано специально. Модель, которая «исправляет» факт, может внести новую ошибку, причём уже без следа. Поэтому я вижу предупреждение и решаю сам, а расхождение пишется в отдельный журнал. Слабое место я тоже знаю: если ответ проверки не удалось разобрать, пост проходит дальше без предупреждения.

Картинки

Первым делом берётся картинка из исходного поста. Скачивается она лениво, только после того как я одобрил идею: при 236 автоматических пропусках это заметная экономия. Если картинки нет, модель придумывает запрос для Pexels. При неудаче завод повторяет поиск лестницей всё более простых запросов. Недавно использованные фото запоминаются, чтобы они не повторялись в соседних постах.

Без картинки публикация заблокирована на всех площадках. Видео подгоняется через ffmpeg и ffprobe и проверяется на требования каждой площадки. Обложки с моим лицом делает отдельный агент‑дизайнер, с ним я тоже общаюсь в отдельной теме группы.

Тема «Дизайнер»: обложка поста и обсуждение правок

Тема «Дизайнер»: обложка поста и обсуждение правок

Свой текст для каждой площадки

У площадок разные лимиты: Telegram и Facebook — 4096 символов, Instagram — 2200, Threads и описание YouTube — 500. Сокращение под лимит устроено так:

  • цель — лимит минус 20 символов, с запасом;

  • две попытки, и каждая сокращает исходный текст, а не результат прошлой попытки. Иначе смысл деградирует, как у копии с копии;

  • хэштеги и ссылки сравниваются до и после, и потеря любой из них означает новую попытку;

  • в крайнем случае текст обрезается по пробелу с многоточием.

Публикация идёт через официальные API: Facebook Graph API v21.0 (видео уходит как Reels), Instagram Graph API v19.0 (Reels через загрузку файла rupload), Threads API v1.0 и YouTube Data API v3 с возобновляемой загрузкой Shorts. На сайт пост записывается строкой в Supabase сразу на двух языках. Английскую версию делает отдельный шаг за две попытки. Если перевод не удался, пост выходит только на русском, а у меня появляется кнопка «Перевести заново».

Тема «Посты»: публикация в канал, на сайт и в соцсети

Тема «Посты»: публикация в канал, на сайт и в соцсети

Двойное нажатие и падения

Нажатия кнопок обрабатываются строго по очереди. После успешной публикации пост удаляется из списка ожидающих, и повторное нажатие получает ответ «пост не найден». Черновики для площадок удаляются из памяти и с диска до отправки, а не после.

Отдельного ключа идемпотентности нет. Схема держится на том, что процесс один и обработка последовательная. Если когда‑нибудь появятся два обработчика, эту часть придётся переделать первой.

Модель: один агент на все шаги

Все обращения к модели идут в одного агента на Claude Code (Claude Opus), который сам работает как Telegram‑бот. Завод отправляет ему промпт файлом .txt с уникальным идентификатором. Ответ должен заканчиваться маркером [END:<id>], а если маркера нет, ответ принимается после 15 секунд тишины. Вызовы идут строго по одному через asyncio.Lock. Через этого агента проходят 16 разных шагов.

Плюс такой схемы в том, что у агента уже есть поиск по вебу и контекст проекта, и отдельная интеграция с API не нужна. Минус — скорость. Медианы по журналу вызовов:

  • оценка новости — 18 с;

  • поиск источников — 81 с;

  • генерация поста — 333 с (90-й перцентиль — 464 с);

  • проверка фактов — 44 с;

  • версия для соцсетей — 160 с.

Цифры за полгода

  • С 18 апреля по 1 октября 2026 года в Telegram вышло 83 поста в трёх каналах, из них 66 — в основном.

  • Завод разобрал 4299 новостей, больше половины из них модель отсеяла сама.

  • Машинное время на пост — около 8 минут, в основном генерация.

  • Моё время — прочитать превью, иногда надиктовать правку и нажать кнопку.

Что я бы сделал иначе

  • Проверку фактов при неразобранном ответе стоит закрывать, а не пропускать.

  • Нужен явный ключ идемпотентности на публикацию, не завязанный на однопоточность.

  • Дубли отсекаются только на входе. Две разные новости об одном событии из разных источников могут дать два похожих поста, и от этого сейчас защищает только просьба в промпте не повторять последние заголовки.

  • Вызовы модели идут строго по одному. Когда я одобряю несколько идей подряд, они выстраиваются в очередь на десятки минут.

Стек

Python и asyncio, Telethon, Telegram Bot API, Claude Code, OpenAI Whisper, Pexels API, Supabase, Meta Graph API, Threads API, YouTube Data API, ffmpeg.

View the original on Хабр →

KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.