Сегодня многие разработчики различного уровня знают n8n как гибкий инструмент для автоматизации. В нем можно собрать почти любой сценарий - от простейшего Telegram-бота до сложных бизнес-процессов, используя множество готовых нод (узлов) для работы с популярными сервисами.
Но что делать, если в это множество не входит один из используемых вами сервисов, а через ноду HTTP Requests работать крайне сложно и неудобно? Или, может, хочется подключить собственный API и работать с ним по собственной логике?
Здесь напрашивается довольно простой ответ: написать свою ноду на n8n. Изначально это кажется сложным, однако, прочитав эту статью, вы сможете буквально за 1 вечер собрать минимально-рабочую ноду под ваши "хотелки".
Community nodes - что это?
Что очевидно из названия, это нода, написанная каким-то разработчиком из комьюнити (сообщества) n8n.
Комьюнити-ноды недоступны в списке нод в воркфлоу без предварительной их установки. Все ноды, которые доступны без дополнительных манипуляций, проверены и добавлены именно разработчиками n8n.
Такие ноды публикуются разработчиками как пакет в npm Registry, название которого обязательно начинается с n8n-nodes для того, чтобы n8n смог увидеть его.
Например:
n8n-nodes-amvera-inferenceилиn8n-nodes-my-first-node
Где можно развернуть n8n
Перед тем как писать свою ноду, нужно подготовить среду. n8n можно установить локально, в Docker, развернуть в облаке или на VDS/VPS.
В моём случае всё происходило в Amvera Cloud - сервисе для простого и быстрого развертывания IT-приложений, в котором n8n уже есть как настроенный сервис с бесплатным доменом, запуском "одной кнопкой" и собственной нодой доступ�� к LLM c оплатой в рублях.
Установка комьюнити-ноды
Первым делом необходимо убедиться, что ваша версия n8n и окружение поддерживает установку комьюнити-нод.
Если вы используете преднастроенный сервис в Amvera, дополнительно ничего настраивать не нужно и установка community nodes должна быть доступна в настройках n8n.


Если же таких нет - попробуйте обновить n8n или создать/изменить переменную окружения N8N_COMMUNITY_NODES_ENABLED в значении true.
Здесь можно установить любую комьюнити-ноду из списка.
Если при установке комьюнити-ноды n8n возвращает ошибку:
Error installing new package: Request failed with status 504,
Попробуйте установить ноду еще раз через несколько минут, это нормально.
Создаем свою ноду шаг за шагом
Итак, когда у нас готово все окружение, мы можем приступать к практической части.
Мы разберем нашу ноду n8n-nodes-amvera-inference, которая упрощает работу с Amvera LLM Inference API, отправляя запросы к API с определенным токеном и возвращая ответ в двух видах: RAW JSON и Ответ модели (только сам ответ).
Подготовка проекта
Важно понимать, что нода - обычный npm-пакет, но с особой структурой.
Официальный репозиторий для быстрого старта доступен на GitHub: https://github.com/n8n-io/n8n-nodes-starter
Структура проекта
Структура нашей ноды выглядит следующим образом:
n8n-nodes-amvera-inference ├── credentials │ └── AmveraLlmApi.credentials.ts ├── index.ts ├── nodes │ └── AmveraLlm.node.ts ├── package.json └── tsconfig.json
package.json- можно полностью скопировать с официального репозитория n8n-nodes-starter. Важно изменить название пакета.tsconfig.json- для предложенной структуры выше будет выглядеть так:
{ "compilerOptions": { "target": "ES2019", "module": "commonjs", "declaration": true, "outDir": "dist", "rootDir": ".", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "moduleResolution": "node", "resolveJsonModule": true }, "include": ["nodes/**/*.ts", "credentials/**/*.ts"], "exclude": ["node_modules", "dist"] }
AmveraLlmApi.credentials.ts- содержит в себе описание Credentials, используемых для ноды, если она требует авторизацию на TypeScript.AmveraLlm.node.ts- основной код (логика) работы ноды. Чуть ниже будет его разбор на рабочем примере.index.ts- необязательный файл, содержащий в себе export всех модулей.
AmveraLlmApi.credentials.ts
import { ICredentialType, INodeProperties } from 'n8n-workflow'; export class AmveraLlmApi implements ICredentialType { name = 'amveraLlmApi'; displayName = 'Amvera LLM API'; properties: INodeProperties[] = [ { displayName: 'API Token', // имя, которое будет отображаться в n8n name: 'apiToken', // имя, по которому мы будем общаться дальше в коде type: 'string', // тип кредов typeOptions: { password: true }, // доп. настройки default: '', // значение по дефолту - пустое required: true, // обязательно ли наличие кредов description: 'Токен от модели LLM', // описание в UI n8n }, ]; }
Как и говорилось ранее - этот файл содержит в себе описание вида Credentials для того, чтобы n8n понимал, как формировать окно создания кредов.
AmveraLlm.node.ts
import { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription, } from 'n8n-workflow'; export class AmveraLlm implements INodeType { description: INodeTypeDescription = { displayName: 'Amvera LLM', // отображаемое имя name: 'amveraLlm', // имя для обращений в коде group: ['transform'], // группа (тип) ноды version: 1, // версия description: 'Работа с Amvera LLM API', // описание defaults: { name: 'Amvera LLM' }, // дефолтные значения inputs: ['main'], // входные данные (из предыдущей ноды) outputs: ['main'], // выходные данные (в следующую ноду) credentials: [{ name: 'amveraLlmApi', required: true }], // какие креды используются. Здесь мы как раз пишем имя из созданного ранее файла. properties: [ // Описание полей внутри ноды. У нас это: выбор модели, создание сообщений для LLM, выбор режима вывода { displayName: 'Model', // отображаемое имя настройки ноды name: 'model', // внутреннее имя настройки ноды type: 'options', // тип (options - выпадающий список) options: [ // что можно выбрать {name, value} { name: 'llama8b', value: 'llama8b' }, { name: 'llama70b', value: 'llama70b' }, { name: 'gpt-4.1', value: 'gpt-4.1' }, { name: 'gpt-5', value: 'gpt-5' }, ], default: 'llama8b', // значение по умолчанию }, { displayName: 'Messages', name: 'messages', type: 'fixedCollection', // typeOptions: { multipleValues: true }, default: {}, options: [ { name: 'message', displayName: 'Message', values: [ { displayName: 'Role', name: 'role', type: 'options', options: [ { name: 'system', value: 'system' }, { name: 'user', value: 'user' }, { name: 'assistant', value: 'assistant' }, ], default: 'user', }, { displayName: 'Text', name: 'text', type: 'string', default: '', }, ], }, ], }, { displayName: 'Режим вывода', name: 'returnMode', type: 'options', options: [ { name: 'Ответ модели', value: 'first' }, { name: 'JSON', value: 'raw' }, ], default: 'first', }, ], }; async execute(this: IExecuteFunctions): Promise { const items = this.getInputData(); const output: INodeExecutionData[] = []; const creds = await this.getCredentials('amveraLlmApi'); const token = creds.apiToken as string; for (let i = 0; i < items.length; i++) { const model = this.getNodeParameter('model', i) as string; const messages = this.getNodeParameter('messages.message', i, []) as Array<{ role: string; text: string }>; const mode = this.getNodeParameter('returnMode', i) as string; const endpoint = model.startsWith('llama') ? 'llama' : 'gpt'; const body = { model, messages }; const res = await this.helpers.httpRequest({ method: 'POST', url: `https://kong-proxy.yc.amvera.ru/api/v1/models/${endpoint}`, headers: { 'X-Auth-Token': `Bearer ${token}`, 'Content-Type': 'application/json', }, body, json: true, }); let answer = ''; if (model.startsWith('llama')) { const result = res?.result; if (result?.alternatives?.length) { answer = result.alternatives[0]?.message?.text ?? ''; } } else { if (res?.choices?.length) { answer = res.choices[0]?.message?.content ?? ''; } } if (mode === 'first') { output.push({ json: { text: answer } }); } else { output.push({ json: res }); } } return [output]; } }
Здесь чуть сложнее, но все также шаблонно.
Первая часть кода
Содержит описание самой ноды для формирования в n8n. Значения большинства параметров описаны в комментариях в коде. Используя шаблон выше вы можете формировать подобные ноды.
Вторая часть кода - execute()
Всё, что происходит внутри метода execute(), - это реальная логика работы ноды.
n8n вызывает этот метод каждый раз, когда workflow доходит до твоей ноды.
В этот момент нода:
получает входные данные;
читает настройки из интерфейса;
делает запрос к API (или любое другое действие), описанное вами в коде;
формирует выходной JSON и передает его дальше.
Разберем метод подробнее.
1. Получаем входные данные
const items = this.getInputData(); const output: INodeExecutionData[] = [];
getInputData()возвращает массив объектов (JSON) от предыдущей ноды;output- пустой массив, куда мы будем складывать результаты.
n8n умеет работать с массивами данных - если предыдущая нода передала, например, 10 строк, execute() выполнится 10 раз в цикле.
2. Получаем креды и параметры
const creds = await this.getCredentials('amveraLlmApi'); const token = creds.apiToken as string;
getCredentials('amveraLlmApi')- достает токен, который пользователь ввел в Credentials ноды.
Дальше - параметры, которые пользователь задаёт в интерфейсе ноды:
const model = this.getNodeParameter('model', i) as string; const messages = this.getNodeParameter('messages.message', i, []) as Array<{ role: string; text: string }>; const mode = this.getNodeParameter('returnMode', i) as string;
Каждый вызов getNodeParameter() получает значение поля из properties (той самой секции в описании ноды).
i - индекс текущего элемента из входных данных (если их несколько).
3. Формируем запрос к API
const endpoint = model.startsWith('llama') ? 'llama' : 'gpt'; const body = { model, messages };
Здесь мы определяем, какой эндпоинт использовать - llama или gpt и формируем body запроса.
4. Отправляем HTTP-запрос
const res = await this.helpers.httpRequest({ method: 'POST', url: `https://kong-proxy.yc.amvera.ru/api/v1/models/${endpoint}`, headers: { 'X-Auth-Token': `Bearer ${token}`, 'Content-Type': 'application/json', }, body, json: true, });
this.helpers.httpRequest- встроенный метод n8n для HTTP-запросов (автоматически обрабатывает JSON, ошибки, HTTPS). Короче говоря: удобно.В заголовок добавляется токен авторизации (
Bearer ${token}), который мы получили из кредов.json: trueговорит n8n автоматически парсить ответ как JSON.
5. Обрабатываем ответ
Amvera LLM API может вернуть результат в разных форматах - у LLaMA и GPT структура ответа отличается.
let answer = ''; if (model.startsWith('llama')) { const result = res?.result; if (result?.alternatives?.length) { answer = result.alternatives[0]?.message?.text ?? ''; } } else { if (res?.choices?.length) { answer = res.choices[0]?.message?.content ?? ''; } }
Для моделей LLaMA ответ находится в
res.result.alternatives[0].message.text.Для GPT-моделей - в
res.choices[0].message.content.?? ''- оператор, который возвращает строку, если undefined.
6. Формируем выходной результат
if (mode === 'first') { output.push({ json: { text: answer } }); } else { output.push({ json: res }); }
Если выбран режим "Ответ модели", нода вернет только текст (удобно для чат-ботов).
Если выбран режим "JSON", в вывод попадёт весь ответ API
7. Возвращаем результат n8n
return [output];
С такими настройками выглядит следующим образом

Весь код ноды доступен на нашем Github
Публикация пакета
Если у вас уже готов код (т.е. вы настроили вид ноды и ее логику в execute()), пакет нужно опубликовать в npm.
Для этого нужно иметь аккаунт в npm и залогиниться через команду npm login, которая перенаправить вас в браузер для авторизации.
Еще раз убедитесь, что в package.json название пакета начинается с n8n-nodes.
После этого, проект необходимо собрать. Для этого пишем:
npm i npm run build # если у вас есть скрипт build в package.json для компиляции TS
Если у вас появились папки node_modules и dist с скомпилированными js файлами, ваш пакет готов к публикации. Пишем:
npm publish --access public
Если все получилось правильно, пакет должен появиться и быть доступен в npm Registry.
Итог
Теперь вы можете подключить опубликованный пакет в n8n и пользоваться нодой в свое удовольствие.
На самом деле, написание нод для n8n, не такая уж сложная задача, как может казаться на первый взгляд. Достаточно лишь по шаблону заполнить описание ноды и описать логику в методе execute().
Таким образом вы можете подключить любой API буквально за вечер, что дает полную свободу.
