Дисклеймер: в статье упоминается 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‑блок + инструкции по импорту + список сомнительных параметров.
Единственное что забыл дать модели по задачам, в самом конце сборки готового воркфлоу — так это детальную техническую документацию. Так бы и статью написал более детальнее и проще!:‑)

Архитектура воркфлоу: 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. Инструмент новый. Профессия та же: отвечать за результат.
ChimsK
The status manager in Sheets is the part I’d have expected you to skip, and it’s doing more work than a database would have. Keying updates by source_url means a re-run recognises what’s already been through, which is the thing most of these pipelines get wrong.
One question about the edge of that. The Instagram container polls FINISHED for 12 × 5s, then you write PUBLISHED to Sheets. If the publish succeeds but the Sheets write fails, or the polling times out on a container that actually completed, does the next run see DRAFT and publish again? Asking because that gap between “the side effect happened” and “we recorded that it happened” is where I’ve been bitten, and it only ever shows up in production.
Also liked “you never invent API parameters; when unsure, say so explicitly” plus the VERIFY MANUALLY list. Though it’s still an instruction rather than a guarantee — the model can comply 97% of the time and the 3% arrives as an importable JSON with a plausible field name that doesn’t exist. Did you end up validating generated node configs against the n8n schema before import, or was reading them enough at this scale?
gotham_engineer Автор
Hello, ChimsK! Thank you for such deep, production-grade engineering questions. It’s incredibly refreshing to discuss the actual gaps between "generated" and "bulletproof" architecture in the comment section.To give you the full context: this entire pipeline was a fast-paced stress-test of the stealth/ox-alpha (GLM 5.3 Flash) model under a heavy agentic coding marathon. It was never intended to be packaged as a commercial case or put into active production—the 127-node JSON workflow is currently sitting idle as a snapshot of what a low-cost LLM can orchestrate in 3 days. However, you hit the exact architectural pain points that separate a demo from an enterprise system.Here is how these two edge cases look from my perspective:1. The Publication Gap & Distributed State ConsistencyYou are absolutely right about the danger of the gap between a side effect happening in Meta's infra and recording it in Google Sheets. In the experimental setup, if the Nginx/n8n process crashed or the Google Sheets API timed out after a successful Instagram publish, the next cron run would indeed see a DRAFT status and attempt a duplicate upload.To fix this for a real production environment, the step must be made idempotent. Since Instagram Graph API handles Reels in a two-step process—creating a media container (POST /media) and then publishing it (POST /media_publish)—the state transition must be strictly decoupled:Step 1: Generate the media container ID from Meta and immediately commit this ID and timestamps to Redis/Sheets before initiating the final publication.Step 2: On any re-run, the node router checks if a container ID already exists for the given source_url. If it does, instead of uploading a duplicate, it executes a GET request to verify the container's status on Meta’s side. If it's already published, we simply force-update the Sheet to PUBLISHED and fail-open.2. The 3% Hallucination & JSON Schema ValidationYour 97% vs 3% estimation is spot on. Models excel at mimicking plausible naming conventions, which is highly dangerous when n8n node parameters change across versions (e.g., typeVersion mismatch).For this specific experiment, I did not use an automated validator against the official n8n JSON schema. Given the scale and the rapid iteration cycle with Cline, a meticulous manual code audit during the import phase was enough to catch things like ghost parameters, phantom fields, or illegal require() calls inside JavaScript Code nodes (which I documented in the article's flaws section).However, if I were to scale this into a fully autonomous, self-healing framework without a human-in-the-loop audit, injecting a strict schema validation step (using n8n's community schema definitions) directly into the Cline output pipeline would be an absolute mandatory layer of defense.Thanks again for the brilliant breakdown. It's precisely these edge cases that make backend engineering so fascinating!