Дисклеймер: в статье упоминается Meta - организация, признанная экстремистской и запрещённая на территории РФ. Статья - не прогрев и не реклама курсов/самопиар и пр.. Все логи, цифры и скрины - из реальных прогонов тестового аккаунта.
Всем привет!). В финале прошлой статьи (https://habr.com/ru/articles/1076972/) я обещал разбор Reasoning Lock - того самого бага, где рассуждающая модель тратит токены и отвечает пустотой. Разбор готов, правки в воркфлоу заказчика встают в бой, и я хочу выпустить его с живой метрикой, после нескольких дней наблюдений в проде за тем, как изменения работают. А пока счётчик тикает, публикую из бэклога мини - историю, которая созрела ещё в двадцатых числах августа - в разгар фурора вокруг загадочной stealth-модели. Фурор уже стих, но эксперимент от этого хуже не стал: за три дня стелс-модель "навайбкодила" воркфлоу на 127 нод, который реально ходит по API, генерирует медиа и публикует Reels. Ниже я покажу архитектуру, код, честный список косяков модели и моих собственных, и экономика эксперимента. Постараюсь вкратце и по существу.)
Цель, так сказать, эксперимента - нагрузочное тестирование свежей LLM в роли кодера на сложном распределённом пайплайне: пять внешних API, бинарные потоки, три десятка условий ветвления, асинхронные поллинги - и всё в одном воркфлоу! Сейчас на западном рынке бум автономных связок в духе "скрапинг-генерация фото/видео-автопостинг". Я сам контентом не занимаюсь - мне интересны пайплайны и отказоустойчивость. Но задача подходит как идеальное ТЗ!)
И тут совпало: с 20 по 25 августа на OpenRouter открылся бесплатный доступ к загадочной модели stealth/ox-alpha. Позже она деанонизировалась - FAQ OpenRouter это официально подтверждает: это Z.ai, GLM 5.3 Flash (z-ai/glm-5.3-flash в селекторе Cline). Расклад по ней такой: контекст 1М токенов, нативная мультимодальность (текст, картинки, видео на вход), заявка от Z.ai "efficient coding and long-horizon agent tasks" - всё вы про это читали и знаете). Релиз состоялся 26 августа, то есть стелс-окно дало неделю игры до официального анонса. Большой контекст, нулевая цена. Я открыл VS Code, запустил Cline и закинул ТЗ на полноценный медиа-конвейер в n8n.
За три дня (с 21 по 23 августа) ушло 60,9 млн токенов - 85,3% из них кеш-хиты, итоговый счёт по blended-цене $0,07/1M составил около $4. Суть что на выходе - воркфлоу на 127 нод (изначально 156, потом рефакторил), который реально ходит по API, генерит медиа и публикует Reels. Ниже - архитектура, код, честный список косяков модели и моих собственных, и экономика эксперимента.
ТЗ: не "сделай мне хайповые и залётные рилсы", а "ты - senior n8n solutions architect"
Все тут понимают что LLM - это не волшебник/экстрасенс. Банальное правило: чем точнее вход - тем меньше галлюцинаций на выходе. Поэтому в Cline я прописал не "придумай автопостинг с алертами в телеграм", а максимально (вроде как)) структурированный бриф с итерациями. Сокращённая версия реального промпта стала такой:
ROLE You are a senior n8n solutions architect. You produce production-ready, importable n8n workflow JSON. You never invent API parameters or node fields; when unsure, you say so explicitly. PROJECT CONTEXT БЭКЛОГ: «AutoContent-Factory v1.0» — автономный конвейер ИИ-аналитики трендов, генерации мультимедиа и автопостинга в Instagram на базе self-hosted n8n. КОНТУРЫ: 1 — парсинг конкурентов (ScrapeCreators API), формула виральности 1.5 — семантический фильтр (LLM-reranker, порог релевантности) 2 — AI-диспетчер (строгий JSON: сценарий/промпт видео/caption) 3 — мультимодальная генерация (видео/голос/обложка через OpenRouter) 5 — автопостинг (Instagram Graph API) API FACTS (from official docs) - 1 credit = 1 request; cache hits = 0 credits - GET /v1/instagram/user/reels — метрики БЕЗ caption - GET /v2/instagram/media/transcript — 10–30 s, timeout >= 60 s - HTTP 402 = out of credits; 5xx = transient RULES One contour per message. No secrets. Defensive JS (try/catch, null-checks). If ambiguous — ask ONE clarifying question.
Оглашу ключевые приёмы, которые сэкономили мне нервы:
Роль вместо просьбы. "Senior-архитектор" меняет тон генерации: модель пишет defensively, а не разговорно - упрощенно.
Явно запрещено выдумывать параметры. Нет уверенности - скажи и добавь в список "VERIFY MANUALLY".
Итерации по контурам. По одному контуру за сообщение - модель не путается в зависимостях.
Output Contract = Один JSON-блок + инструкции по импорту + список сомнительных параметров.
Единственное что забыл дать модели по задачам, в самом конце сборки готового воркфлоу - так это детальную техническую документацию. Так бы и статью написал более детальнее и проще!)

Архитектура воркфлоу: 5 контуров, 127 нод

Честная арифметика воркфлоу, чтобы никто не пересчитывал за меня: 127 = 113 нод в пяти контурах (23 + 17 + 17 + 37 + 19) + 2 входных триггера (Schedule и Manual) + 4 disabled-заглушки под будущие итерации + 8 стикеров-документации. Рабочих нод, соответственно, 115: 113 контурных + 2 триггера. Подробнее поясню каждый контур:
1 -й контур: назовём "Разведка" (23 ноды)
Схема такая: Schedule (24ч) - список конкурентов - Reels через ScrapeCreators - математика виральности: views > avg × 2.5 - тег TRENDING - для трендовых дотягиваются caption (/v1/НЕЛЬЗЯgram/post) и транскрипт (/v2/instagram/media/transcript, таймаут 60с; null - caption-only). Пока список конкурентов - статические тестовые хендлы: для реального внедрения подставляются желаемые ниши.
Контур 1.5: назовём "Семантический фильтр" (17 нод)
LLM-reranker оценивает релевантность в выбранной нише (я выбрал по автоматизации на n8n) по шкале 0-1. На роль реранкера я выбрал Qwen3 Reranker 8B через chat/completions. В его промпт зашит рубрикатор с живыми примерами: "Строим LLM-агента в n8n для обработки заявок" = 0.95 (core ниша), "Как настроить ChatGPT" = 0.75 (AI productivity), ИИ в целом = 0.5-0.69, смежное (саас бизнес) = 0.2-0.49, личные влоги = 0.0-0.19. Всё ниже порога улетает в тупик Drop: Below Threshold. Без этого контура данная "фабрика" генерировала бы контент по случайно залетевшему личному влогу автора контента.
2 -й контур: AI-диспетчер (17 нод)
Модель не копирует чужой пост! Зачем штамповать однотипный контент. Она "выжимает ДНК виральности" (хук, триггер, формат, призыв) и собирает оригинальную идею. Выход - строгая JSON-схема: angle, hooks, voice_script (120–160 символов), video_prompt, НЕЛЬЗЯgram_caption. Валидный черновик падает в Google Sheets со статусом DRAFT.
3- й контур: медиа-цех (37 нод)
Видео:seedance-2.0-mini с фулбэком на veo-3.1-lite, асинхронный поллинг (Wait 10s × 20 попыток). Голос: TTS отдаёт сырой PCM, который конвертится в WAV на лету. Конфиг в "Clean Voice Script" рассказывает о себе ещё одну вещь: флаги ARCHIVE_TO_DRIVE=false и MUSIC_ENABLED=false - это эконом-конфиг: seedance-2.0-mini/ 480p/ 5s с фолбэком на veo-3.1-lite. Обложка: image-generation с неоновым тех-вайбом. Всё с ретраями, варнингами и статусами MEDIA_READY / MEDIA_FAILED.
Последний контур: дистрибуция (19 нод)
Внутри - ещё один сюрприз: склейка видео с голосом через ffmpeg (Write -Exec -Read в /tmp). Голос опционален: нет голоса = видео уходит как есть под ключом final_mp4. Плюс у контейнера Instagram свой поллинг FINISHED - Wait 5s * 12.
Google Drive (upload + share publicly) - Instagram Graph API (контейнер REELS - publish) - permalink - обновление Sheets - отчёт в Telegram.
Диспетчер статусов на Google Sheets
Чтобы 127 нод не запутались, на каком этапе находится каждый ролик, я не стал городить сложную базу данных, а сделал простой диспетчер статусов прямо в Google Таблицах.

Рефакторинг ради стабильности: было 156 - стало 127
Первая версия собиралась по принципу "если соберёт воркфлоу - то лишь бы работало" и раздулась до 156 нод. Минус 29 за пару вечеров:
дублирующиеся error-ветки сведены в единый паттерн
Failed? → 402? → alert / fail-open;Честности ради: в списке
disabled - reserve-нода Search google, которую стелс-модель напланировала "на будущее" и которую я не стал удалять. Пусть лежит.)все медиа-конфиги и модели вынесены в одну
Code-ноду (Clean Voice Script)вместо россыпиSet-нод;убраны промежуточные хэндоф-заглушки от старых версий архитектуры.
Раскладка по типам нод:
Тип | Количество | Зачем |
IF (условия) | 30 | ошибки, 402, статусы, наличие бинарников |
Code (JS) | 28 | парсинг, нормализация, PCM в WAV, конфиги |
Telegram | 12 | алерты на каждый критический сбой |
HTTP Request | 11 | все внешние вызовы |
NoOp | 11 | точки передачи между контурами + тупики дропов |
Sticky Note | 8 | документация прямо на канвасе |
LangChain | 6 | 2 агента + 2 модели + 2 structured-парсера |
Google Sheets | 4 | статистика: append + 3 update |
StopAndError | 4 | жёсткий стоп при 402 |
Триггеры | 3 | Manual, Schedule, ExecuteWorkflow-триггер (disabled) |
Disabled-заглушки | 3 | 2 ноды scrapeCreators, Call "Hunter_Media" *p.s. Воркфлоу я назвал Hunter content = отсюда и названия контуров |
Set | 2 | финальные выходы контуров 1 и 1.5 |
Google Drive | 2 | upload + share publicly |
SplitInBatches | 1 | цикл по хендлам |
Wait | 1 | поллинг видео (10s) |
НЕЛЬЗЯagram (community) | 1 | публикация Reels |
Можно чётко увидеть, что больше трети нод - это защитная логика. Это в принципе осознанная цена автономности.
Теперь как говориться, инженерная нутрянка
Жемчужина: PCM - WAV на лету
TTS-модель отдаёт сырой PCM (24 кГц, 16 бит, mono) без контейнера - ни n8n, ни НЕЛЬЗЯgram такой поток не понимают. Модель сгенерировала Code-ноду, пришивающую корректный RIFF-заголовок:
function wavHeader(len) { const sr = 24000, ch = 1, bits = 16; const b = Buffer.alloc(44); b.write('RIFF', 0); b.writeUInt32LE(36 + len, 4); b.write('WAVE', 8); b.write('fmt ', 12); b.writeUInt32LE(16, 16); b.writeUInt16LE(1, 20); b.writeUInt16LE(ch, 22); b.writeUInt32LE(sr, 24); b.writeUInt32LE(sr * ch * bits / 8, 28); b.writeUInt16LE(ch * bits / 8, 32); b.writeUInt16LE(bits, 34); b.write('data', 36); b.writeUInt32LE(len, 40); return b; } const pcm = await helpers.getBinaryDataBuffer(i, 'voice_mp3'); const wav = Buffer.concat([wavHeader(pcm.length), pcm]); bin.voice_mp3 = await helpers.prepareBinaryData(wav, 'voice.wav', 'audio/wav');
Я перепроверил каждый байт: 44-байтный заголовок - все вычисляются, а не хардкодятся, и используются правильные binary-helpers n8n, а не наивное item.binary.data
Static Data: аккумулятор цикла без дублей
Логика сбора трендов: крутим цикл по хендлам в нише, бережно копим данные в static data воркфлоу, а на выходе вычитываем этот буфер, чистим его и до кучи делаем финальную дедупликацию по URL :
// внутри цикла: const sd = $getWorkflowStaticData('global'); sd.acf_trending = sd.acf_trending || []; sd.acf_trending.push(...$input.all().map(i => i.json)); // после цикла: const rows = sd.acf_trending || []; sd.acf_trending = []; // состояние не течёт между запусками const seen = new Set(); return rows.filter(r => { const key = r.post_url || r.shortcode; if (seen.has(key)) return false; seen.add(key); return true; }).map(r => ({ json: r }));
402 не равно 5xx: две разные смерти сервиса
Система различает между "сервис временно умер" и "кончились у.е.". Универсальная проверка, которую модель штампует в каждой error-ветке:
const e = $json.error || {}; const sc = Number($json.statusCode || e.statusCode || e.status || 0); const msg = String(e.message || ''); const is402 = sc === 402 || msg.indexOf('402') !== -1;
Политика в данной схеме такая: 402 = алерт в Telegram + StopAndError (штамповать ретраи без денег бессмысленно); 5xx - retry помноженное на 3 = fail-open: хендл пропускается, конвейер живёт. Отвал TTS не убивает рилс просто уйдёт без голоса, с warning в таблице.
Формула виральности в коде - не магическое число в условии, а именованная константа:
```javascript // Phase 1: average views per handle; views > avg * 2.5 => tag TRENDING. const TREND_MULTIPLIER = 2.5; ```
Под неё - defensive-обёртка pickNumber(), вытаскивающая счётчик просмотров из какой угодно формы ответа API.
Отдельная жемчужина - fail-open нода реранкера. Если Qwen3 умер после трёх ретраев, всем документам присваивается нейтральный 0.5 = который порог 0.75 честно отсекает. Конвейер не ломается: он просто тихо пропускает раунд. Комментарий в ноде это признаёт дословно: "0.5 < MIN_RELEVANCE_SCORE (0.75), so the filter drops them; pipeline stays healthy".
Финальный мерджер бинарников
HTTP-ноды в file-режиме стирают бинарники из $input. stealth/ox-alpha сама предложила вытягивать их напрямую из нод-производителей, минуя текущий поток:
function grabBinary(nodeNames, keys) { for (const n of nodeNames) { try { const bin = ($(n).first() || {}).binary || {}; for (const k of keys) if (bin[k] && (bin[k].data || bin[k].fileName)) return bin[k]; } catch (e) {} } return null; } const vid = grabBinary(['Fetch Video'], ['video_mp4', 'video', 'data']); const voi = grabBinary(['PCM to WAV', 'Generate Voice'], ['voice_mp3']); const cov = grabBinary(['Download Cover', 'Normalize Cover'], ['cover_png']);
Где модель тупила и мои собственные затупы
Без этого подраздела статья была бы наверное в стиле пресс-релиза, так что вот самы краткий список "болячек" (хотя как понимаете на 60 млн. токенов их было уйма):
Косяки модели:
require(‘crypto’)в Code-ноде. В n8nrequireнедоступен - пришлось душить Cline переписывать на встроенные функции.Google стирает бинарники. Google Drive нода возвращает только свой json, и голос/видео терялись после апдейта строки. Родилась
нода Rebuild Handoff Item, восстанавливающая item из нод - производителей.Фантомные ноды. Пару раз в JSON приезжали
type/typeVersion, которых нет в нынешней версии n8n - сверял вручную.Хардкод
IG_USER_ID.Модель не догадалась вынестиID в credentials- в коде торчит константа. Для теста ок, для запуска - выносить в env.
Где я сам накосячил (выловил только на ручном аудите):
Порог реранкера разъехался. В стикере-документации
MIN_RELEVANCE_SCORE = 0.75, а вIF-нодена время отладки стоит>= 0.4- и я честно забыл вернуть. Поймал себя на том самом"одном и том же релевантном рилсе каждый день". Вывод: конфиг должен жить в одном месте, а не в стикере и в ноде раздельно.Поллинг видео 20 помножить 10с. В часы пик очереди
Veo/Seedanceмогут быть длиннее -MAX_ATTEMPTSпридётся поднять.
А теперь пример затупов/косяков, и почему это не провал:

Видео не сгенерировалось = драфт не потерян, помечен MEDIA_FAILED. Публикация не прошла = алерт с причиной и ссылкой на Drive для ручной загрузки. Мелочь для внимательных: Telegram съел подчёркивания, и в сообщении красуется "MEDIAFAILED" - можно считать это бесплатной цензурой маркдауна.
Реальный запуск воркфлоу в цифрах: сколько это ест ресурсов

Скажу честно: когда я запускал этот тест (ведь ждал в конце хоть и кривую копеечную генерацию), то реально скрестил пальцы)). Ожидания оправдались: лог выполнения (Execution) выдал заветный зеленый статус!)))
Для тех, кто крутит тяжелую автоматизацию, эти цифры на скрине - самый сок:
Время выполнения (4м 13сек): Для сквозного процесса, где внутри сидят генерация видео через API (с постоянным поллингом статуса), озвучка от Gemini и кастомная склейка байтов, четыре минуты с копейками - это отличный результат. Основное время, понятное дело, уходит на ожидание ответов от серверов генерации.
Потребление памяти (8 MB): Весь запуск огромной махины сожрал всего 8 мегабайт. Помните наш трюк с пакетной сборкой трендов в
$getWorkflowStaticData('global')вместо раздувания стандартного контекста внутри цикла? Вот это и есть главное доказательство того, что оптимизация сработала. Мы не держим тяжелые бинарники в оперативной памяти n8n, благодаря чему сервер чувствует себя прекрасно и не улетает в Out of Memory.
А вот и результат в профиле


Рилс ушёл в публикацию через Graph API: в таблице статус PUBLISHED с permalink, у поста дата "3 дн.". Цепочка отработала целиком: скрапинг - реранкер - диспетчер - медиа-цех - Drive - НЕЛЬЗЯgram. Поясню: это тестовый прогон на тестовом аккаунте - целью была проверка воркфлоу, а не сбор просмотров(!). Факт: текст, обложка, видео и публикация сгенерированы цепочкой; я лишь нажал ExecuteWorkflow.
Экономическая сторона: 60,9 млн токенов за примерно 4 у.е.

Вопрос возникает сходу: почему так дёшево?! Во-первых, stealth-окно было бесплатным. Во-вторых, итерактивная разработка в Cline - это перечитывание одного и того же контекста, и prompt кэшинг превращает 85% запросов в кэш-хиты.
Сразу закрою ожидание: это не обзор модели по бенчмаркам - таких с релиза вышло десяток, и все пересказывают одни и те же таблицы. Здесь 127 нод, живой тестовый НЕЛЬЗЯagram и счёт в долларах за реальные прогоны.
И факты по модели после деанона: Z.ai GLM 5.3 Flash - нативная мультимодальность (текст, картинки, видео на вход), контекст 1М токенов, релиз 26 августа. Цены сейчас: $0.075/$0.25 за 1M (in/out) при скидке Z.ai −50% до 9 сентября, кэш-рид $0.015. И вишенка из статистики: по объёму токенов в топ-3 приложений модели входит Cline - тот самый, через который это всё и "навайбкодилось".
Сколько бы стоил такой объём на платных моделях (по самой верхней таксе, 90/10 input/output). Да, модели в таблице не по принципу "топ под задачу"! Честно- я просто ткнул пять моделей из разных ценовых категорий каталога OpenRouter, чтобы показать вилку. Это сравнение ценников, которые я посчитал по среднему, а не бенчмарк.
LLM | Цена за 1M (in/out) | Оценка за 60,9M |
Anthropic: Claude Opus 4.8 | $5 / $25 | около 426$ |
OpenAI: GPT-5.6 Terra | $2 / $12 | около 183$ |
Anthropic: Claude Sonnet 5 | $2 / $10 | около 171$ |
Qwen: Qwen3.8 27B | $0,35 / $2,75 | около 36$ |
DeepSeek: V3.1 Terminus ( единственный минус упомяну что у модели контекст всего 164К.) | $0,27 / $1 | около 21 $ |
stealth/ox-alpha + кэш | $0,07 | около 4$ |
То есть формально, если говорить про именно LLM из таблицы, то все пять под задачу "агентный кодинг марафон" подходят по позиционированию, разница - в ценовой категории и размере окна. Единственная реальная оговорка что 164K у DeepSeek против проделанных мега сессий. И да, парадокс, который можно подчеркнуть: бесплатная загадочная модель построила фабрику, которая крутится на копеечных DeepSeek, Gemini-flash и seedance, которые жгут центы за публикацию.
Итоги
Модель - это джуниор разраб с энциклопедической памятью и нулевым опытом. Защитный код (
defensive-парсинги, fail-open, корректная бинарная арифметика) она выдаёт только тогда, когда защитный код запрошен в ТЗ. Мой промпт - не магия, а чёткие инструкции.Бенчмарки не показывают главное. Анонимная stealth-модель бесплатно вытянула в принципе стабильную сборку с пятью API, бинарниками и асинхронщиной - это проверяется только спустя наверное с пару десятков запусков воркфлоу.
Отказоустойчивость - это наверное фишка номер 1. Ведь, блин, согласитесь, что
ценность не в том, что конвейер работает, когда всё работает, а в том, что он не теряет данные, когда всё падает!)
Зоны роста воркфлоу
От себя, могу в теории предложить развитие данного проекта (если бы это был реальный кейс) примерно в таком направлении:
разбор монолита на три воркфлоу
(Radar / Generate / Publish),Telegram-бот с
human-in-the-loopуправлением ("Опубликовать / Перегенерировать")ветка нейроаватара ( модель, к примеру,
HeyGen: Avatar IVнедавно вышедшая - хорошо подойдёт на эту роль);
Вместо заключения
Из каждого угла сейчас можно прочитать: "...ИИ заменит программистов и ИТшников все, просто скажи “сделай мне сайт”...". Этот эксперимент = аргумент против. Модель за три дня сожгла 60,9 млн токенов, чтобы получилось то, что получилось: отличную заготовку, требующую ручного аудита каждого порога, каждой ноды, каждого байта заголовка WAV. "Сделай мне сайт" она бы сожгла за вечер - вместе с продакшеном. Заменит не ИИ. Заменит человек, который научился им пользоваться, тем же, кто умел пользоваться компилятором и Stack Overflow. Инструмент новый. Профессия та же: отвечать за результат.

