Дисклеймер: в статье упоминается Meta — организация, признанная экстремистской и запрещённая на территории РФ. Статья — не прогрев и не реклама курсов/самопиар и пр.. Все логи, цифры и скрины — из реальных прогонов тестового аккаунта.

Всем привет! В финале прошлой статьи я обещал разбор 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‑блок + инструкции по импорту + список сомнительных параметров.

Единственное что забыл дать модели по задачам, в самом конце сборки готового воркфлоу — так это детальную техническую документацию. Так бы и статью написал более детальнее и проще!:‑)

 Первые шаги: stealth/ox-alpha шуршит в консоли... пишется JSON-конфиг для нод
Первые шаги: stealth/ox‑alpha шуршит в консоли... пишется JSON‑конфиг для нод

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

 В процессе сборки: примерно 2/3 готового воркфлоу на холсте
В процессе сборки: примерно 2/3 готового воркфлоу на холсте

Честная арифметика воркфлоу, чтобы никто не пересчитывал за меня: 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 Таблицах.

Каждый драфт проходит цепочку статусов DRAFT - MEDIA_READY - PUBLISHED (или MEDIA_FAILED / PUBLISH_FAILED), обновление - по source_url
Каждый драфт проходит цепочку статусов DRAFT — MEDIA_READY — PUBLISHED (или MEDIA_FAILED / PUBLISH_FAILED), обновление — по source_url

Рефакторинг ради стабильности: было 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‑ноде. В n8n require недоступен — пришлось душить 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 придётся поднять.

А теперь пример затупов/косяков, и почему это не провал:

 Самое крутое - система не умерла молча. Мне в Telegram прилетел аккуратный алерт со ссылкой на конкретную ошибку, а сам черновик видео спокойно остался лежать в таблице
Самое крутое — система не умерла молча. Мне в Telegram прилетел аккуратный алерт со ссылкой на конкретную ошибку, а сам черновик видео спокойно остался лежать в таблице

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

Реальный запуск воркфлоу в цифрах: сколько это ест ресурсов

 Тот самый момент, когда честно скрестил пальцы на все 4 минуты)
Тот самый момент, когда честно скрестил пальцы на все 4 минуты)

Скажу честно: когда я запускал этот тест (ведь ждал в конце хоть и кривую копеечную генерацию), то реально скрестил пальцы)). Ожидания оправдались: лог выполнения (Execution) выдал заветный зеленый статус!))) 

Для тех, кто крутит тяжелую автоматизацию, эти цифры на скрине — самый сок: 

  • Время выполнения (4м 13сек): Для сквозного процесса, где внутри сидят генерация видео через API (с постоянным поллингом статуса), озвучка от Gemini и кастомная склейка байтов, четыре минуты с копейками — это отличный результат. Основное время, понятное дело, уходит на ожидание ответов от серверов генерации. 

  • Потребление памяти (8 MB): Весь запуск огромной махины сожрал всего 8 мегабайт. Помните наш трюк с пакетной сборкой трендов в $getWorkflowStaticData('global') вместо раздувания стандартного контекста внутри цикла? Вот это и есть главное доказательство того, что оптимизация сработала. Мы не держим тяжелые бинарники в оперативной памяти n8n, благодаря чему сервер чувствует себя прекрасно и не улетает в Out of Memory. 

А вот и результат в профиле

Обложка от google/gemini-3.1-flash-image: кириллица читается, модель сама придумала контраст "грустный базовый ChatGPT vs n8n"
Обложка от google/gemini-3.1-flash‑image: кириллица читается, модель сама придумала контраст «грустный базовый ChatGPT vs n8n»
Кадр: seedance снял ровно то, что просил video_prompt - интерфейс n8n без людей. Caption собран по схеме: боль - ценность - CTA с кодовым словом + 8 хэштегов
Кадр: seedance снял ровно то, что просил video_prompt — интерфейс n8n без людей. Caption собран по схеме: боль — ценность — CTA с кодовым словом + 8 хэштегов

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

Экономическая сторона: 60,9 млн токенов за примерно 4 у.е.

Да, +217211% - до "эксперимента" аккаунт будто проставивал
Да, +217211% — до «эксперимента» аккаунт будто проставивал

Вопрос возникает сходу: почему так дёшево?! Во‑первых, 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. Инструмент новый. Профессия та же: отвечать за результат.