Коротко
- Между 2026.9.1 и 2026.9.6 Gateway шлёт в конце стрима лишний чанк с
replace:true, без обработки флага клиент рисует ответ дважды. agents.defaults.compaction.reserveTokensFloorвыведен из схемы: ключ вopenclaw.jsonвалит CLI, чинитopenclaw doctor --fix.fallbacksвagents.defaults.modelспасают только primary по умолчанию; модель, выбранную черезsessions.patch, при 503 резервная цепочка уже не подхватит.
Сверено с документацией OpenClaw 2026.9.8, 4 октября 2026.
После обновления Gateway до 2026.9.6 пользовательский клиент автора поста на r-openclaw поверх WebSocket рисует каждый ответ ассистента двойным абзацем. Виновник — финальный чанк стрима, который Gateway теперь отправляет с новым itemId и флагом replace:true. Кто видит новый itemId и сразу дописывает абзац, получает дубль. По дороге всплывают ещё две мины: устаревший ключ конфига ломает CLI, а выбор модели через sessions.patch больше не прикрыт общим резервом.
Как устроен финальный чанк
С переходом OpenAI-моделей на плагин codex Gateway после основного потока под itemId вида msg_… отправляет ещё один stream=assistant чанк. У него новый itemId, полный текст ответа слово в слово и replace:true. Если клиент трактует каждый новый itemId как новый блок, абзац выводится дважды. Обрабатывайте флаг replace:true: такой чанк заменяет уже выведенный текст тем же текстом, а не добавляет его.
Конфиг: reserveTokensFloor больше нет
Ключ agents.defaults.compaction.reserveTokensFloor вывели из схемы. Если он остался в openclaw.json, любая команда CLI падает: конфиг считается невалидным, и после ближайшего рестарта Gateway не поднимется. Доктор умеет это лечить сам.
openclaw config validate
openclaw doctor --fix
openclaw config validate подсветит имя ключа, openclaw doctor --fix удалит его. Добавлять ключ обратно руками, чтобы «починить поведение», не надо.
Сессия выбирает модель строго
fallbacks в agents.defaults.model защищает только primary по умолчанию. Если модель задана для конкретной сессии через sessions.patch, резервная цепочка больше не срабатывает: провайдер вернул 503, запуск падает явно, без перебора запасных. Это задокументированное поведение, просто его легко пропустить. Для строгих сессий закладывайте собственный резерв на стороне клиента или оборачивайте вызов ретраем.
Мелкие правки, которые тоже стоит учесть
Метод models.list теперь возвращает записи из agents.defaults.models, а не весь каталог провайдеров. В дефолтах chat.startup поле с провайдером переименовано в modelProvider.
Где ломается и когда не применять
Рецепт для тех, кто держит свой клиент поверх WebSocket Gateway: бот, дашборд, интеграция с CRM, мобильное приложение. Перед деплоем на 2026.9.6 проверьте, что в openclaw.json нет reserveTokensFloor, иначе после рестарта Gateway не вернётся. И отдельно зафиксируйте версии пакетов @openclaw/gateway-client и @openclaw/gateway-protocol с пином через --save-exact — стабильный релиз 2026.8.1, как советует документация по сборке клиентов.