Планировщик задач (Cron)

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

Что cron умеет сейчас

Задачи Cron могут:

Всё это доступно самому Hermes через инструмент cronjob, так что вы можете создавать, приостанавливать, редактировать и удалять задачи, просто спросив на естественном языке — CLI не требуется.:::предупреждение Сессии, запущенные через cron, не могут рекурсивно создавать новые задачи cron. Hermes отключает инструменты управления cron внутри cron-выполнений, чтобы предотвратить бесконечные циклы планирования.

Создание запланированных задач

В чате с помощью /cron

/cron add 30m "Напомни мне проверить сборку"
/cron add "every 2h" "Проверить статус сервера"
/cron add "every 1h" "Суммировать новые элементы фида" --skill blogwatcher
/cron add "every 1h" "Использовать оба навыка и объединить результат" --skill blogwatcher --skill maps

Из автономного CLI

hermes cron create "every 2h" "Проверить статус сервера"
hermes cron create "every 1h" "Суммировать новые элементы фида" --skill blogwatcher
hermes cron create "every 1h" "Использовать оба навыка и объединить результат" \
  --skill blogwatcher \
  --skill maps \
  --name "Комбо навыков"

Через диалог

Просто спросите Гермеса:

Каждое утро в 9 утра проверяй Hacker News на новости об ИИ и присылай мне сводку в Telegram.

Hermes внутренне использует единый инструмент cronjob.

Cron-задачи с поддержкой функций

Задача Cron может загрузить одно или несколько задач перед выполнением.

один навык

cronjob(
    action="create",
    skill="blogwatcher",
    prompt="Проверь настроенные фиды и суммируй всё новое.",
    schedule="0 9 * * *",
    name="Утренние фиды",
)

Несколько навыков

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

cronjob(
    action="create",
    skills=["blogwatcher", "maps"],
    prompt="Найди новые локальные события и интересные места поблизости, затем объедини их в одну краткую сводку.",
    schedule="every 6h",
    name="Локальная сводка",
)

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

Запуск задачи внутри каталога проекта

Задачи Cron выполняются отдельно из любой репозитории — не загружаются AGENTS.md, CLAUDE.md или .cursorrules, инструменты терминала/файлов/выполнения кода работают из тех рабочих каталогов, в которых был запущен шлюз. Передайте --workdir (CLI) или workdir= (инструмент вызова), чтобы изменить это:

# Автономный CLI (расписание и промпт позиционные)
hermes cron create "every 1d at 09:00" \
  "Проверить открытые PR, суммировать состояние CI и опубликовать в #eng" \
  --workdir /home/me/projects/acme
# Из чата, через инструмент cronjob
cronjob(
    action="create",
    schedule="every 1d at 09:00",
    workdir="/home/me/projects/acme",
    prompt="Проверить открытые PR, суммировать состояние CI и опубликовать в #eng",
)

Когда установлен workdir:

Редактирование задачи

Вам не нужно удалять и пересоздавать задачи, чтобы просто изменить их.

Чат

/cron edit <job_id> --schedule "every 4h"
/cron edit <job_id> --prompt "Использовать пересмотренную задачу"
/cron edit <job_id> --skill blogwatcher --skill maps
/cron edit <job_id> --remove-skill blogwatcher
/cron edit <job_id> --clear-skills

Автономный CLI

hermes cron edit <job_id> --schedule "every 4h"
hermes cron edit <job_id> --prompt "Использовать пересмотренную задачу"
hermes cron edit <job_id> --skill blogwatcher --skill maps
hermes cron edit <job_id> --add-skill maps
hermes cron edit <job_id> --remove-skill blogwatcher
hermes cron edit <job_id> --clear-skills

Примечания:

-повторный --skill заменяет прикреплённый список функций задач - --add-skill добавлен к существующей списку, не заменяя его - --remove-skill основные прикреплённые навыки - --clear-skills восстановление всех прикреплённых навыков

Действия жизненного цикла

Задачи Cron теперь имеют более полный жизненный цикл, чем просто создание/удаление.

Чат

/cron list
/cron pause <job_id>
/cron resume <job_id>
/cron run <job_id>
/cron remove <job_id>

Автономный CLI

hermes cron list
hermes cron pause <job_id>
hermes cron resume <job_id>
hermes cron run <job_id>
hermes cron remove <job_id>
hermes cron status
hermes cron tick

Что они делают:

Как это работает

Выполнение cron обрабатывается демоном шлюза. Шлюз тикает планировщик менеджеров в течение 60 секунд, запуская все бессмысленное выполнение задач в изолированных сеансах агента.

hermes gateway install     # Установить как пользовательский сервис
sudo hermes gateway install --system   # Linux: системный сервис для серверов
hermes gateway             # Или запустить в фореграунде

hermes cron list
hermes cron status

Поведение планировщика шлюза

В каждом случае, как в Гермесе:

  1. Загрузите задачу из ~/.hermes/cron/jobs.json
  2. сначала next_run_at относительно текущего времени
  3. запускает новую сессию AIAgent для каждой подлежащей выполнению задачи.
  4. опционально внедряет один или несколько прикреплённых навыков в эту свежую сессию.
  5. выполнить просьбу завершить
  6. доставляет лучший ответ
  7. обновляет метаданные выполнения и следит за запланированным временем.

Файловая блокировка ~/.hermes/cron/.tick.lock является своеобразным перекрытием тиков планировщика, чтобы одна и та же задача партии не выполнялась дважды.

Варианты доставки

При планировании задач вы указываете, куда направить вывод:

Опция Описание Пример
"происхождение" Обратно туда, где была создана проблема По умолчанию на платформах обмена сообщениями
"местный" Сохранить только в локальных файлах (~/.hermes/cron/output/) По умолчанию в CLI
"телеграмма" Домашний канал Telegram Использует TELEGRAM_HOME_CHANNEL
"телеграмма:123456" Конкретный чат Telegram по ID Прямая доставка
"телеграмма:-100123:17585" Конкретная тема Telegram Формат chat_id:thread_id
"раздор" Домашний канал Discord Использует DISCORD_HOME_CHANNEL
"discord:#engineering" Конкретный канал Discord По имени канал
"слаба" Домашний канал Slack
"WhatsApp" Домашний WhatsApp
"сигнал" Сигнал
"матрица" Домашняя комната Матрица
"самое важное" Домашний канал Mattermost
"электронная почта" Электронная почта
"смс" СМС через Twilio
"домашний помощник" Домашний помощник
"Динтолк" ДинТок
"фейшу" Фейшу/Жаворонок
"Веком" ВеКом
"Вэйсинь" Вэйсинь (WeChat)
"голубые пузыри" BlueBubbles (iMessage)
"qqbot" QQ-бот (Tencent QQ)
"все" Разослать всем подключенным домашним друзьям Разрешается в момент выполнения
"телеграмма,дискорд" Разослать в конкретный набор каналов Список через запятую
"происхождение,все" Доставить в исходный чат плюс все остальные подключенные каналы Комбинируйте любые токены

Окончательный ответ агента приходит автоматически. Вам не нужно вводить send_message в cron-prompte.

Маршрутизация намерений (все)

all Позволяет отправлять одну задачу cron во все настроенные каналы обмена сообщениями, не перечисляя их по имени. Он разрешается в момент выполнения, поэтому задача, созданная для подключения Telegram, захватывает Telegram в следующий раз после установки TELEGRAM_HOME_CHANNEL.

Семантика: все расширяется до каждой платформы с настроенным внешним каналом. Ноль — это нормально; Задача просто не создает цели доставки и регистрируется как сбой доставки вышестоящим компонентом.

все комбинируется с явными властями. origin,all доставляет в исходный чат плюс каждый другой подключённый домашний канал, дедулицируя по (platform,chat_id, thread_id).

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

По умолчанию доставляемый cron-вывод оборачивается в заголовок и нижний колонтитул, чтобы получатель знал, что это готово для запланированной задачи:

Ответ Cronjob: Утренние фиды
-------------

<вывод агента>

Примечание: Агент не видит это сообщение и поэтому не может на него ответить.

Чтобы получить сырой вывод агента без обёртки, установите cron.wrap_response в false:

# ~/.hermes/config.yaml
cron:
  wrap_response: false

Тихая подавленность

Если окончательный ответ агента начинается с [SILENT], доставка полностью блокируется. Вывод всё равно выполняется локально для аудита (в ~/.hermes/cron/output/), но сообщение не направлено на доставку.

Это полезно для мониторинга задач, которые следует сообщать только о проблемах:

Проверь, работает ли nginx. Если всё в порядке, ответь только [SILENT].
В противном случае сообщи о проблеме.

Неудачные задачи всегда выполняются независимо от маркера [SILENT] — только успешные выполнения могут быть замолчаны.

Тайм-аут скрипта

Скрипты первого запуска (прикреплённые через параметр script) имеют тайм-аут по умолчанию 120 секунд. Если вашим скриптам нужно больше времени — например, для включения рандомизированных задержек, чтобы избежать ботоподобных паттернов — вы можете увеличить его:

# ~/.hermes/config.yaml
cron:
  script_timeout_seconds: 300   # 5 минут

Или установите переменную среду HERMES_CRON_SCRIPT_TIMEOUT. Порядок разрешения: переменная окружения → config.yaml → значение по умолчанию 120 с.

Режим без агента (только скрипты)

Для повторяющихся задач, не требующих рассуждений LLM — классические сторожевые сигналы, оповещения о диске/памяти, пульс, CI-пинги — передайте no_agent=True при создании. Планировщик запускает ваш скрипт по расписанию и выдает его стандартный вывод напрямую, полностью минуя агента:

hermes cron create "every 5m" \
  --no-agent \
  --script memory-watchdog.sh \
  --deliver telegram \
  --name "memory-watchdog"

Семантика:

Файлы .sh / .bash выполняются под /bin/bash; всё остальное — под текущим интерпретатором Python (sys.executable). Скрипты должны находиться в ~/.hermes/scripts/ (то же самое правило работает и для шлюза во время запуска скриптов).

Агент настраивает их для вас

Схема инструмента cronjob предоставляет no_agent напрямую Hermes, так что вы можете описать сторожевого пса в чате и дать агенту его настройку:

Пингуй меня в Telegram, если RAM превышает 85%, каждые 5 минут.

Hermes записывает скрипт проверки в ~/.hermes/scripts/ через write_file, а затем вызывает:

cronjob(action="create", schedule="every 5m",
        script="memory-watchdog.sh", no_agent=True,
        deliver="telegram", name="memory-watchdog")

Он автоматически выбирает no_agent=True, когда критические сообщения полностью определены скриптом (сторожевые псы, пороговые оповещения, пульс). Этот же инструмент также позволяет агенту приостанавливать, возобновлять, сохранять и удалять задачи — так что весь жизненный цикл управляется через чат без необходимости касаться CLI.

Смотрите руководство Cron-задачи только со скриптами с различными примерами.

Цепочки задач с context_from

Задачи Cron выполняются в изолированных сеансах без памяти о предыдущих запусках. Но иногда выводят одну задачу — это именно то, что нужно вот эту задачу. Параметр context_from автоматически устанавливает это соединение — подсказка задачи B получает последний вывод задачи A, добавленный в качестве контекста во время выполнения.

# Задача 1: Сбор сырых данных
cronjob(
    action="create",
    prompt="Получи топ-10 AI/ML историй с Hacker News. Сохрани их в ~/.hermes/data/briefs/raw.md в формате markdown с заголовком, URL и оценкой.",
    schedule="0 7 * * *",
    name="Сборщик новостей AI",
)

# Задача 2: Триаж — получает вывод задачи 1 как контекст
# Получите ID задачи 1 через: cronjob(action="list")
cronjob(
    action="create",
    prompt="Прочитай ~/.hermes/data/briefs/raw.md. Оцени каждую историю от 1 до 10 по потенциалу вовлечения и новизне. Выведи топ-5 в ~/.hermes/data/briefs/ranked.md.",
    schedule="30 7 * * *",
    context_from="<job1_id>",
    name="Триаж новостей AI",
)

# Задача 3: Отправка — получает вывод задачи 2 как контекст
cronjob(
    action="create",
    prompt="Прочитай ~/.hermes/data/briefs/ranked.md. Напиши 3 черновика твитов (зацепка + тело + хэштеги). Доставь в telegram:7976161601.",
    schedule="0 8 * * *",
    context_from="<job2_id>",
    name="Дайджест новостей AI",
)

Как это работает:

Что принимает context_from:

Формат Пример
Один ID задачи (строка) context_from="a1b2c3d4"
Несколько ID задач (список) context_from=["job_a", "job_b"]

Выводы объединяются в порядке перечисления.

Когда использовать:

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

Задачи Cron наследуют настроенные резервные провайдеры и ротацию пула учётных данных. Если первичный API-ключ ограничен по скорости или провайдер возвращает ошибку, cron-агент может:

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

Форматы расписания

Окончательный ответ агента приходит автоматически — вам не нужно включать send_message в cron-prompt для той же цели. Если cron-запуск выдает send_message для той же цели, в которой планировщик уже доставлен, Hermes пропускает это дублирующее сообщение и сообщает модели по перемещению пользовательского контента в конечный ответ. Используйте send_message только для дополнительных или других целей.

Относительные задержки (одноразовые)

30m     → Выполнить один раз через 30 минут
2h      → Выполнить один раз через 2 часа
1d      → Выполнить один раз через 1 день

Интервалы (повторяющиеся)

every 30m    → Каждые 30 минут
every 2h     → Каждые 2 часа
every 1d     → Каждый день

Cron-выражения

0 9 * * *       → Ежедневно в 9:00
0 9 * * 1-5     → По будням в 9:00
0 */6 * * *     → Каждые 6 часов
30 8 1 * *      → Первое число каждого месяца в 8:30
0 0 * * 0       → Каждое воскресенье в полночь

ISO-метки времени

2026-03-15T09:00:00    → Одноразово 15 марта 2026 в 9:00

Поведение повторов

Тип расписания Повтор по умолчанию Поведение
Одноразовое (30m, метка времени) 1 Выполняется один раз
Интервал («каждые 2 часа») бесконечно Выполняется до удаления
Cron-выражение бесконечно Выполняется до удаления

Вы можете переопределить это:

cronjob(
    action="create",
    prompt="...",
    schedule="every 2h",
    repeat=5,
)

Программное решение задач

API для агента — это один инструмент:

cronjob(action="create",...)
cronjob(action="list")
cronjob(action="update", job_id="...")
cronjob(action="pause", job_id="...")
cronjob(action="resume", job_id="...")
cronjob(action="run", job_id="...")
cronjob(action="remove", job_id="...")

Для update передайте skills=[], чтобы удалить все прикреплённые навыки.

Наборы инструментов, доступные cron-задачи

Cron запускает каждую задачу в свежей сессии агента без прикреплённой чат-платформы. По умолчанию cron-агент получает набор инструментов, который вы установили для платформы cron в hermestools — не CLI по умолчанию, не всё подряд.

hermes tools
# → выберите платформу "cron" в curses UI
# → включайте/выключайте наборы инструментов так же, как для Telegram/Discord и т.д.

Более надежный контроль для каждой задачи доступен через поле enabled_toolsets в cronjob.create (или для относительных задач через cronjob.update):

cronjob(action="create", name="weekly-news-summary",
        schedule="every sunday 9am",
        enabled_toolsets=["web", "file"],      # только web + file, без terminal/browser и т.д.
        prompt="Суммируй новости AI за эту неделю:...")

Когда для задачи выбран enabled_toolsets, он имеет приоритет; в противном случае используется использование cron платформы из hermestools; В противном случае Гермес возвращается к значениям по умолчанию. Это важно для контроля затрат: включение moa, браузер, делегирование в каждую сложную задачу "получить новости" раздувает подсказку со схемой инструментов при каждом LLM-вызове.

Пропуск агента полностью: wakeAgent

Если ваша задача cron прикрепляет предварительную проверку скрипта (через script=), скрипт может во время ее решения, стоит Гермесу выполнить вообще работу агента. Вы вводите этот текст в стандартный формат:

{"wakeAgent": false}

…и cron пропускает выполнение агента для этого тика. Полезно для частных опросов (каждые 1–5 минут), которые следует активировать LLM только при вызове состояния — иначе вы будете платить за пустые витки агента снова и снова.

# скрипт предварительной проверки
import json, sys
latest = fetch_latest_issue_count()
prev = read_state("issue_count")
if latest == prev:
    print(json.dumps({"wakeAgent": False}))   # пропустить этот тик
    sys.exit(0)
write_state("issue_count", latest)
print(json.dumps({"wakeAgent": True, "context": {"new_issues": latest - prev}}))

Когда wakeAgent опущен, по умолчанию используется true (пробудить агента, как обычно).

Цепочки задачи: context_from

Задача Cron может получить последний успешный результат одной или нескольких других задач, перечислив их имена (или идентификаторы) в context_from:

cronjob(action="create", name="daily-digest",
        schedule="every day 7am",
        context_from=["ai-news-fetch", "github-prs-fetch"],
        prompt="Напиши ежедневный дайджест, используя выводы выше.")

Последние завершенные выводы указывают на то, что задачи объявляются перед приглашением в качестве контекста для этого запуска. каждая вышестоящая запись должна быть действительным идентификатором задачи или именем (см. cronjob action="list"). Примечание: цепочка читает последний завершённый вывод — она не ждёт вышестоящие задачи, которые выполняются таким же образом.

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

Задачи хранения в ~/.hermes/cron/jobs.json. Выводы задач запуска определяются в ~/.hermes/cron/output/{job_id}/{timestamp}.md.

Задачи могут хранить модели и поставщики как null. Когда эти поля опущены, «Гермес» разрешает их выполнение во время выполнения стандартного плана. Они создавали записи задач только тогда, когда были установлены переопределения для конкретной задачи.

Хранилище использует атомарные записи в файле, поэтому прерванные записи не являются частично зарегистрированными файловыми задачами.

Самодостаточные промпты всё ещё важны:::предупреждение Важно

Задачи Cron выполняются в совершенно новой сессии агента. Промпт должен сохранить все, что нужно агенту, что еще не предоставлено прикреплёнными навыками. ПЛОХО: "Проверь ту проблему на расстоянии"

ХОРОШО: "Подключись по SSH к серверу 192.168.1.100 как пользователь 'deploy', проверь, работает ли nginx с помощью 'systemctl status nginx', и убежденсь, что https://example.com использует HTTP 200."

Безопасность

Промпты запланированных задач сканируются на предмет инъекций, промптов и рабочих мест, учётных данных при создании и обновлении. Промпты, содержащие невидимые Unicode-трюки, попытку бэкдора через SSH или очевидную полезную нагрузку для кражи секретов, блокируются.