July 30, 2025

Полное руководство: Создание ИИ-рекрутера в Telegram с нуля, даже если вы не программист

Привет! Это вторая часть нашего гайда по созданию ИИ-ассистента для найма. В первой части мы разобрали концепцию. Здесь мы займемся сборкой.

Этот гайд написан для тех, кто никогда не работал с n8n, API и не писал код. Мы будем использовать Google Gemini не только как «мозг» нашего бота, но и как помощника-программиста, который напишет нам код.

Важное замечание: Мы создаем бота для Telegram. Это универсальное и мощное решение. Если вам нужна более глубокая и сложная интеграция (например, бот, который сам забирает отклики с HeadHunter, анализирует резюме из PDF и работает с корпоративной почтой), это требует кастомной разработки. За такими решениями — обращайтесь ко мне в Telegram: @chiefgentleman.

А теперь, поехали.


Часть 0: Подготовительный этап для новичков (Что мы вообще используем?)

Если вы уже знакомы с API и n8n, можете пропустить эту часть.

  • Что такое n8n? Представьте себе конструктор LEGO для приложений. n8n — это платформа, где вы можете соединять разные сервисы (Telegram, Google, Gemini) в одну цепочку действий (workflow), не написав почти ни строчки кода. Мы будем использовать облачную версию n8n — она проще всего для старта.
  • Что такое API? Это как официант в ресторане. Вы (ваше приложение) говорите официанту (API), что хотите заказать на кухне (в другом сервисе, например, у Gemini). Официант передает заказ, а потом приносит вам готовое блюдо. API-ключ (API key) — это ваш "секретный пароль", который доказывает сервису, что это именно вы.
  • Что такое JSON? Это универсальный язык для передачи данных. Представьте, что вы даете официанту записку со структурированным списком: Имя: "Иван", Заказ: "Стейк", Прожарка: "Medium". Вот это и есть JSON. Он понятен и человеку, и машине.
  • Почему Google Gemini? Это наша "кухня". Мы отдаем Gemini "сырые" данные (диалог с кандидатом), а он возвращает нам "готовое блюдо" (структурированный JSON с анализом).

Часть 1: Фундамент. Получаем все доступы

1. Создаем Telegram-бота и получаем токен

  1. Откройте Telegram и найдите официального бота @BotFather.
  2. Напишите ему команду /newbot.
  3. Он попросит придумать имя для бота (например, Мой HR Ассистент).
  4. Затем попросит придумать юзернейм — он должен быть уникальным и заканчиваться на bot (например, MySuperHRBot или test_recruiter_123_bot).
  5. В ответ BotFather пришлет вам сообщение с API-токеном. Он выглядит как длинная строка из цифр и букв. Скопируйте и сохраните его в надежном месте. Это ваш ключ к боту.

2. Получаем API-ключ для Google Gemini

  1. Перейдите в Google AI Studio.
  2. Войдите, используя ваш Google-аккаунт.
  3. Нажмите на кнопку «Create API key in new project».
  4. Появится окно с вашим API-ключом. Скопируйте и сохраните его. Это ваш доступ к нейросети.

3. Создаем Google Таблицу для нашей CRM

  1. Перейдите на sheets.google.com и создайте новую таблицу.
  2. Назовите ее, например, «Отклики кандидатов».
  3. В первой строке создайте заголовки столбцов. Важно, чтобы они были названы точно так, как здесь (на английском), это упростит нам жизнь позже:
    Timestamp, Telegram_ID, Name, Experience, Salary_Expectation, Skills, Decision, Summary

4. Регистрируемся в n8n и настраиваем доступы (Credentials)

  1. Перейдите на сайт n8n.io и выберите облачную версию (Cloud). Зарегистрируйтесь.
  2. После регистрации вы попадете в ваш личный кабинет. Слева в меню найдите вкладку Credentials.
  3. Нажмите Add credential. Нам нужно добавить три доступа:
    • Для Telegram: В поиске введите Telegram. Выберите Telegram Bot API. В поле Access Token вставьте API-токен вашего бота, который вы получили от BotFather. Сохраните.
    • Для Gemini: В поиске введите Google Gemini. В поле API Key вставьте ключ, который вы получили в Google AI Studio. Сохраните.
    • Для Google Sheets: В поиске введите Google Sheets. Нажмите "Sign in with Google" и разрешите n8n доступ к вашему Google-аккаунту (тому же, где вы создали таблицу). Сохраните.

Фундамент готов. Теперь самое интересное — сборка.

Часть 2: Пошаговая сборка Workflow в n8n

Откройте n8n и создайте новый пустой Workflow (Add workflow).

Шаг 1: Триггер — точка входа

  • Узел: Telegram Trigger (нажмите на + и найдите его в поиске).
  • Зачем он нужен: Этот узел "слушает" вашего бота и запускает всю цепочку, когда кто-то ему пишет.
  • Настройки:
    1. В поле Credential for Telegram API выберите тот доступ, что вы создали.
    2. В поле Updates поставьте галочку на message.
    3. Остальное оставьте по умолчанию.

Шаг 2: Интервью с кандидатом (последовательность узлов)

Мы будем задавать вопросы и сохранять ответы. Это похоже на диалог.

2.1 Приветствие и первый вопрос

  • Узел: Telegram (это другой узел, не Trigger!)
  • Зачем он нужен: Для отправки сообщений от имени бота.
  • Настройки:
    • Credential for Telegram API: Выберите ваш доступ.
    • Chat ID: {{ $json.message.chat.id }}. Это выражение означает "взять ID чата из данных, которые пришли в триггер". Просто скопируйте и вставьте.
    • Text:Generated codeЗдравствуйте! Вы откликаетесь на вакансию [Название вакансии]. Чтобы мы могли быстрее обработать вашу заявку, ответьте, пожалуйста, на несколько вопросов. Как вас зовут и какая у вас фамилия?content_copydownloadUse code with caution.

2.2 Сохранение имени

  • Узел: Set
  • Зачем он нужен: Для временного хранения данных внутри workflow.
  • Настройки:
    • Keep Only Set: Включите (поставьте true). Это очистит workflow от лишних данных.
    • Нажмите Add Value.
    • Name: candidateName
    • Value: {{ $json.message.text }} (берем текст последнего сообщения кандидата).

2.3 Второй вопрос (опыт)

  • Узел: Telegram
  • Настройки:
    • Chat ID: {{ $trigger.message.chat.id }}
    • Text: Отлично, {{ $('Set').item.json.candidateName }}! Кратко опишите ваш релевантный опыт работы. (Например: 3 года в B2B продажах, работал с amoCRM, выполнял план на 110%).

2.4 Сохранение опыта

  • Узел: Set
  • Настройки:
    • Keep Only Set: Выключите (false). Нам нужно добавить данные, а не перезаписать имя.
    • Нажмите Add Value.
    • Name: candidateExperience
    • Value: {{ $json.message.text }}

2.5 Третий вопрос (ЗП)

  • Узел: Telegram
  • Настройки:
    • Chat ID: {{ $trigger.message.chat.id }}
    • Text: Понятно. Укажите ваши зарплатные ожидания (например, "100 000 руб. на руки").

2.6 Сохранение ЗП

  • Узел: Set
  • Настройки:
    • Keep Only Set: false
    • Add Value > Name: candidateSalary > Value: {{ $json.message.text }}

2.7 Финальное сообщение

  • Узел: Telegram
  • Настройки:
    • Chat ID: {{ $trigger.message.chat.id }}
    • Text: Спасибо! Ваши данные приняты в обработку. Мы скоро вернемся с ответом.

Шаг 3: Анализ данных с помощью Gemini

Сейчас у нас есть разрозненные ответы. Соберем их вместе и отправим на анализ.

3.1 Подготовка текста для ИИ

  • Узел: Set
  • Зачем он нужен: Чтобы собрать все ответы в один удобный текст.
  • Настройки:
    • Keep Only Set: false
    • Add Value > Name: fullInterviewText
    • Переключите поле Value в режим Expression и вставьте:Generated code`Кандидат: ${{$('Set').item.json.candidateName}}\nОпыт: ${{$('Set1').item.json.candidateExperience}}\nЗарплата: ${{$('Set2').item.json.candidateSalary}}`content_copydownloadUse code with caution.(Внимание: названия узлов Set, Set1, Set2 могут отличаться. Кликните на поле и перетащите нужные переменные из левой панели).

3.2 Отправка в Gemini (самый важный узел)

  • Узел: Google Gemini
  • Настройки:
    • Credential for Google Gemini: Выберите ваш доступ.
    • Operation: Chat
    • Model: gemini-pro
    • В разделе Chat Messages нажмите Add Chat Message Item.
    • Role: User.
    • В поле Message переключитесь в режим Expression и вставьте этот промпт, заменив текст в [] на свой:

Generated js

// --- НАЧАЛО ПРОМПТА ---

`Твоя роль — HR-аналитик мирового класса. Ты анализируешь краткое интервью с кандидатом на вакансию "[Название вашей вакансии, например, Менеджер по продажам]".

Твоя задача — проанализировать текст и вернуть ТОЛЬКО JSON-объект без каких-либо вводных слов, комментариев или markdown-обертки ```json. Только чистый JSON.

Ключевые требования к кандидату: [Опишите ваши идеальные критерии, например: опыт в B2B продажах от 2 лет, знание amoCRM, готовность к холодным звонкам, успешные кейсы].
Зарплатная вилка: [Укажите вашу вилку, например, 80000 - 120000 руб. на руки].

Вот текст интервью:
---
${{ $('Set3').item.json.fullInterviewText }}
---

Проанализируй текст и сформируй JSON со следующей структурой:
{
  "name": "Имя и Фамилия кандидата",
  "experience": "Краткое и четкое описание опыта, извлеченное из ответа",
  "salary_expectation": "Зарплатные ожидания кандидата (только число, если возможно, иначе текст)",
  "skills": "Массив строк с ключевыми навыками, которые ты нашел в тексте",
  "decision": "строка 'подходит' или 'не подходит'",
  "summary": "Краткое резюме на 2-3 предложения на русском языке, объясняющее, почему принято такое решение (decision), основываясь на сравнении его ответов с ключевыми требованиями."
}

Правила для поля "decision":
- Если опыт и навыки кандидата соответствуют ключевым требованиям, А зарплатные ожидания находятся в пределах или ниже вилки, ставь 'подходит'.
- Во всех остальных случаях ставь 'не подходит'.
- Будь строгим, но справедливым. Нам нужны только лучшие.`

// --- КОНЕЦ ПРОМПТА ---

Шаг 4: Обработка ответа от Gemini и запись в таблицу

Что у нас есть на данный момент: На предыдущем шаге мы отправили в Google Gemini сырой текст диалога и попросили его вернуть JSON. Теперь у нас на выходе из узла Google Gemini есть текстовая строка, которая выглядит как JSON.

В чем проблема? Для n8n это просто набор символов, а не структурированные данные. Наша задача — объяснить машине: "Эй, этот текст — не просто текст, это структурированный объект с полями name, decision, summary и т.д. Пожалуйста, разбери его на части, чтобы я мог использовать каждую отдельно". Этот процесс называется парсинг.

Этот шаг мы разделим на две части:

  1. 4.1. Магия парсинга: Превращаем текст в настоящие данные с помощью узла Code.
  2. 4.2. Финальный пункт: Записываем эти данные в нужные ячейки Google Таблицы.

4.1. Магия парсинга: Узел Code

Раньше этот узел назывался Function. Это ваш личный мини-программист внутри n8n, который может выполнять небольшие кусочки кода на JavaScript. Не пугайтесь, мы заставим Gemini написать код за нас.

1. Добавьте узел Code

  • Нажмите на + после узла Google Gemini и найдите в поиске Code. Добавьте его.

2. Заставляем Gemini написать код

  • Откройте новую вкладку браузера и перейдите в Google Gemini (или любой другой чат с ИИ).
  • Скопируйте и вставьте туда следующий промпт. Он идеально сформулирован, чтобы получить то, что нам нужно.
Промпт для Gemini:Напиши, пожалуйста, код для узла Code в n8n на языке JavaScript.Задача кода:Взять данные из предыдущего узла. В n8n они доступны через переменную $json.response. Эти данные — это строка, которая должна быть в формате JSON.Иногда эта строка может приходить с лишними символами, например, с оберткой json в начале и в конце. Код должен надежно очищать строку от этих символов.После очистки, код должен преобразовать (распарсить) эту строку в настоящий JSON-объект.Результат нужно вернуть в формате, который понятен для следующих узлов n8n, а именно: return [{ json: parsedData }].Важно: добавь блок try...catch для обработки ошибок. Если по какой-то причине строка не является валидным JSON и ее не удается распарсить, код не должен ломать весь workflow, а должен вернуть объект с информацией об ошибке.

3. Получаем и вставляем код

  • Gemini сгенерирует код. Он должен выглядеть практически идентично этому:

Generated javascript

// Этот код берет текстовый ответ от Gemini и превращает его в структурированные данные.

try {
  // 1. Получаем текстовую строку из предыдущего узла.
  const geminiResponse = $json.response;

  // 2. Очищаем строку от возможных markdown-оберток и лишних пробелов.
  const cleanJsonString = geminiResponse.replace(/```json/g, '').replace(/```/g, '').trim();

  // 3. Пытаемся преобразовать (распарсить) чистую строку в JSON-объект.
  const parsedData = JSON.parse(cleanJsonString);

  // 4. Возвращаем результат в формате, понятном для n8n.
  return [{ json: parsedData }];

} catch (error) {
  // 5. Если на любом из этапов произошла ошибка (например, Gemini вернул не JSON)
  // мы не ломаем весь процесс, а возвращаем объект с информацией об ошибке для отладки.
  console.error("Ошибка парсинга JSON:", error);
  const originalResponse = $json.response || "Ответ от Gemini отсутствует";
  return [{ 
    json: { 
      error: "Не удалось обработать ответ от Gemini. Проверьте вывод узла Gemini.", 
      originalResponse: originalResponse 
    } 
  }];
}

content_copy

download

Use code with caution.

JavaScript

  • Скопируйте этот код и вставьте его в поле JavaScript Code в вашем узле Code в n8n.

Что мы только что сделали? Мы создали надежный преобразователь. Теперь, что бы ни вернул Gemini (чистый JSON или JSON с мусором), этот узел попытается извлечь из него полезные данные. Если не получится, он не сломает всю автоматизацию, а просто сообщит об ошибке.


4.2. Финальный пункт: Запись в Google Sheets

Теперь у нас есть узел Code, который на выходе отдает красивые, структурированные данные. Осталось только положить их на нужные "полочки" в нашей Google Таблице.

1. Добавьте узел Google Sheets

  • Нажмите + после узла Code и найдите Google Sheets.

2. Настройте узел

  • Credential for Google Sheets: Выберите доступ, который вы настраивали в самом начале.
  • Operation: Выберите Append (это означает "добавить строку в конец таблицы").
  • Spreadsheet ID: Начните вводить название вашей таблицы («Отклики кандидатов»). n8n найдет ее в вашем Google Диске. Выберите ее.
  • Sheet Name: Выберите нужный лист, скорее всего, он называется Лист1 или Sheet1.
  • Columns > Mode: Выберите Map Each Column Below to a Field. Это позволит нам вручную указать, какие данные в какой столбец класть.

3. Сопоставление данных (самый важный этап здесь)

  • Теперь n8n покажет вам список столбцов из вашей таблицы. Наша задача — для каждого столбца указать, откуда брать данные.
  • Нажимайте на значок с перекрестием (Add Expression) и выбирайте переменные из левой панели (Current Node > Input Data > JSON).

Вот как должно получиться:

  • Timestamp: {{ $now }}
    • (Это специальная переменная n8n, которая всегда содержит текущую дату и время).
  • Telegram_ID: {{ $trigger.message.chat.id }}
    • (Мы берем ID пользователя из самого первого, триггерного узла, чтобы всегда знать, кто это был).
  • Name: {{ $json.name }}
    • (Берем поле name из данных, которые нам вернул узел Code).
  • Experience: {{ $json.experience }}
    • (Аналогично берем поле experience).
  • Salary_Expectation: {{ $json.salary_expectation }}
  • Skills: {{ $json.skills }}
    • (n8n достаточно умен, чтобы превратить массив навыков в строку текста).
  • Decision: {{ $json.decision }}
  • Summary: {{ $json.summary }}

Визуально это будет выглядеть так:

Готово! Теперь после каждого диалога с кандидатом вся проанализированная и структурированная информация будет автоматически, как по волшебству, появляться в новой строке вашей Google Таблицы. Вы можете открыть ее и увидеть, как она заполняется в реальном времени.

Вы только что завершили самый сложный технический этап. Следующий шаг — вишенка на торте: настройка уведомлений для себя.

Конечно. Завершаем наш гайд, делая финальные шаги максимально понятными.


Шаг 5: Вишенка на торте — Умные уведомления

Сейчас наш бот молча заносит данные в таблицу. Это хорошо, но неудобно — вам придется постоянно проверять таблицу вручную. Давайте научим его сообщать нам о результатах.

Для этого нам понадобится "развилка на дороге" — узел, который будет направлять процесс по разным путям в зависимости от того, подошел кандидат или нет.

5.1. Создаем развилку: Узел IF

  • Нажмите на + после узла Google Sheets и найдите в поиске узел IF.
  • Зачем он нужен: Он проверяет одно условие (например, "равно ли поле decision слову подходит?") и, в зависимости от ответа "да" или "нет", активирует разные ветки.
  • Настройки узла IF:
    1. Нажмите Add Condition.
    2. Выберите тип String.
    3. Value 1: Нажмите на значок с перекрестием и найдите переменную, отвечающую за решение Gemini. Путь будет таким: Nodes → Code → Output Data → JSON → decision. Выражение будет выглядеть так: {{ $('Code').item.json.decision }}.
    4. Operation: Выберите Equal (Равно).
    5. Value 2: Напишите слово подходит (в нижнем регистре, точно так же, как вы указали в промпте для Gemini).

Теперь у вашего узла IF есть два выхода: верхний (true) и нижний (false). Ветка true сработает, если кандидат подходит. Ветка false — если не подходит.

5.2. Ветка TRUE: Уведомление для вас

Сюда мы подключим узел, который будет отправлять вам в Telegram срочное уведомление о классном кандидате.

  • Протяните связь от выхода true узла IF и создайте новый узел Telegram.
  • Настройки узла Telegram:
    • Credential for Telegram API: Выберите ваш доступ.
    • Chat ID: Это важно! Здесь нужно указать ваш личный ID в Telegram, а не ID кандидата.
      • Как узнать свой Chat ID? Найдите в Telegram бота @userinfobot, напишите ему /start, и он пришлет ваш уникальный ID. Это будет число (например, 123456789). Скопируйте его и вставьте сюда.

Заключение: Вы создали систему, а не просто бота

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

Теперь вы не ищете иголку в стоге сена, а выбираете лучшую из нескольких иголок, которые система сама нашла, очистила и принесла вам на блюдечке.

Но это только начало. Что можно сделать дальше?

Этот workflow — как мощный двигатель. Вы можете построить вокруг него настоящий гоночный болид, добавив новые функции:

  1. Интеграция с календарем: Добавить еще один шаг, который после решения подходит автоматически отправляет кандидату ссылку на ваш Calendly или Cal.com, чтобы он сам забронировал свободный слот для собеседования. Без единого письма.
  2. Автоматические тестовые задания: Усложнить узел IF, чтобы он проверял не только "подходит/не подходит", но и, например, ключевые навыки (skills). И в зависимости от навыков, отправлял кандидату разные ссылки на тестовые задания.
  3. Мультиканальность: Подключить этот же workflow к форме "Откликнуться на вакансию" на вашем сайте (Tilda, Webflow, WordPress) с помощью узла Webhook. Логика останется той же, но вы будете захватывать кандидатов из разных источников.

Эти идеи — реальные кейсы, которые уже работают в бизнесе и приносят результат. Если вы хотите построить такой "гоночный болид", интегрировать систему с HeadHunter, научить ее анализировать PDF-резюме или решить любую другую сложную задачу по автоматизации — вы знаете, куда писать.

За такими кастомными и мощными решениями обращайтесь ко мне в Telegram: @chiefgentleman

Помните: автоматизация — это не про замену людей. Это про усиление лучших из них. И про то, чтобы дать вам возможность заниматься тем, что действительно важно для роста вашего бизнеса.