Очередь команд (2026-01-16)

Мы сериализуем входящие запуски автоответа (все каналы) через крошечную внутрипроцессную очередь, чтобы предотвратить столкновение нескольких запусков агентов, сохраняя при этом безопасный параллелизм между сессиями.

Почему

  • Запуски автоответа могут быть дорогими (вызовы LLM) и могут сталкиваться, когда несколько входящих сообщений поступают близко друг к другу.
  • Сериализация избегает конкуренции за общие ресурсы (файлы сессий, журналы, stdin CLI) и снижает вероятность ограничений скорости выше по потоку.

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

  • Очередь FIFO с поддержкой линий дренирует каждую линию с настраиваемым ограничением параллелизма (по умолчанию 1 для ненастроенных линий; main по умолчанию 4, subagent 8).
  • runEmbeddedPiAgent ставит в очередь по ключу сессии (линия session:<key>), чтобы гарантировать только один активный запуск на сессию.
  • Каждый запуск сессии затем ставится в очередь в глобальную линию (main по умолчанию), чтобы общий параллелизм был ограничен agents.defaults.maxConcurrent.
  • Когда включено подробное ведение журнала, запуски в очереди выдают короткое уведомление, если они ждали более ~2 секунд перед запуском.
  • Индикаторы набора все еще срабатывают немедленно при постановке в очередь (когда поддерживается каналом), поэтому пользовательский опыт не изменяется, пока мы ждем своей очереди.

Режимы очереди (для каждого канала)

Входящие сообщения могут направлять текущий запуск, ждать следующего хода или делать и то, и другое:

  • steer: внедрить немедленно в текущий запуск (отменяет ожидающие вызовы инструментов после следующей границы инструмента). Если не потоковая передача, откатывается к followup.
  • followup: ставить в очередь для следующего хода агента после завершения текущего запуска.
  • collect: объединить все сообщения в очереди в один ход followup (по умолчанию). Если сообщения нацелены на разные каналы/треды, они дренируются индивидуально для сохранения маршрутизации.
  • steer-backlog (он же steer+backlog): направить сейчас и сохранить сообщение для хода followup.
  • interrupt (устаревший): прервать активный запуск для этой сессии, затем запустить новейшее сообщение.
  • queue (устаревший псевдоним): то же, что и steer.

Steer-backlog означает, что вы можете получить ответ followup после управляемого запуска, поэтому поверхности потоковой передачи могут выглядеть как дубликаты. Предпочтите collect/steer, если вы хотите один ответ на входящее сообщение. Отправьте /queue collect как автономную команду (для каждой сессии) или установите messages.queue.byChannel.discord: "collect".

Значения по умолчанию (когда не установлено в конфигурации):

  • Все поверхности → collect

Настройте глобально или для каждого канала через messages.queue:

{
  messages: {
    queue: {
      mode: "collect",
      debounceMs: 1000,
      cap: 20,
      drop: "summarize",
      byChannel: { discord: "collect" }
    }
  }
}

Опции очереди

Опции применяются к followup, collect и steer-backlog (и к steer, когда он откатывается к followup):

  • debounceMs: ждать тишины перед началом хода followup (предотвращает "продолжить, продолжить").
  • cap: максимум сообщений в очереди на сессию.
  • drop: политика переполнения (old, new, summarize).

Summarize хранит короткий список пунктов удаленных сообщений и внедряет его как синтетическую подсказку followup. По умолчанию: debounceMs: 1000, cap: 20, drop: summarize.

Переопределения для каждой сессии

  • Отправьте /queue <mode> как автономную команду, чтобы сохранить режим для текущей сессии.
  • Опции могут быть объединены: /queue collect debounce:2s cap:25 drop:summarize
  • /queue default или /queue reset очищает переопределение сессии.

Область видимости и гарантии

  • Применяется к запускам агента автоответа по всем входящим каналам, которые используют конвейер ответа gateway (WhatsApp web, Telegram, Slack, Discord, Signal, iMessage, webchat и т.д.).
  • Линия по умолчанию (main) охватывает весь процесс для входящих + основных сердцебиений; установите agents.defaults.maxConcurrent, чтобы разрешить несколько сессий параллельно.
  • Дополнительные линии могут существовать (например, cron, subagent), чтобы фоновые задания могли выполняться параллельно, не блокируя входящие ответы.
  • Линии для каждой сессии гарантируют, что только один запуск агента касается данной сессии за раз.
  • Нет внешних зависимостей или фоновых рабочих потоков; чистый TypeScript + промисы.

Устранение неполадок

  • Если команды кажутся застрявшими, включите подробные журналы и ищите строки "queued for …ms", чтобы подтвердить, что очередь дренируется.
  • Если вам нужна глубина очереди, включите подробные журналы и следите за строками времени очереди.