Workflow, Node, Connection, Execution: четыре слова объясняют мир n8n

На холсте пять блоков и четыре линии. Экспортируем это в JSON — останутся только два ключа:nodes 和 connections. Записи выполнения хранятся в другом месте, выстроены одна за другой, каждая со своим номером.

Три места говорят об одном и том же, используя четыре слова: workflow, node, connection, execution. Разберёшься с этими четырьмя словами — дальше любой туториал по нодам будет даваться легче; не разберёшься — будешь бесконечно метаться между «я же нажал выполнить» и «почему оно не запустилось».

Не нужно уметь писать код. Достаточно, чтобы установленный n8n открывался и хотя бы раз запустил workflow (если не установлен, смотриэту статью, а если интерфейс ещё незнаком, сначала откройобзор интерфейса). У меня версия 2.43.7, у тебя минорная версия может отличаться — расположение кнопок может немного не совпадать.

Четыре слова, четыре вещи

Сначала приведём сравнительную таблицу, а в следующих разделах разберём её подробно.

词 Что это такое Где хранится Количественное соотношение
Workflow Набор узлов, соединённых вместе для выполнения одной задачи Таблица workflow в базе данных, один JSON 1 workflow содержит N узлов
Node Единица выполнения, выполняющая один шаг работы В JSON workflow nodes В массиве 1 узел принадлежит 1 рабочему процессу
Connection Подключить выход предыдущего узла ко входу следующего в одном и том же JSON connections внутри объекта 1 рабочий процесс имеет N линий
Execution Этот рабочий процесс был запущен один раз Таблица выполнений, независимая от рабочего процесса 1 рабочий процесс имеет N выполнений

Легче всего запутаться в последней строке. Рабочий процесс — это чертёж, выполнение — это стройка. Сколько бы раз ни менялся чертёж, ранее выполненная стройка за ним не изменится.

n8n 画布上的五个节点与四条连线,IF 节点右侧标着 true 和 false
Пять квадратов и четыре линии — это первые три из этих четырёх вещей. Две маленькие точки справа от блока условия, одна помечена true, другая false, — это два разных выхода

Workflow: один container, плюс два состояния

Официальное определение очень короткое: группа соединённых узлов, которые автоматически выполняют что-либо; когда срабатывает триггер, вы нажимаете вручную или другой процесс вызывает его, он начинает выполняться, узел за узлом, может ветвиться, объединяться, зацикливаться.

В определении не к чему придраться. Что действительно требует внимания — это состояние, появившееся после 2.x:Черновик и опубликованная версия — это две разные вещи。

Вы меняете что-то на холсте, n8n сохраняет сам, в течение от одной до пяти секунд записывает в базу, кнопки сохранения нет. Но это лишь сохранение в черновик. Чтобы изменения попали в продакшен, нужно нажать «Опубликовать» в правом верхнем углу и закрепить определённую версию в продакшене. После этого таймеры, Webhook и события приложений запускают именно закреплённую версию, а не ту, что сейчас у вас на экране.

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

只有手动触发器的工作流,发布按钮是灰的,提示没有需要发布的触发节点
Смотрите только в правый верхний угол. Кнопка серая, при наведении курсора причина прямо говорит: у этого workflow нет trigger-узла, требующего публикации. Ручной триггер не выходит в продакшен, поэтому публиковать нечего

Это заодно объясняет, почему у некоторых первый workflow никак не «активируется». Есть только ручной триггер, у него от природы нет продакшен-формы, кнопка публикации всегда серая. Нужно по расписанию — добавьте Schedule Trigger; нужно принимать внешние запросы — добавьте Webhook. С такими триггерами кнопка станет активной.

Из интерфейса это видно яснее: на моём экземпляре у нового workflow active 是 false,activeVersionId 是 null, только один versionId меняется с каждым изменением. Если не публиковали, продакшен-версии нет.

Node: имя — это первичный ключ

Узел — это единица выполнения. Одни отвечают за запуск (триггеры), другие получают данные, отправляют данные, вычисляют данные, третьи занимаются только управлением потоком, одна строка IF тоже может быть узлом.

В JSON узел — это всего семь вещей:

{
  "parameters": { "jsCode": "return [{ json: { amount: 620 } }];" },
  "id": "n2",
  "name": "造两条订单",
  "type": "n8n-nodes-base.code",
  "typeVersion": 2,
  "position": [-400, 0]
}
  • type: это тип узла.n8n-nodes-base.code это узел Code,-base. хвост после него — имя узла в нижнем регистре.
  • typeVersion:Версия определения узла. У разных версий одного и того же узла структура параметров меняется. В моём случае IF — это 2.2, Edit Fields — это 3.5, Code — это 2, Manual Trigger — это 1. Эти числа не вы вводите — они записываются при создании по определению на тот момент.
  • parameters: Всё, что вы заполняете в правой панели, находится здесь. При смене типа узла этот блок заменяется целиком.
  • position: Координаты на холсте, только для отображения, к порядку выполнения отношения не имеют.
  • id: Короткий идентификатор, используемый внутри workflow; при копировании узла генерируется новый.

name На вид самый незаметный, но на практике это самое проблемное место из этих четырёх слов:это первичный ключ. Соединения хранят имя, а не id.

Я на холсте переименовал «小单归档» в «小单归档(改)», четыре связи не оборвались ни одна, после сохранения в API connections тоже стало новым именем — это интерфейс подставил за вас. Другой способ: напрямую изменить в JSON name, не трогая соединения — сервер сразу отклонит, причём выдаст две ошибки за раз:

Workflow structure is invalid. nodes[4].name (duplicate_node_name):
Duplicate node name "大单跟进"; connections.判断大单.main[1][0].node
(unknown_connection_target): Connection target "小单归档" does not
reference an existing node

Первая говорит о дублировании имени, вторая — что какая-то линия указывает на несуществующий узел. Обе фразы на самом деле две стороны одного и того же: вы переименовали узел в чужое имя, а соединение по-прежнему указывает на вытесненное имя.

Поэтому имена узлов я советую задавать как имена переменных: не используйте что-то вроде «Set» или «Code 1» и не меняйте их раз в два дня. Пробелы, скобки и китайские символы в имени допустимы, n8n их принимает, но когда вы сами пишете в выражении $('小单归档(改)') , легко пропустить скобку.

Connection: двухуровневый массив, первый уровень — номер выхода

Соединение — это подключение выхода одного узла ко входу другого. В JSON это выглядит так:

"connections": {
  "造两条订单": { "main": [[{ "node": "判断大单", "type": "main", "index": 0 }]] },
  "判断大单": { "main": [
    [{ "node": "大单跟进", "type": "main", "index": 0 }],
    [{ "node": "小单归档", "type": "main", "index": 0 }]
  ]}
}

Разберём по частям: самый внешний ключ —имя исходного узла;main — это тип соединения (обычный поток данных; для AI-части это ai_tool、ai_languageModel и т.д.); индекс во внутреннем массиве— это номер выхода; дальше идёт список целей, один выход может быть подключён к нескольким нижестоящим узлам.

У узла проверки крупных заказов две группы, поэтому это [[...],[...]]. Первая группа соответствует той точке на узле, что помечена true , вторая группа соответствует false. На первый взгляд кажется, что массив вложен слишком глубоко, но на самом деле это просто «какой выход → к кому подключён».

判断大单节点内部:条件大于 500,输出分 True 分支与 False 分支各 1 个项目
Внутри узла всего одно условие: сумма больше 500. Выход справа делится на ветку True и ветку False, после выполнения в каждой по 1 элементу. Это взаимно однозначно соответствует тем двум группам массивов в JSON.

Здесь стоит разобрать одно концептуальное недоразумение. Многие думают, что IF — это «выбор из двух»: условие истинно — идём сюда, ложно — идём туда, проходит только одна ветка.

Нет. IF — этопострочное распределение. Я дал ему принять два заказа, 620 и 180, в результате в ветке true 1 элемент, в ветке false 1 элемент, обе линии горят. Если подать 100 записей, он распределит их по двум сторонам по сумме каждой, может слева 30, справа 70, а может с одной стороны 0.

Поэтому фразу «узел после IF не выполнился» сначала проверьте — возможно, на той стороне просто нет данных. Это не сбой.

Execution: один запуск с одним snapshot

Execution — это один прогон этого workflow. Один ручной клик — один раз, один сработавший таймер — один раз, один запрос от Webhook — один раз. Он не входит в workflow JSON, хранится в другой таблице и привязывается обратно через workflowId mount.

Поля в записи execution, которые меня интересуют:

Поле Значение в этой записи Зачем нужно
id 35 Одна автоинкрементная последовательность на весь экземпляр, не с 1 для каждого workflow
workflowId 9biNEw9D0DqWOVV1 К какому workflow он относится
mode manual 手动跑的还是生产跑的
status success 成功、失败、取消、崩溃、等待中
startedAt / stoppedAt 01:17:42.352 / 01:17:42.513 差 161 毫秒,就是界面上那个「在 161毫秒 内」
workflowVersionId 一个 uuid 这次跑的是哪个版本

最后一行容易忽略但很有用:执行认的是版本。你改完参数没发布,生产跑的还是旧版本,执行记录里挂的就是旧版本的 id。

执行记录列表与跑完的画布,每条连线上标着流过的项目数
左边两条执行,右边是选中那条跑完的样子。每条连线上标着流过的项目数:造两条订单出 2 项,分流后两边各 1 项。这个数字比任何日志都直观

还有一个我这次才注意到的细节:每条执行里存了一份当时的工作流的快照(workflowData)。我把「小单归档」改成「小单归档(改)」之后,回去翻 09:17:42 那条执行,画布上显示的仍然是「小单归档」——因为渲染用的是那条执行自带的快照,不是你现在的画布。

这解释了两件事。好的一面:改参数、删节点,旧记录不会被篡改,回头查问题看到的就是当时的现场。坏的一面:你拿旧记录去对照现在的画布,节点名可能对不上,别以为是自己记错了。

所有执行列表:工作流、状态、开始时间、运行时间、执行 ID 五列
「所有执行」这一页把整个实例的执行摊在一起,第一列是工作流名。同一个工作流三条,ID 34、35、36,连着涨;最下面那条 5 号是 13 天前另一个工作流的

存多久是个现实问题。默认开自动清理:超过 336 小时(14 天)的删掉,总量超过 10000 条也从旧的开始删。成功和失败都存,手动跑的也存。两条规矩谁先撞上算谁:每 5 分钟跑一次的工作流,一天 288 次,14 天攒到 4032 条,先撞年龄;一天 2000 次的,第五天就满一万,先撞条数。所以「执行列表里没有那次」,不一定是没跑,可能已经被清掉了。

串起来看:一次排错的顺序

Четыре слова по отдельности понятны, но при использовании нужен порядок. Моя привычка — идти снаружи внутрь:

  1. Сначала смотрю на статус записи выполнения. Если записи нет, значит, запуск вообще не произошёл — проблема в триггере или статусе публикации, а не в узлах.
  2. Если статус —失败, захожу и смотрю, какой узел горит красным. В деталях узла смотрю входные данные; в большинстве случаев вход уже неверный.
  3. Если статус — успех, но результат неверный, смотрю количество элементов на связях. Если на какой-то линии 0, последующие узлы, естественно, ничего не делают.
  4. Если числа верные, но поля неверные, только тогда стоит подозревать параметры узла или то, что вышестоящий узел изменил тип.

Преимущество такого порядка в том, что каждый шаг отсекает большую часть возможных причин. Наоборот, если сразу уставиться в код узла Code, часто смотришь полчаса и только потом обнаруживаешь, что вышестоящий узел отправил всего 0 записей.

Как понять, что действительно разобрался

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

Во-первых, посчитать.Сколько квадратов на холсте, столько и должно быть в экспортированном JSON nodes в массиве. У меня здесь 5 штук, длина массива — 5. Количество связей тоже: 4 линии соответствуют connections 4 исходным ключам (в одном ключе для определения крупного заказа лежат две группы, но линий всё равно 4).

Во-вторых, изменить одну линию.Удалить узлы на ветке false и снова экспортировать —判断大单 вторая группа массива должна стать пустым массивом, а не исчезнуть целиком. Этот шаг помогает запомнить: «выход определяется позицией, а не наличием или отсутствием нижестоящих узлов».

III. Запустите дважды.После запуска перейдите в «Все выполнения» — должна появиться ещё одна запись, ID на 1 больше предыдущей, а время соответствует моменту, когда вы нажали кнопку. Затем измените один параметр, не публикуйте, запустите один раз, а потом посмотрите в рабочей среде (по расписанию или через Webhook) — используется ли ещё старый параметр. Если это ваш реальный бизнес-процесс, этот шаг рекомендуется выполнять на тестовом workflow.

Пять ошибок, которые действительно случаются

1. Два узла с одинаковым именем.После копирования узла забыли переименовать или вручную отредактировали JSON. При сохранении сервер отклоняет запрос, выдавая Duplicate node name, и одновременно выбрасывает unknown_connection_target. Если видите две ошибки — не паникуйте, просто верните уникальное имя.

2. Изменили имя узла, а выражение не обновили.Соединения интерфейс дополнит автоматически, а выражения — нет. Предыдущий узел назывался A, вы ниже по потоку используете $('A').item.json.amount для получения данных; после переименования в B это выражение ничего не найдёт, и ошибка укажет на строку с выражением, а не на факт переименования.

3. Кнопка публикации серая.В workflow есть только ручной триггер, нет ничего, что можно вывести в рабочую среду. При наведении курсора появится надпись «В этом workflow нет триггерных узлов, требующих публикации». Добавьте Schedule Trigger или Webhook, чтобы появилась возможность публикации.

4. После изменения параметров задача по расписанию выполняется по старой логике.Изменения внесены в черновик, но публикация не нажата. Такие проблемы сложнее всего диагностировать, потому что холст, параметры и тестовые выполнения выглядят нормально, и только поведение в рабочей среде неверно.

5. Запись выполнения не найдена.Три варианта: запись удалена по истечении срока хранения, рабочий процесс удалён и запись исчезла вместе с ним, либо отключён переключатель «сохранять и успешные» (EXECUTIONS_DATA_SAVE_ON_SUCCESS=none). Первые два наиболее часты.

Риски при экспорте, публикации и сохранении следов

JSON рабочего процесса можно целиком экспортировать и передать другому. Здесь есть три места утечки.

Открытый текст в параметрах.Сами учётные данные в JSON отсутствуют (остаётся только ссылка по имени), но parameters может содержать что угодно: token в URL, вручную прописанный key в заголовках HTTP-запроса, path у Webhook.grep один раз key、token、Bearer и отправить дальше — дело двух минут.

В записях выполнения хранятся исходные данные.Что узел выполнял, то и сохраняется в записи в исходном виде: номер заказа, имя клиента, адрес — всё там. При self-hosted можно самому управлять сроком хранения, уменьшить EXECUTIONS_DATA_MAX_AGE — самый простой вариант; на экземпляре с несколькими пользователями лучше задать это сразу.

Вставить JSON, присланный другим человеком, напрямую.Вставив, вы запускаете написанный им код на своём экземпляре — JS в узле Code не спросит, нужно ли это выполнять. Рабочий процесс из неизвестного источника сначала запустите на пустом тестовом экземпляре, а потом уже разбирайтесь.

Краткое резюме

Workflow — это чертёж, node — это блок на чертеже, connection — это стрелка между блоками, execution — это один раз, когда по чертежу ведут строительство. Четыре слова соответствуют четырём вещам, их положение разное, и последствия изменений тоже разные: изменение параметров node влияет на каждое последующее execution, изменение записи execution ничего изменить не может (она и так является записью), изменение имени потянет за собой connection, но expression не обязательно.

Если честно, если мне нужно выбрать одно, что стоит запомнить в первую очередь, — это «execution со snapshot». Это одновременно объясняет, почему старые записи тебя не обманут, почему новые изменения не обязательно вступят в силу и почему после окончания периода очистки уже ничего не найти.

Чтобы понять, разобрался ты или нет, есть глупый способ: открой любой чужой workflow, не смотри на canvas, смотри только на экспортированный JSON — сможешь ли ты сказать, сколько node будет при запуске, сколько путей, какой из них пустой прогон. Если можешь сказать, значит эти четыре слова освоены.

Дальше

Тем, кто ещё не прогнал первый workflow до успешного завершения, сначала смотреть«Первый workflow: ручной trigger → edit fields → code», там рассказывается, как соединить три node и прогнать. Ошибки запуска, занятость port и подобные проблемы, из-за которых не получается войти, — вэтом месте. Оглавление всего курса наэтой странице, всё, что связано с node, — вэтой категории.

В trigger чаще всего проблемы возникают с типом «по расписанию», про него отдельно написана статья:Workflow по расписанию не срабатывает: 5 причин разобрать по одной。

Справочные материалы

  • Key concept glossary: официальные определения терминов workflow, node, execution, publish — именно на них выравнивается данная статья
  • Understand workflows: что такое workflow, а также разделы о создании workflow, компонентах и execution
  • Connect nodes together: создание и удаление соединений, выход одного node подключается ко входу другого
  • Save and publish workflows: временной диапазон автосохранения, публикация закрепляет версию в сети, production execution использует опубликованную версию
  • Understand executions: разница между ручным и production execution, какие execution учитываются в квоте
  • If: типы данных и способы сравнения условий, два выхода
  • Executions переменные окружения: хранение 336 часов, лимит 10000 записей, успешные и неуспешные сохраняются — эти значения по умолчанию

Последнее обновление: 4 ноября 2026 г., использовалась версия n8n 2.43.7.

THE END