Bezpłatna rozmowa

Co się psuje, gdy ktoś importuje Twój workflow n8n

Zgłosiliśmy workflow do biblioteki n8n i wrócił odrzucony przez jedną brakującą właściwość w JSON-ie. Pół roku później ten sam plik wysypał się na naszej instancji jeszcze trzy razy, z zupełnie innych powodów.

Autor

Opublikowano:
Ostatnia weryfikacja:
Wersja n8n:
2.8.4

W skrócie

Co robi

  • wyjaśnia, dlaczego workflow działający u autora potrafi nie ruszyć u odbiorcy
  • dostarcza skrypt sprawdzający layout eksportu przed zgłoszeniem

Czego nie robi

  • nie sprawdza treści notatek
  • nie weryfikuje usunięcia credentiali
  • nie jest twardą bramką CI bez kalibracji stałych

Czego wymaga

  • Python 3
  • wyeksportowany plik JSON

Co się psuje, gdy ktoś importuje Twój workflow n8n

Zgłosiliśmy workflow do biblioteki template'ów n8n. Wrócił odrzucony: tekst notatek nachodzi na node'y. U nas wyglądał dobrze. U recenzenta nie.

Przyczyną była jedna brakująca właściwość w wyeksportowanym JSON-ie. Ale kiedy pół roku później zaimportowaliśmy ten sam plik na własną, nowszą instancję, wysypał się jeszcze trzy razy z zupełnie innych powodów.

Ten tekst jest o tym, co eksport n8n zabiera ze sobą, a czego nie — i dlaczego plik, który u Ciebie działa, u kogoś innego potrafi nie ruszyć.

Warstwa pierwsza: notatka, która sama się zwija

Sticky notes w n8n mają w parameters pola width i height. Kiedy rozciągasz notatkę myszką, oba się zapisują. Kiedy jej nie ruszasz albo edytujesz JSON ręcznie, mogą nie istnieć.

Brak width nie znaczy „zachowaj wygląd". Przy imporcie n8n przyjmuje domyślne 240 pikseli.

sticky-note-3.json
{
  "parameters": {
    "content": "## Qualify with AI\n\nThe bid qualification agent evaluates candidate tenders using an Anthropic chat model, an HTTP tool for tender details, and a structured output parser to produce consistent GO / NO-GO verdicts."
  },
  "type": "n8n-nodes-base.stickyNote",
  "typeVersion": 1,
  "position": [2048, 96],
  "name": "Sticky Note3"
}

W naszej sesji ta notatka była rozciągnięta, akapit mieścił się w trzech liniach, a ramka sekcji obejmowała agenta i wszystkie trzy jego sub-node'y. Po zwinięciu do 240 pikseli dzieją się dwie rzeczy.

Akapit przewija się z trzech linii na osiem i dochodzi do samej krawędzi node'a pod spodem. Ile dokładnie wychodzi poza ramkę, zależy od renderowania czcionek — u recenzenta nachodziło, u nas mija o kilka pikseli. Ta zmienność jest tu sednem, nie przypisem: przy 240 pikselach układ nie ma żadnego zapasu, więc czy wyjdzie „ciasno" czy „zepsuto", decyduje czyja maszyna to rysuje.

Odrzucony eksport po imporcie: ramka sekcji Qualify with AI zwężona, tekst zawinięty na osiem linii
Porównaj szerokość ramki Qualify with AI z sąsiednią sekcją. Logika się nie zmieniła, tylko zapisana geometria.

Drugi problem tego samego zwinięcia

Zwężenie w poziomie ma konsekwencję, którą widać jednoznacznie. Dwa node'y zostają poza jakąkolwiek ramką.

Fetch Tender Details i Parse Tender Verdict to sub-node'y agenta. Wizualnie należą do sekcji „Qualify with AI". Kiedy notatka zwęża się do 240 pikseli, wypadają za jej prawą krawędź, wiszą między sekcjami, a ich podpisy zlewają się w jedną nieczytelną linię.

Nikt tego nie zauważa przy budowaniu, bo canvas czyta się bliskością. Recenzent otwierający plik na zimno czyta go granicami — a granice mówiły, że te dwa node'y nie należą do niczego.

Zbliżenie zwiniętej sekcji: node'y Fetch Tender Details i Parse Tender Verdict poza ramką, z zachodzącymi na siebie podpisami
Dwa sub-node'y agenta, poza granicą, która ma je opisywać.

Naprawa i skrypt

Nie poprawialiśmy notatki na oko, bo to właśnie oko wyprodukowało problem. Zamiast tego przeliczyliśmy geometrię i zweryfikowaliśmy wynik.

RegułaWartośćPo co
Jawne width w każdym stickywymaganeusuwa domyślne 240 px
Jawne height w każdym stickywymaganeto samo w pionie
Szerokość Sticky Note3640 pxakapit mieści się w trzech liniach
Odstęp od góry sticky do pierwszego node'a176 pxjedna wartość we wszystkich sekcjach
Odstęp między sekcjami32 pxnotatki nie stykają się krawędziami

Diff dotknął wyłącznie position, width i height. Parametry node'ów, prompt agenta, kod i wszystkie połączenia zweryfikowane jako nietknięte. Naprawa layoutu, która po cichu zmienia logikę, jest gorsza niż sam layout.

Skrypt sprawdza cztery rzeczy: czy tekst mieści się w notatce, czy nie nachodzi na node, czy notatki nie zachodzą na siebie i czy node'y się nie nakładają.

validate_layout.py
python tools/validate_layout.py workflow.json
validate_layout.py
NODE_W, NODE_H = 200, 96
SUB_W, SUB_H   = 100, 100        # sub-node'y AI renderuja sie mniejsze
STICKY_DEFAULT_W, STICKY_DEFAULT_H = 240, 160
CHAR_W, LINE_H, PADDING = 7.2, 21, 32

def rendered_text_height(content: str, width: int) -> int:
    """Ile miejsca zajmie tekst przy danej szerokosci notatki."""
    cols = max(int((width - 24) / CHAR_W), 1)
    lines = 0
    for raw in content.split("\n"):
        lines += max(1, -(-len(raw) // cols))   # dzielenie w gore
    return lines * LINE_H + PADDING

def overlap(a, b) -> bool:
    ax, ay, aw, ah = a
    bx, by, bw, bh = b
    return ax < bx + bw and bx < ax + aw and ay < by + bh and by < ay + ah

Pełny skrypt jest w repozytorium, razem z parą plików przed i po naprawie — można go uruchomić na obu i zobaczyć różnicę.

Wyjście skryptu walidacyjnego na obu eksportach: odrzucony plik nie przechodzi na brakującym width, poprawiony przechodzi
Uruchom na katalogu examples/layout-rejection w repozytorium, żeby to odtworzyć.

Warstwa druga: wersje node'ów

Poprawiony workflow został przyjęty i opublikowany. Pół roku później zaimportowaliśmy ten sam plik na własną, zaktualizowaną instancję. Agent odmówił współpracy z modelem czatu:

This model is not supported in 2 version of the Agent node. Please upgrade the Agent node to the latest version.

Eksport przypina typeVersion każdego node'a do momentu zapisu. Agent miał wersję 2. Świeżo dodany node agenta na tej samej instancji dostawał 3.1.

To jest sprawdzalne w trzydzieści sekund: dodaj czysty node na pustym canvasie, wyeksportuj mini-workflow i odczytaj jego typeVersion. Potem podnieś wartość w pliku.

bump_typeversions.py
TARGET = {
    "@n8n/n8n-nodes-langchain.agent":       3.1,
    "@n8n/n8n-nodes-langchain.chatTrigger": 1.4,
}

for node in workflow["nodes"]:
    want = TARGET.get(node.get("type"))
    if want and node.get("typeVersion", 0) < want:
        node["typeVersion"] = want

Warstwa trzecia: node, który przestał istnieć

Po podniesieniu wersji agenta wysypało się narzędzie HTTP. Komunikat mówił „Invalid URL", a w panelu wyjścia wisiało zdanie, które okazało się właściwą wskazówką:

No parameters are set up to be filled by AI.

Okazało się, że w n8n są dwa różne node'y do wywołań HTTP jako narzędzia agenta, a eksport niósł ten starszy.

Typ node'aWartości od agentaStan
@n8n/n8n-nodes-langchain.toolHttpRequest{placeholder} plus sekcja Placeholder Definitionswycofany
n8n-nodes-base.httpRequestTool$fromAI('nazwa', 'opis', 'typ')aktualny

Ten starszy nadal renderuje sekcję Placeholder Definitions i podpowiedź opisującą składnię {placeholder}. Tyle że nic już tych placeholderów nie wypełnia. Node zgłasza brak parametrów do wypełnienia, a klamry docierają do API jako dosłowny tekst — stąd błąd o nieprawidłowym adresie, który wcale nie dotyczy adresu.

Poprawna postać wygląda tak:

URL narzędzia, tryb Expression
https://api.example.com/records/{{ $fromAI('record_id', 'Numeric record ID', 'string') }}

Dwie rzeczy warto o tym wiedzieć. $fromAI rozwija się wyłącznie wtedy, gdy node jest podpięty do agenta jako Tool i to agent go wywołuje — uruchomienie samego node'a przyciskiem „Execute step" przepuszcza wyrażenie bez zmian, co wygląda jak zepsuty adres. I z tego samego powodu podgląd pod polem URL pokazuje w edytorze [undefined]. To jest normalne.

Warstwa czwarta: API pod spodem też się zmienia

Ostatnia rzecz nie jest już winą n8n. Narzędzie miało ustawione dataField na data.advertisement, a rejestr odpowiedział:

Target field "data.advertisement" not found in response. The response contained these fields: [status, data]

Struktura odpowiedzi zmieniła się między napisaniem workflow a jego ponownym uruchomieniem. Nic w n8n tego nie wykryje, bo z punktu widzenia platformy zapytanie się powiodło.

To jest argument za polem „ostatnia weryfikacja" w dokumentacji i za tym, żeby ta data znaczyła „wtedy to uruchomiliśmy", a nie „wtedy to opisaliśmy".

Checklista przed zgłoszeniem

  1. Wyeksportuj workflow, zaimportuj go na czystą instancję i patrz na niego tam. Nie na swoją kartę edytora.
  2. Sprawdź, czy każdy sticky ma w parameters i width, i height.
  3. Sprawdź, czy każdy node siedzi wewnątrz ramki, która go opisuje — łącznie z sub-node'ami AI.
  4. Porównaj typeVersion node'ów z tym, co dostaje świeżo dodany node na Twojej instancji.
  5. Sprawdź, czy nie używasz wycofanych typów node'ów.
  6. Uruchom cały workflow, nie pojedynczy node.
  7. Uruchom skrypt walidacyjny.

Punkt pierwszy łapie najwięcej. Punkt szósty jest tam, bo połowę wczorajszego wieczoru straciliśmy na testowaniu narzędzia agenta w oderwaniu od agenta.

Ograniczenia

Konkretne wersje w tym tekście zestarzeją się. typeVersion agenta równy 3.1 i typ n8n-nodes-base.httpRequestTool są aktualne dla n8n 2.8.4. Metoda sprawdzenia zostaje ta sama, wartości nie.

Skrypt walidacyjny sprawdza geometrię, nie treść. Przejdzie na workflow z notatkami, które nic nie tłumaczą.

Nie mamy pomiaru, jak często to dotyka innych. Opisujemy jeden przypadek zgłoszenia i jeden przypadek importu po pół roku, nie badanie.

Do czego to się sprowadza

Biblioteka template'ów n8n renderuje Twój workflow z pliku, na cudzym ekranie, bez pamięci o Twojej sesji. To samo robi każdy, kto pobierze eksport z Twojego repo za pół roku.

Wszystko, co czyni ten workflow czytelnym i działającym, musi być zapisane wprost. Notatka bez szerokości nie jest notatką, która zachowuje rozmiar — jest notatką, która zgaduje, i zgaduje 240 pikseli.

Weź to do siebie

Jak to zacytować

Igor Panek (2026). Co się psuje, gdy ktoś importuje Twój workflow n8n. SEVENEDGE. https://sevenedge.pl/pl/workflows/import-eksportu-n8n-co-sie-psuje (dostęp: 29 sierpnia 2026)

Źródła

  1. n8n docs — Notatki na canvasiedokumentacja n8n
  2. n8n docs — Szablony workflowdokumentacja n8n
  3. n8n docs — HTTP Request Tooldokumentacja n8n

Kto za tym stoi

Igor Panek

Współzałożyciel SEVENEDGE

Współzałożyciel SEVENEDGE. Odpowiada za automatyzacje procesów: buduje i utrzymuje instancję n8n obsługującą wdrożenia klienckie, publikuje workflow w bibliotece n8n. Poza automatyzacjami pracuje na tym samym stacku co drugi współzałożyciel — Next.js, FastAPI, PostgreSQL.

Powiązane dokumenty

Inne przepływy, które opisaliśmy tak samo dokładnie.

7SVENZwykle odpowiada od ręki
Cześć! Jestem SVEN z SEVENEDGE. Robimy apki, SaaS i automatyzacje AI. W czym pomóc?
SVEN, maskotka SEVENEDGE, analizuje zgłoszenieSVEN, maskotka SEVENEDGE, zastanawia się przy kawieSVEN, maskotka SEVENEDGE, pracuje przy laptopie
Masz pomysł na apkę?