Messages and delivery
Очередь команд
Мы сериализуем входящие запуски автоответов (все каналы) через небольшую внутрипроцессную очередь, чтобы несколько запусков агента не сталкивались друг с другом, при этом сохраняя безопасный параллелизм между сеансами.
Зачем
- Запуски автоответов могут быть дорогими (вызовы LLM) и могут конфликтовать, когда несколько входящих сообщений приходят почти одновременно.
- Сериализация предотвращает конкуренцию за общие ресурсы (файлы сеанса, журналы, stdin CLI) и снижает вероятность лимитов частоты на стороне вышестоящих сервисов.
Как это работает
- FIFO-очередь с учетом полосы обрабатывает каждую полосу с настраиваемым лимитом параллелизма (по умолчанию 1 для ненастроенных полос; main по умолчанию 4, subagent — 8).
runEmbeddedAgentставит в очередь по ключу сеанса (полосаsession:<key>), чтобы гарантировать только один активный запуск на сеанс.- Затем каждый запуск сеанса ставится в глобальную полосу (
mainпо умолчанию), так что общий параллелизм ограничиваетсяagents.defaults.maxConcurrent. - Когда включено подробное логирование, запуски в очереди выводят короткое уведомление, если ждали более ~2 с перед стартом.
- Индикаторы набора по-прежнему срабатывают сразу при постановке в очередь (если канал поддерживает это), поэтому пользовательский опыт не меняется, пока мы ждем своей очереди.
Значения по умолчанию
Если не задано, все входящие поверхности каналов используют:
mode: "steer"debounceMs: 500cap: 20drop: "summarize"
Управление в том же ходе является поведением по умолчанию. Подсказка, поступившая во время выполнения, внедряется в активную среду выполнения, если запуск может принимать управление, поэтому второй запуск сеанса не начинается. Если активный запуск не может принимать управление, OpenClaw ждет завершения активного запуска перед запуском подсказки.
Режимы очереди
/queue управляет тем, что делают обычные входящие сообщения, когда у сеанса уже есть
активный запуск:
steer: внедрять сообщения в активную среду выполнения. OpenClaw доставляет все ожидающие сообщения управления после того, как текущий ход ассистента завершит выполнение вызовов инструментов, перед следующим вызовом LLM; app-server Codex получает один пакетныйturn/steer. Если запуск не выполняет активную потоковую передачу или управление недоступно, OpenClaw ждет завершения активного запуска перед запуском подсказки.followup: не управлять. Ставить каждое сообщение в очередь для более позднего хода агента после завершения текущего запуска.collect: не управлять. Объединять сообщения в очереди в один последующий ход после окна тишины. Если сообщения нацелены на разные каналы/потоки, они обрабатываются по отдельности, чтобы сохранить маршрутизацию.interrupt: прервать активный запуск для этого сеанса, затем выполнить самое новое сообщение.
Сведения о специфичных для среды выполнения таймингах и поведении зависимостей см.
Очередь управления. Сведения о явной команде /steer <message>
см. в разделе Управление.
Настраивайте глобально или для каждого канала через messages.queue:
{ messages: { queue: { mode: "steer", debounceMs: 500, cap: 20, drop: "summarize", byChannel: { discord: "collect" }, }, },}Параметры очереди
Параметры применяются к доставке из очереди. debounceMs также задает окно тишины
для управления Codex в режиме steer:
debounceMs: окно тишины перед обработкой последующих сообщений или пакетов collect из очереди; в режиме Codexsteer— окно тишины перед отправкой пакетногоturn/steer. Простые числа считаются миллисекундами; параметры/queueпринимают единицыms,s,m,hиd.cap: максимальное число сообщений в очереди на сеанс. Значения ниже1игнорируются.drop: "summarize": по умолчанию. При необходимости отбрасывать самые старые записи очереди, сохранять компактные сводки и внедрять их как синтетическую последующую подсказку.drop: "old": при необходимости отбрасывать самые старые записи очереди без сохранения сводок.drop: "new": отклонять самое новое сообщение, когда очередь уже заполнена.
Значения по умолчанию: debounceMs: 500, cap: 20, drop: summarize.
Управление и потоковая передача
Когда потоковая передача канала имеет значение partial или block, управление может выглядеть как несколько
коротких видимых ответов, пока активный запуск достигает границ среды выполнения:
partial: предварительный просмотр может завершиться рано, затем после принятия управления начинается новый предварительный просмотр.block: блоки размером с черновик могут создавать такой же последовательный вид.- Без потоковой передачи управление возвращается к последующему сообщению после активного запуска, когда среда выполнения не может принять управление в том же ходе.
steer не прерывает уже выполняющиеся инструменты. Используйте /queue interrupt, когда самое новое
сообщение должно прервать текущий запуск.
Приоритет
Для выбора режима OpenClaw разрешает:
- Встроенное или сохраненное переопределение
/queueдля сеанса. messages.queue.byChannel.<channel>.messages.queue.mode.- Значение по умолчанию
steer.
Для параметров встроенные или сохраненные параметры /queue имеют приоритет над конфигурацией. Затем
применяются специфичный для канала debounce (messages.queue.debounceMsByChannel), значения debounce по умолчанию Plugin,
глобальные параметры messages.queue и встроенные значения по умолчанию. cap и drop — это глобальные/сеансовые параметры, а не конфигурационные
ключи для отдельных каналов.
Переопределения для сеанса
- Отправьте
/queue <steer|followup|collect|interrupt>как отдельную команду, чтобы сохранить режим очереди для текущего сеанса. - Параметры можно комбинировать:
/queue collect debounce:0.5s cap:25 drop:summarize /queue defaultили/queue resetочищает переопределение сеанса.
Область действия и гарантии
- Применяется к запускам агента автоответов во всех входящих каналах, которые используют конвейер ответов Gateway (WhatsApp web, Telegram, Slack, Discord, Signal, iMessage, webchat и т. д.).
- Полоса по умолчанию (
main) действует в рамках процесса для входящих сообщений и основных Heartbeat; задайтеagents.defaults.maxConcurrent, чтобы разрешить параллельную работу нескольких сеансов. - Могут существовать дополнительные полосы (например,
cron,cron-nested,nested,subagent), чтобы фоновые задания могли выполняться параллельно, не блокируя входящие ответы. Изолированные ходы cron-агента удерживают слотcron, пока их внутреннее выполнение агента используетcron-nested; оба используютcron.maxConcurrentRuns. Общие не-cron-потокиnestedсохраняют собственное поведение полосы. Эти отсоединенные запуски отслеживаются как фоновые задачи. - Полосы для сеанса гарантируют, что только один запуск агента одновременно обращается к данному сеансу.
- Никаких внешних зависимостей или фоновых рабочих потоков; только TypeScript + promises.
Устранение неполадок
- Если команды кажутся зависшими, включите подробные журналы и ищите строки "queued for ...ms", чтобы подтвердить, что очередь обрабатывается.
- Если нужна глубина очереди, включите подробные журналы и следите за строками тайминга очереди.
- Запуски app-server Codex, которые принимают ход, а затем перестают выводить прогресс, прерываются адаптером Codex, чтобы активная полоса сеанса могла освободиться, не дожидаясь тайм-аута внешнего запуска.
- Когда диагностика включена, сеансы, которые остаются в
processingдольшеdiagnostics.stuckSessionWarnMsбез наблюдаемого ответа, инструмента, статуса, блока или прогресса ACP, классифицируются по текущей активности. Активная работа логируется какsession.long_running; принадлежащие владельцу тихие вызовы модели также остаютсяsession.long_runningдоdiagnostics.stuckSessionAbortMs, чтобы медленные или непотоковые провайдеры не считались зависшими слишком рано. Активная работа без недавнего прогресса логируется какsession.stalled; принадлежащие владельцу вызовы модели переключаются наsession.stalledна пороге прерывания или после него, а устаревшая активность модели/инструмента без владельца не скрывается как длительная.session.stuckзарезервирован для восстанавливаемого устаревшего учета сеансов, включая простаивающие сеансы в очереди с устаревшей активностью модели/инструмента без владельца, и только этот путь может освободить затронутую полосу сеанса, чтобы работа из очереди продолжила обрабатываться. Повторные диагностикиsession.stuckприменяют backoff, пока сеанс остается неизменным.