Разобран баг тишины в ИИ-агенте на n8n
Автор разобрал случай, когда все ноды агента на n8n отработали успешно, но клиент не получил ответа. Материал полезен разработчикам, сталкивающимся с подобными сбоями.
В блоге на Хабре разобрали второй случай «тишины» в ИИ-агенте, работающем на self-hosted n8n. Агент принимает заявки в директ ателье украшений, ведёт диалог, собирает анкету и создаёт сделки в amoCRM. Несмотря на то что все ноды воркфлоу завершались успешно, клиенты не получали ответов. Автор отмечает, что проблема не в LLM, а в инфраструктуре вокруг неё: невидимые символы, некорректная проверка на пустоту и отключённый чекбокс сохранения успешных выполнений.
Первопричина обнаружилась в том, что в настройках n8n была отключена опция Save successful production executions. Это привело к тому, что логи успешных прогонов не сохранялись, и расследование осложнилось. После включения сохранения автор увидел, что воркфлоу доходит до конца, поля записываются в CRM, но клиенту ничего не отправляется. В OpenRouter карточка генерации показала 105 видимых токенов, которые оказались служебными тегами протокола, а не человеческим текстом.
Валидатор пустого ответа, добавленный ранее, не сработал, потому что проверял только факт отсутствия пустоты, а не наличие осмысленного текста. Нода Format Response for IG вырезала служебные теги, оставляя шлейф из пробелов и переводов строк. Этот шлейф воспринимался как непустая строка, и guard, проверяющий факт выполнения ноды, пропускал его. В результате Meta API получала символы и отвечала 200 OK, хотя клиент видел пустое сообщение.
Второй баг проявился как Bad request на финальном этапе сбора анкеты. Ошибка возникала при отправке длинного сообщения с переносами строк. Автор изучил документацию Meta и выяснил, что ограничение в 1000 символов относится к байтам, а не к символам. Кириллица в UTF-8 занимает 2 байта на букву, эмодзи — 3-4 байта. Таким образом, анкета из 570 символов русского текста занимает более 1000 байт, что приводило к ошибке 400.
Автор отмечает, что предыдущие рекомендации из комментариев — тестировать валидатор в составе системы и проверять инвариант «пустой content + потраченные токены + finish_reason: stop не равно успех» — не были реализованы. Новый баг прошёл сквозь оба пункта. Также остаётся открытым вопрос о ретрае после уже выполненных действий: если CRM уже записана, а клиенту сообщение не ушло, неясно, как обрабатывать такие ситуации.
В качестве фикса предлагается использовать компактное выражение на JavaScript, которое проверяет не только факт выполнения ноды, но и содержимое ответа. Также необходимо учитывать ограничения на размер сообщений в байтах, особенно при работе с кириллицей и эмодзи. Автор подчёркивает, что зелёные ноды могут скрывать ошибки, и призывает коллег уделять больше внимания end-to-end тестированию и мониторингу.
История показывает, что даже при успешных выполнениях всех компонентов итоговый результат может быть неверным. Важно не только логировать ошибки, но и сохранять успешные прогоны для анализа. В данном случае отключение сохранения успешных выполнений привело к слепому расследованию. Рекомендуется включать эту опцию в продакшене, несмотря на экономию дискового пространства.
Материал подготовлен ИИ-редакцией «Сигнала» как пересказ публикации первоисточника. Фактическую точность и подробности проверяйте по оригиналу.