Продолжаю делиться граблями, на которые я наступил в Claude Code. Как я ловил API Error: Stream idle timeout - partial response received
Дисклеймер: кажется, что всё это можно было и не ловить — по крайней мере в более простых системах я такие ошибки никогда не видел. Но раз уж начал упарываться в агентов, то почему бы не наступить на все грабли.
Проблема такая: оркестратор собирает SEO-статью на 8 000 слов, отдаёт редактору, пробует сохранить. Через 30 секунд тишины: API Error: Stream idle timeout — partial response received
Файл создан, но обрезан на месте, где стрим ушёл в idle.
❌ Первая очевидная неверная гипотеза: большой Write
Значит надо резать на чанки. Снизил лимит 15 000 → 8 000 → 6 000 → 5 000. Таймаут повторялся. Значит, дело не в размере записи.
✨ Настоящая причина: пересборка текста
Оркестратор не копировал готовый текст субагента. Он его пересобирал: переоформлял, перенумеровывал 28 сносок, «причёсывал» заголовки. Пока модель думала над форматированием, токены в стрим не эмитились. API считал соединение мёртвым и закрывал.
Решение РАЗ: passthrough + чанки ≤ 3 000
Вводим правило rules/common/safe-file-save.md:
➡️ Субагент возвращает строку оркестратору. Оркестратор копирует её в Write байт-в-байт — без «улучшений».
➡️ Разбиение планируется один раз до первого Write, потом проходится механически.
➡️ Лимит 3 000 символов на Write/Edit — потолок, при котором стрим не уходит в idle при честном passthrough.
➡️ Перед каждым Edit — сообщение 💾 Чанк K/M…. Иначе пользователь видит тишину и прерывает.
Если таймаут повторяется на 3 000 — спуск на 1 500. Если и там падает — это сеть, не контент.
И Recovery для обрезанных файлов
Повторный Write поверх частичного файла затирает уже сохранённое. Поэтому:
➡️ ls — проверить, что файл есть
➡️ Read — измерить длину
➡️ Edit (append) с точки обрыва, чанки по 3 000
Никогда не стартовать Write заново по тому же пути.
⭐️ Вторая волна: редактор
После фикса записи таймаут вернулся на возврате субагента-редактора. Вход 18 000 символов, выход 18 000 переписанного текста + отчёт «до/после» + метрики. Prefill и генерация занимают десятки секунд без эмита токенов. Retry не помогал: корень — объём выхода.
Решение ДВА: diff-mode
Вводим правило rules/common/editor-diff-mode.md. Редактор возвращает не переписанный текст, а список правок:
=== EDIT id=1 op=replace === FIND: Данное решение является инновационным продуктом REPLACE: VK Cloud управляет инфраструктурой — от ВМ до managed-БД REASON: редполитика + инфостиль === END EDIT ===
Лимиты: ≤ 60 правок, FIND ≤ 300, REPLACE ≤ 500, суммарный выход ≤ 8 000. Оркестратор парсит блоки и применяет через Edit.
Матрица по длине для глубокой редактуры:
➡️ ≤ 4 000 → классический
➡️ 4 000 – 20 000 → diff-mode
➡️ > 20 000 → секционный (одна H2 за вызов)
Пороги ниже именно для тяжёлых режимов — они удваивают выход за счёт отчёта «до/после».
Что в итоге то:
Два источника одной ошибки: оркестратор переформатирует перед Write, редактор генерирует слишком много на выход. Лечатся по отдельности: passthrough + чанки для записи, diff-mode для правок. Recovery закрывает остаточные случаи, когда таймаут всё-таки прилетел.
Я вроде не курю, но захотелось.
Как всегда ссылка на канал. Подписывайтесь

