Суб-агенты

Суб-агенты — это фоновые запуски агентов, порожденные из существующего запуска агента. Они работают в собственной сессии (agent:<agentId>:subagent:<uuid>) и, по завершении, объявляют свой результат обратно в чат-канал запросившего.

Слэш-команда

Используйте /subagents для проверки или управления запусками суб-агентов для текущей сессии:

  • /subagents list
  • /subagents stop <id|#|all>
  • /subagents log <id|#> [limit] [tools]
  • /subagents info <id|#>
  • /subagents send <id|#> <message>

/subagents info показывает метаданные запуска (статус, временные метки, ID сессии, путь к транскрипту, очистка).

Основные цели:

  • Распараллеливание работы «исследование / длинная задача / медленный инструмент» без блокировки основного запуска.
  • Изоляция суб-агентов по умолчанию (разделение сессий + опциональная песочница).
  • Ограничение неправильного использования инструмента: суб-агенты не получают инструменты сессии по умолчанию.
  • Избегание вложенного веерного запуска: суб-агенты не могут порождать суб-агенты.

Примечание о стоимости: каждый суб-агент имеет собственный контекст и использование токенов. Для тяжелых или повторяющихся задач установите более дешевую модель для суб-агентов и оставьте основного агента на более качественной модели. Вы можете настроить это через agents.defaults.subagents.model или через переопределения для конкретного агента.

Инструмент

Используйте sessions_spawn:

  • Запускает запуск суб-агента (deliver: false, глобальная полоса: subagent)
  • Затем выполняет шаг объявления и публикует ответ объявления в чат-канал запросившего
  • Модель по умолчанию: наследуется от вызывающего, если вы не установите agents.defaults.subagents.model (или для конкретного агента agents.list[].subagents.model); явный sessions_spawn.model всё равно выиграет.

Параметры инструмента:

  • task (обязательно)
  • label? (опционально)
  • agentId? (опционально; породить под другим ID агента, если разрешено)
  • model? (опционально; переопределяет модель суб-агента; недопустимые значения пропускаются, и суб-агент работает на модели по умолчанию с предупреждением в результате инструмента)
  • thinking? (опционально; переопределяет уровень размышления для запуска суб-агента)
  • runTimeoutSeconds? (по умолчанию 0; при установке запуск суб-агента прерывается через N секунд)
  • cleanup? (delete|keep, по умолчанию keep)

Список разрешений:

  • agents.list[].subagents.allowAgents: список ID агентов, которые могут быть целевыми через agentId (["*"] разрешает любой). По умолчанию: только агент запросившего.

Обнаружение:

  • Используйте agents_list, чтобы увидеть, какие ID агентов в настоящее время разрешены для sessions_spawn.

Автоархивирование:

  • Сессии суб-агентов автоматически архивируются после agents.defaults.subagents.archiveAfterMinutes (по умолчанию: 60).
  • Архивирование использует sessions.delete и переименовывает транскрипт в *.deleted.<timestamp> (та же папка).
  • cleanup: "delete" архивирует сразу после объявления (но сохраняет транскрипт через переименование).
  • Автоархивирование выполняется по возможности; ожидающие таймеры теряются, если шлюз перезапускается.
  • runTimeoutSeconds не автоархивирует; он только останавливает запуск. Сессия остается до автоархивирования.

Аутентификация

Аутентификация суб-агента разрешается по ID агента, а не по типу сессии:

  • Ключ сессии суб-агента — agent:<agentId>:subagent:<uuid>.
  • Хранилище аутентификации загружается из agentDir этого агента.
  • Профили аутентификации основного агента объединяются как запасной вариант; профили агента переопределяют основные профили при конфликтах.

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

Объявление

Суб-агенты сообщают обратно через шаг объявления:

  • Шаг объявления выполняется внутри сессии суб-агента (не в сессии запросившего).
  • Если суб-агент отвечает точно ANNOUNCE_SKIP, ничего не публикуется.
  • В противном случае ответ объявления публикуется в чат-канал запросившего через последующий вызов agent (deliver=true).
  • Ответы объявления сохраняют маршрутизацию потоков/топиков, когда доступна (потоки Slack, топики Telegram, потоки Matrix).
  • Сообщения объявления нормализуются до стабильного шаблона:
    • Status: получен из результата запуска (success, error, timeout, или unknown).
    • Result: содержание резюме из шага объявления (или (not available), если отсутствует).
    • Notes: детали ошибки и другой полезный контекст.
  • Status не выводится из вывода модели; он происходит из сигналов результата выполнения.

Полезные данные объявления включают строку статистики в конце (даже при обертывании):

  • Время выполнения (например, runtime 5m12s)
  • Использование токенов (входные/выходные/всего)
  • Оценочная стоимость, когда настроены цены модели (models.providers.*.models[].cost)
  • sessionKey, sessionId и путь к транскрипту (чтобы основной агент мог получить историю через sessions_history или проверить файл на диске)

Политика инструментов (инструменты суб-агента)

По умолчанию суб-агенты получают все инструменты, кроме инструментов сессии:

  • sessions_list
  • sessions_history
  • sessions_send
  • sessions_spawn

Переопределение через конфигурацию:

{
  agents: {
    defaults: {
      subagents: {
        maxConcurrent: 1
      }
    }
  },
  tools: {
    subagents: {
      tools: {
        // deny побеждает
        deny: ["gateway", "cron"],
        // если allow установлен, он становится только разрешенным (deny всё равно побеждает)
        // allow: ["read", "exec", "process"]
      }
    }
  }
}

Одновременность

Суб-агенты используют выделенную полосу внутрипроцессной очереди:

  • Название полосы: subagent
  • Одновременность: agents.defaults.subagents.maxConcurrent (по умолчанию 8)

Остановка

  • Отправка /stop в чат запросившего прерывает сессию запросившего и останавливает любые активные запуски суб-агентов, порожденные из неё.

Ограничения

  • Объявление суб-агента выполняется по возможности. Если шлюз перезапускается, ожидающая работа «объявить обратно» теряется.
  • Суб-агенты всё еще разделяют ресурсы одного и того же процесса шлюза; рассматривайте maxConcurrent как предохранительный клапан.
  • sessions_spawn всегда неблокирующий: он немедленно возвращает \{ status: "accepted", runId, childSessionKey \}.
  • Контекст суб-агента вставляет только AGENTS.md + TOOLS.md (без SOUL.md, IDENTITY.md, USER.md, HEARTBEAT.md или BOOTSTRAP.md).