Перейти к содержимому

Воркеры и каналы

Канал — это чат внутри организации, в котором участвуют операторы (люди) и ИИ-воркеры. Воркер читает сообщения канала, рассуждает, выполняет команды на машинах организации и пишет в канал трассы своих действий. Иерархия простая: организация → каналы; отдельного уровня «сервер» нет — организация и есть сервер.

Каналы и воркеры связаны как M:N: один воркер может обслуживать несколько каналов, в одном канале может быть несколько воркеров.

Три похожих термина, которые не стоит путать:

  • воркер — ИИ-участник канала;
  • агент — демон nythronix-agent на управляемой машине, «руки» воркера;
  • nyx-worker — непривилегированный Unix-пользователь на машине, под которым агент выполняет команды воркера. К ИИ-воркеру отношения не имеет.
  1. В кабинете (https://app.nx.3fe.ru) откройте раздел Воркеры. Укажите имя, при необходимости — скилы (пресет, см. Скилы через MCP) и зону ответственности, выберите режим памяти и нажмите Создать.
  2. Откройте раздел Чат, введите имя нового канала и нажмите Создать. При создании канала можно задать пресет воркера.
  3. В канале нажмите + добавить воркера и выберите воркера из списка. Убрать его можно кнопкой убрать из канала.

Воркер обнаруживает свои каналы по членству: отдельной привязки «один воркер — один канал» нет.

Воркер не подключается к машинам напрямую. Он видит агентов своей организации через control plane и выполняет команды только через него: запрос cmd-exec уходит на control plane, тот пересылает его агенту, агент запускает команду под пользователем nyx-worker (если агент работает от root и такой пользователь существует) и возвращает вывод. Поэтому «добавить машину в канал» — это просто зарегистрировать агента в организации: воркер увидит его в списке машин. Как поставить агента, описано в Установка на Linux.

Как работает воркер: читает, предлагает, запускает

Заголовок раздела «Как работает воркер: читает, предлагает, запускает»

Воркер работает по циклу «рассуждение → инструмент → наблюдение». В канал попадают его трассы: что он собирается сделать и что получил в ответ.

  • Команды только для чтения (например df -h, ps aux | grep postgres, systemctl status nginx, docker logs) выполняются без подтверждения. Список допустимых «читающих» команд задан на сервере положительно: команда запускается автоматически, только если каждая стадия конвейера распознана как безопасное чтение.
  • Всё остальное — изменения файлов, сервисов, пакетов, сети, любые перенаправления вывода, подстановки $(...), интерпретаторы вроде bash -c, а также чтение секретов (.env, id_rsa, /etc/shadow, env) — требует подтверждения человеком.

Когда воркеру нужна изменяющая команда, он публикует в канале карточку нужно подтверждение с полями «Команда, которая выполнится», «Зачем» и «выполнится на» (машина). Оператор нажимает Подтвердить или Отклонить.

При подтверждении control plane выпускает одноразовый токен, привязанный к точному тексту команды и конкретному агенту; срок действия — 10 минут. Воркер обязан предъявить этот токен в следующем cmd-exec; сервер сверяет команду и агента и только тогда выполняет её. Без токена, с чужим токеном, с изменённой командой или после истечения срока запрос отклоняется с ошибкой approval.required / approval.*. Проверка выполняется на сервере, а не в воркере, поэтому обойти её со стороны воркера нельзя.

Каждое выполнение попадает в аудит как agent.cmd_exec с текстом команды и сведениями о подтверждении; решение оператора — как chat.approval.decided.

Разделение обязанностей при подтверждении

Заголовок раздела «Разделение обязанностей при подтверждении»

Для каждого оператора администратор может задать категории подтверждения (поле «Апрув: категории» в разделе Операторы): secret, user, package, network, db, service, filesystem, shell, other или *. Сервер определяет категорию команды (например, psql → db, apt → package, iptables → network) и разрешает подтверждение только оператору, у которого есть эта категория. Пустой список означает «любые категории»; роль owner может подтверждать всё. Так DBA не сможет «проштамповать» сетевое изменение.

Память воркера хранится на control plane и переживает пересоздание контейнера воркера. Она двухуровневая: «сырые» записи (сообщения каналов и заметки воркера) не удаляются, а старое содержимое сворачивается в скользящую сводку — блокнот воркера и сводку по каналу.

Режим памяти выбирается при создании воркера:

  • Общая — по всем каналам воркера (worker): воркер помнит свою зону во всех каналах. Удобно, если каналы — одна команда.
  • Изолированная — по каждому каналу (channel): заметки одного канала не попадают в промпт другого. Подходит, когда у каналов разная аудитория.

Ключи LLM никогда не хранятся на control plane. Их держит супервизор (реконсайлер), который запускает контейнеры воркеров: по умолчанию используется общий профиль LITELLM_*, а для отдельной организации можно задать свой base_url, api_key и model в файле, на который указывает NYX_LLM_PROFILES_FILE (в compose — ./llm-profiles.json):

{
"<organization-id>": {
"base_url": "https://litellm.example.com",
"api_key": "sk-...",
"model": "gpt-5.5"
}
}

Файл перечитывается каждый цикл, перезапуск не нужен. В SaaS-режиме этот файл ведёт оператор площадки; в self-hosted — вы (см. Развёртывание).

Управление воркером идёт по двум независимым осям.

  • Запустить / Остановить в разделе Воркеры задают желаемое состояние процесса (running / stopped). Control plane только записывает это поле; контейнер запускает и удаляет супервизор, который опрашивает control plane каждые 5 секунд. Упавший контейнер пересоздаётся автоматически; «зависший» (не шлёт heartbeat дольше NYX_HUNG_GRACE_SECS, по умолчанию 90 с) — перезапускается.
  • Пауза / Продолжить, Стоп и Рестарт в шапке канала действуют в рамках одного канала: пауза означает, что воркер жив, но новых задач в этом канале не берёт (текущая задача дорабатывается); стоп прерывает текущую задачу; рестарт перезапускает процесс.

Наблюдаемый статус в канале — «воркер онлайн», «воркер работает…», «на паузе», «воркер офлайн» — приходит от heartbeat воркера и не совпадает по смыслу с желаемым состоянием.