Cron-задачи на скриптах

Иногда вы уже точно знаете, какое сообщение хотите отправить. Обдумывать тут нечего, агент не нужен — достаточно гонять скрипт по таймеру и, если он что-то выводит, слать это в Telegram / Discord / Slack / Signal.

В Hermes такой режим называется no-agent mode. Та же cron-система, только без LLM.

   ┌──────────────────┐          ┌──────────────────┐
   │ scheduler tick   │  every   │ run script       │
   │ (every N minutes)│ ──────▶ │ (bash or python) │
   └──────────────────┘          └──────────────────┘

                                          │ stdout

                                 ┌──────────────────┐
                                 │ delivery router  │
                                 │ (telegram/disc…) │
                                 └──────────────────┘
  • Никаких обращений к LLM. Ноль токенов, ни одного прохода цикла агента, ноль расходов на модель.
  • Скрипт и есть задача. Он сам решает, слать алерт или промолчать: что-то вывел — сообщение уходит, вывел пустоту — тихий тик.
  • Bash или Python. Файлы .sh / .bash идут через /bin/bash; всё с любым другим расширением — через текущий интерпретатор Python. Принимается любой файл из ~/.hermes/scripts/.
  • Тот же планировщик. Задача живёт в cronjob рядом с LLM-задачами, а пауза, возобновление, список, логи и настройка доставки работают точно так же.

Когда это нужно

No-agent mode хорош для таких сценариев:

  • Watchdog по памяти / диску / GPU. Запуск раз в 5 минут, алерт только при пробитии порога.
  • CI-хуки. Деплой завершён → отправить SHA коммита. Сборка упала → прислать последние 100 строк лога.
  • Периодические метрики. «Выручка Stripe за день в 9 утра» — это один API-запрос и красивый вывод, не больше.
  • Поллинг внешних событий. Дёрнуть API, сигнализировать при смене состояния.
  • Heartbeat-пинги. Раз в N минут стучаться в дашборд и доказывать, что хост жив.

А вот обычный (LLM-driven) cron берут, когда агент должен сам решить, что сказать: пересказать длинный документ, выбрать интересное из ленты, набросать человечное напоминание. No-agent-путь — для случаев, где stdout скрипта уже и есть готовое сообщение.

Создать через чат

Самое приятное в no-agent mode: агент настроит watchdog за вас сам — без редактора, без шелла, без зубрёжки флагов CLI. Опишите словами, что хотите, дальше Hermes напишет скрипт, поставит его в расписание и скажет, когда тот сработает.

Пример диалога

Вы: пинги в telegram если RAM выше 85% каждые 5 минут

Hermes: (пишет ~/.hermes/scripts/memory-watchdog.sh, затем вызывает cronjob(...) с no_agent=true)

Готово. Запускается каждые 5 мин, шлёт в Telegram только когда RAM выше 85%. Скрипт: memory-watchdog.sh. ID задачи: abc123.

Под капотом агент делает два вызова инструментов:

# 1. Write the check script
write_file(
    path="~/.hermes/scripts/memory-watchdog.sh",
    content='''#!/usr/bin/env bash
ram_pct=$(free | awk '/^Mem:/ {printf "%d", $3 * 100 / $2}')
if [ "$ram_pct" -ge 85 ]; then
  echo "RAM ${ram_pct}% on $(hostname)"
fi
# Empty stdout = silent tick; no message sent.
''',
)

# 2. Schedule it — no_agent=True skips the LLM on every tick
cronjob(
    action="create",
    schedule="every 5m",
    script="memory-watchdog.sh",
    no_agent=True,
    deliver="telegram",
    name="memory-watchdog",
)

Дальше каждый тик бесплатен: планировщик запускает скрипт и, если вывод непустой, передаёт его в Telegram. К модели не обращается ни разу.

Что агент решает за вас

Сформулируйте запрос в духе «алертить меня если X» или «каждые N минут проверяй Y и сообщай если Z» — и описание инструмента cronjob само подскажет Hermes взять no_agent=True, раз содержание сообщения полностью задано скриптом. На обычный LLM-путь агент сворачивает там, где нужны рассуждения: «резюмируй новые issue», «выбери самые интересные заголовки», «набросай дружелюбное напоминание».

Указывать --no-agent вручную не придётся. Просто опишите нужное поведение на естественном языке.

Управление watchdog-задачами из чата

Ставить на паузу, возобновлять, править и удалять задачи агент умеет ровно так же, как создаёт:

Вы: останови memory watchdog на сегодняшнюю ночь

Hermes: (вызывает cronjob(action='pause', job_id='abc123'))

На паузе. Возобновить: «включи снова» или через hermes cron resume abc123.

Вы: смени интервал на каждые 15 минут

Hermes: (вызывает cronjob(action='update', job_id='abc123', schedule='every 15m'))

Весь жизненный цикл (create / list / update / pause / resume / run-now / remove) доступен агенту, а команды CLI учить не нужно.

Создать через CLI

Привыкли к шеллу? CLI-путь даёт тот же результат тремя командами:

# 1. Write your script
cat > ~/.hermes/scripts/memory-watchdog.sh <<'EOF'
#!/usr/bin/env bash
# Alert when RAM usage is over 85%. Silent otherwise.
RAM_PCT=$(free | awk '/^Mem:/ {printf "%d", $3 * 100 / $2}')
if [ "$RAM_PCT" -ge 85 ]; then
  echo "⚠ RAM ${RAM_PCT}% on $(hostname)"
fi
# Empty stdout = silent run; no message sent.
EOF
chmod +x ~/.hermes/scripts/memory-watchdog.sh

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

# 3. Verify
hermes cron list
hermes cron run <job_id>    # fire it once to test

Вот и всё. Ни промпта, ни навыка, ни модели.

Как вывод скрипта превращается в доставку

Поведение скриптаРезультат
Выход 0, непустой stdoutstdout доставляется дословно
Выход 0, пустой stdoutТихий тик — доставки нет
Выход 0, последняя строка stdout содержит {"wakeAgent": false}Тихий тик (общий шлюз с LLM-задачами)
Ненулевой код выходаДоставляется алерт об ошибке (чтобы сломавшийся watchdog не молчал)
Таймаут скриптаДоставляется алерт об ошибке

На «молчании при пустом выводе» и держится классический watchdog-паттерн: скрипт может крутиться хоть каждую минуту, но в канал сообщение прилетит только тогда, когда что-то реально требует внимания.

Правила для скриптов

Скрипты обязаны лежать в ~/.hermes/scripts/. Проверка идёт и при создании задачи, и при запуске: абсолютные пути, раскрытие ~/ и шаблоны обхода каталога (../) отклоняются. Тот же каталог использует и шлюз предварительной проверки для LLM-задач.

Интерпретатор выбирается по расширению файла:

РасширениеИнтерпретатор
.sh, .bash/bin/bash
любое другоеsys.executable (текущий Python)

Шебанги #!/... намеренно игнорируются: чем жёстче и уже набор интерпретаторов, тем меньше того, чему планировщик вынужден доверять.

Синтаксис расписания

Такой же, как у остальных cron-задач:

hermes cron create "every 5m"        # интервал
hermes cron create "every 2h"
hermes cron create "0 9 * * *"       # стандартный cron: каждый день в 9:00
hermes cron create "30m"             # одноразово: запустить через 30 минут

Полный синтаксис — в справочнике по cron.

Цели доставки

--deliver принимает всё, что знает шлюз. Типичные варианты:

--deliver telegram                       # platform home channel
--deliver telegram:-1001234567890        # specific chat
--deliver telegram:-1001234567890:17585  # specific Telegram forum topic
--deliver discord:#ops
--deliver slack:#engineering
--deliver signal:+15551234567
--deliver local                          # just save to ~/.hermes/cron/output/

Для платформ с bot-токеном (Telegram, Discord, Slack, Signal, SMS, WhatsApp) запущенный шлюз в момент запуска скрипта не требуется: инструмент сам стучится в REST-эндпоинт каждой платформы по учётным данным из ~/.hermes/.env / ~/.hermes/config.yaml.

Редактирование и жизненный цикл

hermes cron list                                    # see all jobs
hermes cron pause <job_id>                          # stop firing, keep definition
hermes cron resume <job_id>
hermes cron edit <job_id> --schedule "every 10m"    # adjust cadence
hermes cron edit <job_id> --agent                   # flip to LLM mode
hermes cron edit <job_id> --no-agent --script     # flip back
hermes cron remove <job_id>                         # delete it

Что доступно для LLM-задач — пауза, возобновление, ручной запуск, смена цели доставки — то же работает и с no-agent-задачами.

Пример: алерт о заполненности диска

cat > ~/.hermes/scripts/disk-alert.sh <<'EOF'
#!/usr/bin/env bash
# Alert when / or /home is over 90% full.
THRESHOLD=90
df -h / /home 2>/dev/null | awk -v t="$THRESHOLD" '
  NR > 1 && $5+0 >= t {
    printf "⚠ Disk %s full on %s\n", $5, $6
  }
'
EOF
chmod +x ~/.hermes/scripts/disk-alert.sh

hermes cron create "*/15 * * * *" \
  --no-agent \
  --script disk-alert.sh \
  --deliver telegram \
  --name "disk-alert"

Пока оба раздела заняты меньше чем на 90%, скрипт молчит. Как только один заполнится — пришлёт ровно одну строку на каждый раздел сверх порога.

Сравнение с другими подходами

ПодходЧто выполняетсяКогда использовать
cronjob --no-agent (эта страница)Ваш скрипт по расписанию HermesПериодические watchdog-задачи / алерты / метрики, где рассуждать не нужно
cronjob (по умолчанию, LLM)Агент с опциональным скриптом предварительной проверкиКогда содержание сообщения требует анализа данных
OS cron + curl до webhook subscriptionВаш скрипт по расписанию ОСКогда сам Hermes может лежать (а вы как раз его и мониторите)

Если watchdog критичен и должен срабатывать даже при упавшем шлюзе, берите cron уровня ОС с простым curl до вебхука Hermes (или любого внешнего алертинг-эндпоинта): такие задачи живут отдельными процессами ОС и от состояния Hermes не зависят. А встроенный планировщик хорош там, где мониторишь что-то внешнее.

Связанные материалы

ESC