Очередь команд (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", чтобы подтвердить, что очередь дренируется.
- Если вам нужна глубина очереди, включите подробные журналы и следите за строками времени очереди.