Агент закончил, а Telegram лежит: очередь доставки в agent-hub на Rust
Когда агент уже закончил работу, а Telegram недоступен, повторять запрос к модели нельзя: это стоит токенов и может снова изменить файлы. Автор agent-hub на Rust разделил получение результата и его доставку. Финальный текст сначала пишется на диск, а отдельная задача отправляет его частями и повторяет после сбоя или перезапуска.
AI-обработка оригинала Habr AI; редакция Hamidun News
Знакомая ситуация: агент прочитал код, поправил файлы, проверил результат и написал отличный ответ. А в этот момент Telegram недоступен. Для агента работа закончена, для пользователя не произошло ничего. Запускать задачу заново не хочется: это время, токены и риск, что агент снова что-то изменит. Именно с этим столкнулся автор agent-hub, приложения на Rust, которое запускает AI-агентов локально и общается с ними через темы Telegram-группы.
Разделить результат и доставку
Главная идея простая: получение ответа и его отправка — два разных события. Когда ход агента успешно завершён, хаб сначала сохраняет финальный текст в локальный файл topics.results.json и ставит его в очередь, и только потом обращается к Telegram. Отдельная задача занимается отправкой и повторами. После перезапуска она читает состояние с диска и продолжает доставку без нового вызова модели.
В очередь попадает не вся переписка, а последовательные текстовые блоки после последнего отображаемого вызова инструмента. Вложения, промежуточные сообщения, вопросы и кнопки разрешений автоматически не повторяются.
Важная деталь: хаб хранит уже подготовленные части, а не исходный Markdown. Если после обновления приложения изменится преобразование разметки, границы сообщений останутся прежними, и сохранённый номер следующей части не поедет на другой кусок текста.
Как это переживает сбои
Цикл такой: найти готовую запись, зарезервировать её на 60 секунд и сохранить это на диск, отправить текущую часть, записать подтверждение, перейти к следующей. Резервирование нужно на случай, если процесс оборвётся посреди сетевого запроса: запись не останется занятой навсегда. Запрос к Telegram ограничен 20 секундами, отправка идёт не чаще одной части в секунду.
При временной ошибке паузы растут: 5, 15, 30, 60, 120, 300, 600 секунд. После восьми неудач подряд доставка останавливается до ручного повтора. Если Telegram сам просит подождать (RetryAfter), эта пауза хранится для очереди всей группы и не сокращается ни ручным повтором, ни перезапуском. Если Telegram отклонил HTML, хаб пробует отправить обычный текст, а если и он не прошёл, ждёт вмешательства человека.
Управлять очередью можно из темы: /last показывает последний сохранённый ответ без вызова модели, /outbox — ожидающие доставки с кнопками «Повторить» и «Удалить». В интерфейсе при ошибке чтения хранилища показывается «неизвестно», а не ноль, чтобы сбой диска не выглядел как пустая очередь.
Где гарантии заканчиваются
Автор честно не обещает доставку ровно один раз. Telegram мог принять сообщение, а подтверждение потерялось; или хаб не успел записать его на диск до остановки. Тогда часть уйдёт повторно. Поэтому в начале каждой части стоит ID хода и номер вроде «часть 2/3»: метка не убирает дубликат, но показывает, что это повтор, а не новый ответ.
Есть и жёсткие лимиты: до 50 ожидающих ответов и 8 МиБ в очереди, хранение до 7 дней, до 64 КиБ на один текст. Если очередь полна, старые записи не вытесняются, а новый ответ отправляется без автоповтора и с предупреждением. Файл создаётся с правами 0600, но в нём лежат ответы агента, так что о бэкапах стоит помнить.
Тесты шли на Linux с подменой Telegram и временным хранилищем: недоступная сеть, перезапуск после частичной отправки, потеря подтверждения, RetryAfter, ошибка HTML, переполнение, смена группы. Отключение питания не моделировали.
Что забрать себе
Паттерн универсален для любого агентного инструмента: сохраняйте результат до доставки, храните прогресс по частям, давайте повторам идентификаторы и не обещайте exactly-once там, где его нет. Это по сути маленький outbox-паттерн, знакомый по бэкенду, только для агентов, где повторный запуск дорог и небезопасен. Код открыт под MIT.
- 12 нояб. 2026 г.Claude in Chrome требует разрешать каждый клик на сайтах с категорией 3
- 12 нояб. 2026 г.Norwest собрал рекордный фонд на $4 млрд и ставит на агентов, голос и физический ИИ
- 12 нояб. 2026 г.AWS показала, как 100% точности поиска скрывают провал ИИ-агента
- 12 нояб. 2026 г.Garage Eight убрала чужие апрувы в 69 MR внутреннего сервиса с AI-ревью
Вопросы и ответы по материалу
Что известно по теме: разделить результат и доставку?
Главная идея простая: получение ответа и его отправка — два разных события. Когда ход агента успешно завершён, хаб сначала сохраняет финальный текст в локальный файл topics.results.json и ставит его в очередь, и только потом обращается к Telegram. Отдельная задача занимается отправкой и повторами. После перезапуска она читает состояние с диска и продолжает доставку без нового вызова модели. В очередь попадает не вся переписка, а последовательные текстовые блоки после последнего отображаемого вызова инструмента.
Что известно по теме: как это переживает сбои?
Цикл такой: найти готовую запись, зарезервировать её на 60 секунд и сохранить это на диск, отправить текущую часть, записать подтверждение, перейти к следующей. Резервирование нужно на случай, если процесс оборвётся посреди сетевого запроса: запись не останется занятой навсегда. Запрос к Telegram ограничен 20 секундами, отправка идёт не чаще одной части в секунду. При временной ошибке паузы растут: 5, 15, 30, 60, 120, 300, 600 секунд. После восьми неудач подряд доставка останавливается до ручного повтора.
Что известно по теме: где гарантии заканчиваются?
Автор честно не обещает доставку ровно один раз. Telegram мог принять сообщение, а подтверждение потерялось; или хаб не успел записать его на диск до остановки. Тогда часть уйдёт повторно. Поэтому в начале каждой части стоит ID хода и номер вроде «часть 2/3»: метка не убирает дубликат, но показывает, что это повтор, а не новый ответ. Есть и жёсткие лимиты: до 50 ожидающих ответов и 8 МиБ в очереди, хранение до 7 дней, до 64 КиБ на один текст.
Протестируйте новые LLM и мультимодальные модели в одном окне
Платформа Nomad AI (nomadnet.ai) даёт прямой доступ к Claude Opus 5.5, GPT-6, Gemini 3.1, DeepSeek и автономным агентам без VPN, зарубежных карт и зоопарка подписок.
Главное из мира ИИ — раз в неделю
7 ключевых событий недели, отобранных вручную. Без шума, репостов и пресс-релизов.
Готово! Проверьте почту — мы отправили подтверждение.