Pull to refresh
16K+
1
Артём Сапун@gotham_engineer

AI Automation Engineer

15,5
Rating
3
Subscribers
Send message

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!

Если использовать стандартные ноды ожидания Wait внутри самого n8n для проверки лока под нагрузкой = естественно поймать Out of Memorу. Когда жесткий наплыв с таргета, сотни висящих в памяти процессов n8n мгновенно сожрут все ресурсы VPS.

Поэтому в уровне 2 моей статьи описана сама фишка в схеме = внутри n8n никто ничего не ждет) Лок работает по неблокирующему принципу Drop-if-Locked на стороне Redis: прилетает хук, мы делаем проверку ключа лока = если лок занят (обработка уже идёт), этот поток n8n тут же завершает выполнение. Он не уходит в режим ожидания, не запускает таймеры = он просто мгновенно умирает. Память сервера свободна. Само входящее сообщение при этом уже безопасно лежит в буфере Redis (RPUSH). Выгребать этот буфер будет только самый первый поток, который этот лок и захватил. Он отработает паузу дебаунса, а затем атомарным LPOP вычистит всю очередь до нуля.

Вы правы полностью = блокирующий лок внутри самой n8n опасен!) Именно поэтому архитектура перенесена на Redis, чтобы n8n выполнял только быструю линейную работу без "засыпаний" в памяти.

да, в том то и фишка: на вопрос даже не ЗАЧЕМ агент это сделал, а просто ДЕЛАЛ ЛИ - в ответ отрицание. И вы правы - чужого системного промта не видно,увы

Хороший разбор, особенно зацепило правило "после записи состояние перечитывается". Поделюсь случаем в тему: недавно поймал похожий семантический сбой на уровне повыше - при тестировании автономного ИИ-агента (Cline + glm-5.3-flash), у которого был доступ к Browser Use. Ситуация один в один как ваш третий случай про " запрос принят, но разошелся с замыслом". Из-за конфликта внутренних системных промптов агент отказался генерировать тестовый джайсон файл, но решил по его мнению "нанести пользу" иначе. Он увидел открытую вкладку в браузере, сам распарсил DOM-дерево и бахнул клик публикации. С точки зрения API — статус 200 OK, впринципе норм и соблюден. С точки зрения логики пользователя как то не очень то). А самое веселое, что при попытке перечитать состояние постфактум и спросить агента в чате "Зачем сделал?", он из-за очистки фонового контекста выдал галлюцинацию отрицания и сказал, что ничего не делал. Агентные слои сейчас - это получается порой риск ввиду таких скрытых ошибок

Доброго времени суток! Отличный разбор) Плюс за честность, детальный таймлайн аварии и чистую команду ремонта через compose с запретом трогать зависимости! Отдельный плюс за тезис про то, что "healthy контейнера - не доказательство работоспособности бизнес-цепочки"!)

Обычно все успокаиваются на зелёной плашке в мониторинге, а тут такая засада. Знакомая ситуация...бррр.. Недавно на self-hosted n8n ловили отказ точно такого же класса: снаружи всё выглядело как просто случайный сетевой таймаут, а внутри оказалась гонка данных на общем Redis-ключе. И как у Вас один в один похоже - "очень похоже на медленную базу", да и логи идеальные. Раскрутить получилось только когда сел руками сопоставлять таймстампы двух параллельных экзекушн.

По поводу Вашего техдолга)) хочу спросить: Служебные воркфлоу (тот же SQL-мост) в отдельный пул планируете выделять вообще отдельной инсталляцией n8n или просто разнесением очередей по разным воркерам внутри той же самой инсталляции? Я такое видел в проде на нагруженных проектах, и у каждого, мягко говоря, свои специфические затыки... Интересно, в какую сторону вы смотрите?

Ваша правда: пока токен жив, параллельные запросы работают без проблем. Затык именно в момент ротации раз в сутки.

Могу по себе сказать: Redis с TTL пожалуй лишь один из вариантов, и без атомарной блокировки (вроде SET NX или flock) от гонки в момент удаления ключа он не спасет по большей части. Пачка параллельных хуков все равно может синхронно ломануться в API. Проблема специфическая как оказывается специфичная и даже скрытая = общался по этому вопросу с интегратором, у которого за плечами более 240 кейсов, и даже там этот момент со сгоранием долбанного refresh_token на нагруженных проектах вызывал ступор.

В любом случае, круто, что подняли эту тему. Было приятно подискутировать и обменяться опытом!) Ждем новых разборов по специфике работы с CRM))

Спасибо за развернутый бэкенд). Логика понятна: про expires_at в БД — абсолютно рабочая схема для большинства API впринципе. Но блин, конкретно с amoCRM есть одна жесткая подводная засада, из-за которой Redis с TTL либо аналог в памяти приходится городить с самого первого запроса. Просто при каждом обновлении access-токена старый refresh-токен моментом сгорает и выдается пара новых. Если на систему прилетает два параллельных хука ( типа юзер отправил два быстрых сообщения подряд) = два curl-запроса на обновление токена улетают одновременно. Что на выхлопе получается гонка данных: первый запрос обновит ключи, а второй падет из-за того, что его refresh-токен уже аннулирован. А итог - интеграция намертво ложится, пока клиент руками заново не авторизуется.Поэтому кэш в оперативной памяти с блокировкой повторных запросов на обновление - это в amoCRM становится вынужденная мера безопасности, и пофиг что в сутки идет всего 10 запросов. Спасибо ещё раз за интересную и продуктивную дискуссию))

Спасибо за детальный разбор кода и отличные конструктивные вопросы по логике!)) Постараюсь вкратце)

1.По поводу HTML-парсинга против регулярок.Идея с кастомными HTML-тегами (вроде <phone.....</phone>) хорошая, я её гонял на этапе проектирования контура. Но в проде вылезли грабли: на fallback-модели (в пики подхватывает Qwen через OpenRouter , сначала была Llama через грок) нейронка при генерации длинных ответов иногда тупо "забывает" закрывать теги, путает их местами или нафиг экранирует знаки < > как HTML-сущности. В итоге штатные HTML/XML парсеры в n8n на таком выводе просто падали по синтаксической ошибке.Текстовые маркеры в верхнем регистре ([VERDICT:...]) и регулярки оказались тупее, это факт...но тупо надежнее!) Флаги gm и универсальный "пылесос-очиститель" /[A-Z_]+:\s*[^\]]*/gi вытаскивают сущности, даже если модель поплыла по форматированию. А сам человекочитаемый блок с анкетой в конце - это внутренний такой "черновик" для самой LLM в рамках сессии LMemory, чтобы она не теряла контекст. Перед отправкай клиенту этот кусок всё равно срезается нодой Format Response, так что юзер его не видит.

2. Про нарезку на 180 и 140 символов.Тут в статье из-за сокращения кода получился визуальный парадокс) Логика там как раз каскадная. Нода Format Response сначала нарезает сырое полотно на абзацы (лимит 180 символов = это чисто визуальный ориентир для предложений, чтобы текст на экране смартфона не выглядел как спам-рассылка - и тут скорее , так сказать "эстетические пожелания заказчика"... А вот финальный контур отправки (сама нода Split AI Response) уже берет этот готовый красивый текст и жестко пилит его по предложениям на чанки строго до 140 символов, чтобы отправлять их в Директ порциями через цикл с Typing Delay. Так что один большой смысловой абзац может улететь двумя короткими сообщениями с имитацией живого набора текста, что визуально считывается клиентом как общение с человеком( и впринципе мало клиентов понимало что они вообще с ии говорят = что пришлось докручивать ,из юридических соображений, на штатное "Здравствуйте, я ИИ - ассистент ателье ХХХХХ" )

3. Про тег "говнокод"..) А вот тут вы попали в самую точку, тег висит не просто так) На самом деле, этот проект вытрепал мне столько мозгов и нервов, сколько ни один другой. И дело было не столько в самой разработке, а в заказчике, точнее скорее непонимании того что он хочет = не так легко и не по щелчку. Перед самым запуском и финальным расчетом мне кидали правки в промпт 6 раз(!). А в первые две недели после внедрения (на период бесплатного теста и гарантии) начался сущий ад — прилетал бесконечный вал скринов и сообщений в духе "твой ИИ говорит не как живой менеджер и не так запятые ставит". Я в какой-то момент вообще перестал семье время уделять (а когда дочери 14 лет, а сыну 1,5 года — это критично), зашился полностью в вылизывании того, что по определению детерминированным быть не может.В итоге просто ткнул пальцем в пункты подписанной оферты и прямо сказал, что сегодня же всё отключаю к чертям до выяснения отношений. Только после этого наступила тишина и ко мне прислушались) Сейчас, к слову, продукт крутится уже 4-й месяц, всё стабилизировалось и работает нормально - на октябрь расширение хотят на ещё мессенджер, к слову меня заказчик не трогает и я их))

опечатка promt в имени поля Redis-ноды, на которую завязана куча логики и которую теперь тупо и не охота трогать - официально считается частью этой так сказать выстраданной архитектуры)) ещё раз спасибо Вам за оценку кейса)

Хороший, объёмный разбор. Вы подтверждаете про прожорливость Falco и Tetragon на живых системах. Смотрите, хочу вопрос задать Вам как специалисту: 3 месяца в проде крутится связка n8n + Redis 7 в докере на чистой Ubuntu 6.8. Сервер скромный, 4 ГБ оперативки, поэтому каждый мегабайт оверхеда от логгеров критичен. Подумывал затащить eBPF для безопасности контейнеров, но, судя по вашим сценариям, объемы логов при плотном потоке данных просто сожрут дисковый I/O и память.Подскажите, а если вместо eBPF заворачивать логи докер-демона напрямую в systemd-journald с жестким лимитом (к примеру, SystemMaxUse=500M) - насколько это снижает общую нагрузку на хост по сравнению с тем же Falco? Стоит ли переходить на journald в мелком контуре?

Благодарю за развернутый фидбэк!)) По ссылке детально изучу). Знаете, н самом деле, на контрасте со стеком n8n + amoCRM, работа с файлами в Битриксе выглядит как отдельный вид, если так сказать можно) .В amoCRM файлового API в привычном понимании долгое время вообще не было вроде как (все просто кидали ссылки во внешние облака), поэтому там связка с n8n и Redis подгружается на автомате, как базовый буфер. А вас в битриксе, получается, система пытается всё хранить внутри (в UF или диске), но из-за этого наворачивает жесткие лимиты на транспорт (те самые 2 рпс и base64). Извечный спор: монолит со своими правилами против распределенного кастомного стека...

Спасибо за фидбэк - учту что можно в тг напрямую))

Про бачи и кэш Вы правы, для старта этого за глаза, иначе TTM улетит в бесконечность. Ну а до кафки и 40 бирж еще, мягко говоря, дорасти надо) Респект за плотный диалог и пищу для ума)

Логика абсолютно железная!) спасибо за развернутый ответ! Проектирование L1/L2 слоев на старте реально верный способ закопаться на месяцы и похоронить MVP. Я как раз на днях столкнулся с похожим выбором итераций. Поделюсь: проектирую кастомный веб-виджет для чата на сайт (на Тильде). Трафик там пока небольшой, до 50 лидов за пару часов, но данные нужно синхронизировать в реальном времени с CRM.

И я всё думаю, как у вас вот в схеме: с одной стороны, хочется сделать просто и по классике = складывать сессии в локальный SQLite на бэкенде виджета, а n8n пускай дергает вебхуки. Но блин, с другой то стороны, как говорится, мозг шепчет сразу развернуть Redis Queue для асинхронного буфера, чтобы намертво защититься от Race Conditions, если несколько юзеров кликнут одновременно (хотя пока такого в проекте не было, по утверждению заказчика).

По вашему опыту работы с потоками событий, на таких малых объемах SQLite в проде будет нормальный рабочий компромисс ради скорости запуска, или лучше сразу закладывать очереди, чтобы потом не переписывать архитектуру с нуля?

Как понимаю что Вы описали в статье что то вроде каркаса для старта. Отдельный плюс за то, что без рефералок.) Сугубо из теоретического интереса интереса вопрос сходу: когда этот фреймворк начнет разрастаться, на что его лучше сразу пересаживать с Excel? Хватит ли обычного SQLite для хранения истории сделок и стаканов на первое время, или под постоянные REST-запросы сразу надо поднимать что-то вроде Redis?

Вы правы про дофамин от написания руками - 100%. Когда ИИ делает вообще всю работу, программирование превращается в унылый конвейер (наверное как банальная офисная рутина) по схеме " скопировал - вставил - отправил". Исчезает сам кайф от того, что ты сидел, думал и сам решил задачу. Наверное поэтому приходится заводить пет-проекты чисто ради того, чтобы написать код руками и вернуть чувство, когда всё заработало именно благодаря собственным мозгам, а не удачному промпту

Хороший детальный разбор) Фишка с трюком с N-gram таблицей и выгрузкой в обычную RAM = физику не обманешь, однако инженерия красивая). По опыту сборки агентских цепочек на проде, у этих свежих китайских моделей (особенно на базе Qwen) столкнулся с двумя болями: дико болтающие, так и у них ощутимо плывет качество русского языка (если сравнивать к примеру с тем же Клодом), а также ломают регулярки при парсинге ответов. А вместо короткого JSON-вердикта или тега начинает выдавать простынь рассуждений = трата времени на жесткие системные промпты и валидаторы, чтобы система банально не порола хрень.

Вопрос хочу задать: пробовали гонять Flash-Next в агентских сценариях с вызовом Tools? Как она держит структуру ответа на длинном контексте, не начинает сыпать галлюнами в параметрах функций?

Так это да - внутренний софт для своей компании = самый благодарный кейс. По крайней мере, точно знаешь все узкие места своих процессов и не нужно тратить время на бесконечные согласования ТЗ, как с внешними заказчиками.

Хаа..) это в футураме Антология интересов вроде как?) лучше 2 часть - где бендер человеком был, нежели Антология интересов 1 )))

Понимаю Вас... Но всё таки когда вся эта связка начинает работать без сбоев на реальном трафике - дофамина прилетает не меньше, чем от запуска MVP за вечер. В общем еще раз спасибо за пост, хорошие мысли)

Довольно интересное заключение) момент про " удешевление любопытства" написано прямо в точку) Хотя дофаминовый туман быстро пропадает, когда пытаешься выкатить ИИ на реальных клиентов.

Из чистого любопытства: у Вас эти проекты так и остаются крутыми игрушками для души, или что-то из автоматизаций все-таки удалось дотащить до реальной работы, где они приносят пользу?

Information

Rating
554-th
Location
Минск, Минская обл., Беларусь
Registered
Activity

Specialization

Фулстек разработчик, Промпт-инженер
Ведущий
n8n
Node.js
JavaScript
API Интерфейсы
Redis
Docker
Системная интеграция
Организация работы с CRM
Управление проектами