delai-lead-qualification
n8n-сценарий ИИ-квалификации лидов в amoCRM. 20 нод, линейный пайплайн, без агентских циклов и векторных баз. Промпты убраны под NDA — каркас открыт.
📖 Полный разбор со скриншотами и живым демо: delai.agency/avtomatizacii/kvalifikaciya-lidov-amocrm
Что сломалось в первой версии, почему смена модели не помогла, как починили одной валидаторной нодой.
Зачем
Заказчик — B2B-сегмент с премиум-клиентами. Менеджер квалифицировал входящие лиды руками: открывал источники, проверял по чек-листу, относил к одному из 4 тиров. На лид уходило 15–30 минут. Это рутина, на которой выгорает даже опытный менеджер.
Сценарий делает то же за ~3 минуты. Не заменяет менеджера в спорных случаях — но снимает с него поток типовых лидов, по которым он и так принимал бы одно и то же решение.
Архитектура
Триггер — вебхук amoCRM на смену этапа. Дальше:
-
Извлечение и сбор контекста. Set-нода вытаскивает leadId из payload вебхука; два HTTP-узла идут в amoCRM REST API за карточкой сделки (
/api/v4/leads/{id}?with=contacts) и связанным контактом (/api/v4/contacts/{id}). Set-нодаBuild Lead Contextсобирает плоский объект: имя, телефон, e-mail, contactId, leadId. -
Защитные If-ноды.
Is New Lead Stageсравнивает текущий и предыдущий статус из payload — если этап не поменялся, поток уходит в Skip. Дальше — отдельная нода-валидация JSON от ИИ. -
ИИ #1 — исследование. Используется модель
o4-mini-deep-research-2025-06-26с инструментомweb_search. Запрос делается напрямую через HTTP-ноду (не через стандартный OpenAI-узел n8n), потому что async-режим: запрос на/v1/responsesстартует исследование в background, возвращает respId. Дальше Code-нодаPoll Until Doneпингует/v1/responses/{id}каждые 15 секунд до 80 раз (20 минут таймаут). Это позволяет не держать соединение и не падать по таймауту n8n. -
Парсер и валидатор.
Parse OpenAI #1(Set) достаёт text из ответа Responses API (с тремя fallback-вариантами на разные форматы output).Is OpenAI #1 Validпроверяет что report длиннее 100 символов — иначе уходим в Stop. -
ИИ #2 — нормализация. Узел
OpenAI #2 Normalize— нативный n8n OpenAI-узел. Получает summary от #1 и возвращает строго одно из 4 значений тира. Отдельная нода, отдельный промпт — это сделано чтобы исследование (свободная форма) и финальное решение (жёсткий enum) жили раздельно. -
Запись в amoCRM. Два HTTP-узла:
Save Summary As Note(POST/api/v4/leads/{id}/notesс текстом summary и тиром в content) иUpdate Client Type On Contact(PATCH/api/v4/contacts/{id}с custom_fields_values на ID поля Client Type).
Что заменить перед запуском
Workflow.json содержит плейсхолдеры — без подмены не заработает:
| Где | Что | Чем заменить |
|---|---|---|
| 4 HTTP-узла к amoCRM | your-amocrm-subdomain.amocrm.ru |
Ваш поддомен |
| Все 4 узла amoCRM | credentials httpHeaderAuth “amoCRM API” |
Long-lived token в формате Bearer <token> |
OpenAI #1 Start headers |
Bearer sk-REPLACE_WITH_YOUR_OPENAI_KEY |
Ваш OpenAI API key |
Poll Until Done jsCode |
const KEY = "REPLACE_WITH_YOUR_OPENAI_KEY" |
Тот же ключ OpenAI |
OpenAI #2 Normalize |
credentials openAiApi |
OpenAI credential в n8n |
Update Client Type On Contact |
field_id: 697355 |
ID кастомного поля Client Type у Контакта |
Build Prompt #1 (Set) |
[промпт по NDA] |
Ваш research-промпт |
OpenAI #2 Normalize messages |
[промпт по NDA] |
Ваш классификатор-промпт |
Замечания по архитектуре
- Без RAG/векторок. Сознательно — для одного лида в среднем нужно сходить в 3–5 источников. Векторная база не даёт выигрыша, добавляет инфраструктуру.
- Без агентских циклов. Используем максимум один повторный проход исследовательской ноды через nodо-валидатор. Полноценный agentic loop тут излишен — задача не творческая.
- Async-режим Responses API. Deep-research модели могут думать минутами. Sync-вызов держал бы сокет, что неудобно для долгих прогонов. Async + polling — устойчиво.
- Два разных OpenAI-вызова в одном workflow. #1 через HTTP (нужен async + tools), #2 через нативный n8n узел (стандартный chat-completion с jsonSchema-выходом). Это логично разделено.
Безопасность
⚠️ В исходной боевой версии workflow ключ OpenAI был зашит plaintext в headers HTTP-ноды и в Code-ноде. При публикации шаблона эти места заменены на плейсхолдеры. Рекомендация — при настройке у себя положить ключ в credentials (HTTP Header Auth или переменные окружения), не плейнтекстом в нодах.
PR / fork приветствуются
Если у вас есть улучшения по архитектуре (например, поддержка Битрикс24 через адаптер, замена sync-полла на webhook от OpenAI, или метрики через Prometheus) — присылайте PR.
Лицензия
MIT — см. LICENSE.