Messages and delivery

Очередь команд

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

Зачем это нужно

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

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

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

Значения по умолчанию

Если параметры не заданы, все поверхности входящих каналов используют:

  • mode: "steer"
  • debounceMs: 500
  • cap: 20
  • drop: "summarize"

По умолчанию применяется управление в рамках текущего хода. Запрос, поступивший во время выполнения, внедряется в активную среду выполнения, если запуск поддерживает управление, поэтому второй запуск сеанса не начинается. Если активный запуск не поддерживает управление, OpenClaw ожидает его завершения, прежде чем запустить запрос.

Режимы очереди

/queue определяет поведение обычных входящих сообщений, когда в сеансе уже есть активный запуск:

  • steer: внедрять сообщения в активную среду выполнения. OpenClaw передаёт все ожидающие управляющие сообщения после того, как текущий ход ассистента завершит выполнение вызовов инструментов, но до следующего вызова LLM; сервер приложений Codex получает один пакетный turn/steer. Если запуск не передаёт потоковые данные или управление недоступно, OpenClaw ожидает завершения активного запуска, прежде чем запустить запрос.
  • followup: не выполнять управление. Помещать каждое сообщение в очередь для последующего хода агента после завершения текущего запуска.
  • collect: не выполнять управление. Объединять сообщения в очереди в один последующий ход после периода отсутствия активности. Если сообщения предназначены для разных каналов или веток, они обрабатываются отдельно, чтобы сохранить маршрутизацию.
  • interrupt: прервать активный запуск этого сеанса, а затем выполнить новейшее сообщение.

Сведения о временных характеристиках конкретных сред выполнения и поведении зависимостей см. в разделе Очередь управления. Сведения о явной команде /steer <message> см. в разделе Управление.

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

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

Параметры очереди

Параметры применяются к доставке из очереди. debounceMs также задаёт период отсутствия активности для управления Codex в режиме steer:

  • debounceMs: период отсутствия активности перед обработкой последующих сообщений из очереди или объединённых пакетов; в режиме Codex steer — период отсутствия активности перед отправкой пакетного 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 применяет следующий порядок:

  1. Встроенное или сохранённое переопределение /queue для конкретного сеанса.
  2. messages.queue.byChannel.<channel>.
  3. messages.queue.mode.
  4. Значение по умолчанию steer.

Для параметров встроенные или сохранённые параметры /queue имеют приоритет над конфигурацией. Затем в указанном порядке применяются задержка для конкретного канала (messages.queue.debounceMsByChannel), значения задержки по умолчанию из плагина, глобальные параметры messages.queue и встроенные значения по умолчанию. cap и drop являются глобальными параметрами или параметрами сеанса, а не ключами конфигурации отдельных каналов.

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

  • Отправьте /queue <steer|followup|collect|interrupt> как отдельную команду, чтобы сохранить режим очереди для текущего сеанса.
  • Параметры можно комбинировать: /queue collect debounce:0.5s cap:25 drop:summarize
  • /queue default или /queue reset удаляет переопределение сеанса.

Отмена хода в очереди

Пока запрос находится в очереди последующих или объединённых сообщений (например, когда chat.send из TUI или веб-чата поступает во время другого активного хода), Gateway сохраняет принадлежащий Gateway идентификатор отмены для клиентского runId, пока содержимое из очереди не будет выполнено или удалено. Этот идентификатор следует за содержимым, включённым в сводку переполнения.

  • chat.abort с конкретным runId отменяет этот ход, пока он ещё находится в очереди, если запрашивающая сторона авторизована (применяются те же правила владения, что и для активных запусков).
  • chat.abort для сеанса без runId сначала отменяет авторизованные ходы в очереди, а затем прерывает авторизованные активные запуски. Такой порядок не позволяет обработке очереди перевести работу в частично остановленный сеанс.
  • Очистка всей очереди сеанса без проверок для каждой запрашивающей стороны не является способом остановки для сеансов с несколькими владельцами.
  • Ожидание в очереди не представляется как активный запуск агента для sessions.list и не использует семантику тайм-аута активного запуска; она применяется только к активной фазе.

Клиенты (включая TUI) пересылают запросы, поступившие во время выполнения, и позволяют Gateway применить режим очереди. Esc//stop использует прерывание на уровне сеанса, чтобы потеря локальных дескрипторов не привела к выполнению запроса, всё ещё находящегося в очереди.

Область действия и гарантии

  • Применяется к запускам агента автоответов во всех входящих каналах, использующих конвейер ответов Gateway (WhatsApp Web, Telegram, Slack, Discord, Signal, iMessage, веб-чат и т. д.).
  • Линия по умолчанию (main) действует на весь процесс для входящих запросов и основных Heartbeat; задайте agents.defaults.maxConcurrent, чтобы разрешить параллельную работу нескольких сеансов.
  • Могут существовать дополнительные линии (например, cron, cron-nested, nested, subagent), чтобы фоновые задания могли выполняться параллельно, не блокируя входящие ответы. Изолированные ходы агента Cron удерживают слот cron, пока их внутреннее выполнение агента использует cron-nested; оба используют cron.maxConcurrentRuns. Общие потоки nested, не относящиеся к Cron, сохраняют собственное поведение линий. Эти отсоединённые запуски отслеживаются как фоновые задачи.
  • Линии для отдельных сеансов гарантируют, что с конкретным сеансом одновременно работает только один запуск агента.
  • Нет внешних зависимостей или фоновых рабочих потоков; используются только TypeScript и промисы.

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

  • Если кажется, что команды зависли, включите подробные журналы и найдите строки "queued for ...ms", чтобы убедиться, что очередь обрабатывается.
  • Запуски сервера приложений Codex, которые принимают ход, а затем перестают сообщать о ходе выполнения, прерываются адаптером Codex, чтобы активная линия сеанса могла освободиться, не дожидаясь тайм-аута внешнего запуска.
  • Когда диагностика включена, сеансы, которые остаются в processing дольше diagnostics.stuckSessionWarnMs без наблюдаемого ответа, инструмента, состояния, блока или прогресса ACP, классифицируются по текущей активности:
    • Активная работа с недавним прогрессом регистрируется как session.long_running. Принадлежащие владельцу безмолвные вызовы модели также остаются в состоянии session.long_running до diagnostics.stuckSessionAbortMs, чтобы медленные или непотоковые провайдеры не считались зависшими слишком рано.
    • Активная работа без недавнего прогресса регистрируется как session.stalled; принадлежащие владельцу вызовы модели, заблокированные вызовы инструментов и зависшие встроенные запуски переходят в session.stalled при достижении порога прерывания или после него. Устаревшая активность модели или инструмента без владельца не скрывается как длительная.
    • session.stuck зарезервировано для восстанавливаемых устаревших данных учёта сеанса, включая неактивные сеансы в очереди с устаревшей активностью модели или инструмента без владельца.
    • session.stuck всегда запускает восстановление, которое может освободить затронутую линию сеанса. Классификация session.stalled после diagnostics.stuckSessionAbortMs (заблокированный вызов инструмента, зависший вызов модели или зависший встроенный запуск) также может запустить восстановление с прерыванием активного запуска, поэтому устранить зависание очереди могут обе классификации, а не только session.stuck.
    • Повторяющиеся строки предупреждений session.stuck и session.long_running выводятся с экспоненциально увеличивающимися интервалами, пока состояние сеанса не меняется; попытки восстановления по-прежнему выполняются при каждом такте Heartbeat независимо от этого увеличения интервалов.

См. также

Was this useful?
On this page

On this page