Внутреннее устройство Cron

Подсистема cron обеспечивает выполнение запланированных задач — от простых одноразовых задержек до повторяющихся задач с cron-выражениями, включая внедрение функций и кроссплатформенную доставку.

Ключевые файлы

Файл Назначение
cron/jobs.py Модель задания, хранилище, атомарное чтение/запись в jobs.json
cron/scheduler.py Цикл планировщика — Определение просроченных заданий, выполнение, отслеживание повторений
инструменты/cronjob_tools.py Регистрация и обработка инструмента cronjob для моделей
шлюз/run.py Интеграция с шлюзом — тактирование cron в долгоиграющем цикле
hermes_cli/cron.py Подкоманды CLI hermes cron

Модель планирования

Поддерживается четыре формы расписания:

Формат Пример Поведение
Относительная задержка 30м, , Одноразовое, реализованное через указанный промежуток времени
Интервал каждые 2 часа, каждые 30 м Повторяющееся, реализуется через равные промежутки времени
Cron-выражение 0 9 * * * Стандартный синтаксис cron из 5 полей (минута, час, день, месяц, день недели)
ISO-метка времени 2025-01-15T09:00:00 Одноразовое, реализовано в точное время

Интерфейс для моделей представляет собой единый инструмент «cronjob» с операциями в стиле действий: «создать», «список», «обновить», «пауза», «возобновить», «запустить», «удалить».

Хранение заданий

Задание хранения в ~/.hermes/cron/jobs.json с семантикой атомарной записи (запись во временный файл, затем переименование). каждая запись задания содержит:

{
  "id": "a1b2c3d4e5f6",
  "name": "Ежедневный брифинг",
  "prompt": "Обобщи сегодняшние новости об ИИ и раунды финансирования",
  "schedule": {
    "kind": "cron",
    "expr": "0 9 * * *",
    "display": "0 9 * * *"
  },
  "skills": ["ai-funding-daily-report"],
  "deliver": "telegram:-1001234567890",
  "repeat": {
    "times": null,
    "completed": 42
  },
  "state": "scheduled",
  "enabled": true,
  "next_run_at": "2025-01-16T09:00:00Z",
  "last_run_at": "2025-01-15T09:00:00Z",
  "last_status": "ok",
  "created_at": "2025-01-01T00:00:00Z",
  "model": null,
  "provider": null,
  "script": null
}

Состояния жизненного цикла задания

Состояние Значение
запланировано Активно, срабатывает в следующее запланированное время
приостановлено Приостановлено — не будет производиться до восстановления
завершен Исчерпан лимит повторений или одноразовое задание уже сработало
бег Выполняется в данный момент (переходное состояние)

Обратная связь

В старых заданиях может быть одно поле «навыков» вместо массива «навыков». Планировщик нормализует это при включении — одиночный skill преобразуется в skills: [skill].

Среда выполнения планировщика

Цикл тактов

Планировщик работает периодически так (по умолчанию: женщины 60 секунд):

tick()
  1. Захватить блокировку планировщика (предотвращает перекрытие тактов)
  2. Загрузить все задания из jobs.json
  3. Отфильтровать просроченные задания (next_run <= now И state == "scheduled")
  4. Для каждого просроченного задания:
     a. Установить состояние "running"
     b. Создать новый сеанс AIAgent (без истории разговора)
     c. Загрузить прикрепленные навыки по порядку (внедряются как сообщения пользователя)
     d. Выполнить запрос задания через агента
     e. Доставить ответ в настроенный целевой канал
     f. Обновить run_count, вычислить next_run
     g. Если лимит повторений исчерпан → state = "completed"
     h. Иначе → state = "scheduled"
  5. Записать обновленные задания обратно в jobs.json
  6. Освободить блокировку планировщика

Интеграция с шлюзом

В режиме шлюза планировщик работает в выделенном фоновом потоке (_start_cron_ticker в gateway/run.py), который вызывает scheduler.tick() в течение 60 секунд параллельно с обработкой сообщений.

В режиме CLI задания cron срабатывают только при выполнении команды hermes cron или во время активных сеансов CLI.

Изоляция нового сеанса

Результаты каждого задания cron в совершенно новом сеансе агента:

Задания с навыками

Задание cron может прикрепить один или несколько навыков через поле skills. Во время выполнения:

  1. Навыки загружаются в указанном порядке.
  2. Содержимое SKILL.md, каждый навык внедряется как контекст.
  3. Запрос задания включается в качестве инструкции задачи.
  4. Агент обрабатывает объединенные контекстные функции + запрос.

Это позволяет повторно использовать рабочие процессы, протестированные рабочие процессы, без добавления полных инструкций в запрос cron. Например:

Создать ежедневный отчет о финансировании → прикрепить навык "ai-funding-daily-report"

Задания с поддержкой скриптов

Задания также могут прикрепить Python-скрипт через поле script. Скрипт до каждого шага агента, и его стандартный вывод включается в запрос как контекст. Это позволяет реализовать шаблоны сбора данных и обнаружения изменений:

# ~/.hermes/scripts/check_competitors.py
import requests, json
# Получить примечания к релизам конкурентов, сравнить с последним запуском
# Вывести сводку в stdout — агент анализирует и сообщает

Тайм-аут скрипта по умолчанию составляет 120 секунд. _get_script_timeout() устанавливает лимит через цепочку из трех уровней:

  1. Переопределение на уровне модуля_SCRIPT_TIMEOUT (для тестов/подмены). Используется только тогда, когда значения различаются по умолчанию.
  2. Переменная окруженияHERMES_CRON_SCRIPT_TIMEOUT
  3. Конфигурацияcron.script_timeout_секунды в config.yaml (читается через load_config())
  4. По умолчанию — 120 секунд.

Восстановление провайдера

run_job() передает настроенным пользователем резервные провайдеры и пул учетных данных в экземпляре AIAgent:

Это повторяет поведение шлюза — без этого агенты cron не смогли бы восстановиться после отключения скорости.

Модель доставки

Результаты заданий cron могут быть выставлены на любую уязвимую платформу:

Цель Синтаксис Пример
Исходный чат происхождение Доставить в чат, где было создано задание
Локальный файл местный Сохранить в ~/.hermes/cron/output/
Телеграмма telegram или telegram:<chat_id> телеграмма:-1001234567890
Раздор discord или discord:#channel discord:#engineering
слабый слаба Добавить на домашний канал Slack
WhatsApp WhatsApp Добавить в WhatsApp
Сигнал сигнал Доставить в Сигнал
Матрица матрица Доставить во вторую комнату Матрица
Самое важное самое важное Доставить в Mattermost
Электронная почта электронная почта Доставить по электронной почте
СМС смс Доставить по SMS
Домашний помощник домашний помощник Доставить в разговор HA
ДинТок дингтолк Доставить в DingTalk
Фейшу фейшу Доставить в Фейшу
ВеКом веком Доставить в WeCom
Вэйсинь вэйсинь Добавить в Weixin (WeChat)
Синие пузыри голубые пузыри Добавить в iMessage через BlueBubbles
QQ-бот qqbot Доставить в QQ (Tencent) через Официальный API v2

Для темы Telegram воспользуйтесь форматом telegram:<chat_id>:<thread_id> (например, telegram:-1001234567890:17585).

Обработка ответа

По умолчанию (cron.wrap_response: true) cron доставки оборачиваются: - Заголовком, идентифицирующим имя задания и должность. - Нижним колонтитулом, отмечающим, что агент не может видеть представленное сообщение в разговоре.

Префикс [SILENT] в ответе cron полностью отключает доставку — полезен для заданий, которым нужно только записывать данные в файлы или выполнять сложные эффекты.

Сеанс изоляции

Доставки cron НЕ зеркалируются в истории разговора сеанса шлюза. Они существуют только в собственном сеансе задания cron. Это собственное нарушение чередования сообщений в разговоре целевого чата.

Защита от рекурсии

В сеансах запущенных cron набор инструментов cronjob отключается. Это собственное: - Создание новых задач cron запланированным заданием - Рекурсивное планирование, которое может привести к взрывному использованию токенов - Случайное изменение расписания заданий из самого задания

Блокировка

План использует межпроцессную блокировку файловой системы (fcntl.flock в Unix, msvcrt.locking в Windows) для предотвращения выполнения одного и того же пакета просроченных задач, которые перехватывают тактами — даже между внутрипроцессным тактовым генератором шлюза и вызовом Hermes cron / ручным tick(). Если блок поставки не может быть получен, tick() мгновенно возвращает 0.

Интерфейс командной строки

CLI hermes cron обеспечивает прямое управление заданиями:

hermes cron list                    # Показать все задания
hermes cron create                  # Интерактивное создание задания (псевдоним: add)
hermes cron edit <job_id>           # Редактировать конфигурацию задания
hermes cron pause <job_id>          # Приостановить выполняющееся задание
hermes cron resume <job_id>         # Возобновить приостановленное задание
hermes cron run <job_id>            # Запустить немедленное выполнение
hermes cron remove <job_id>         # Удалить задание

Связанная документация