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
- Igor PanekWspółzałożyciel SEVENEDGE
- 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.
{
"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.

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.

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ła | Wartość | Po co |
|---|---|---|
Jawne width w każdym sticky | wymagane | usuwa domyślne 240 px |
Jawne height w każdym sticky | wymagane | to samo w pionie |
| Szerokość Sticky Note3 | 640 px | akapit mieści się w trzech liniach |
| Odstęp od góry sticky do pierwszego node'a | 176 px | jedna wartość we wszystkich sekcjach |
| Odstęp między sekcjami | 32 px | notatki 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ą.
python tools/validate_layout.py workflow.json
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ę.

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.
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'a | Wartości od agenta | Stan |
|---|---|---|
@n8n/n8n-nodes-langchain.toolHttpRequest | {placeholder} plus sekcja Placeholder Definitions | wycofany |
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:
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
- Wyeksportuj workflow, zaimportuj go na czystą instancję i patrz na niego tam. Nie na swoją kartę edytora.
- Sprawdź, czy każdy sticky ma w
parametersiwidth, iheight. - Sprawdź, czy każdy node siedzi wewnątrz ramki, która go opisuje — łącznie z sub-node'ami AI.
- Porównaj
typeVersionnode'ów z tym, co dostaje świeżo dodany node na Twojej instancji. - Sprawdź, czy nie używasz wycofanych typów node'ów.
- Uruchom cały workflow, nie pojedynczy node.
- 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
- n8n docs — Notatki na canvasiedokumentacja n8n
- n8n docs — Szablony workflowdokumentacja n8n
- 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.
- Każdemu agentowi trzeba powiedzieć, czego nie robiPoradniki o systemach wieloagentowych mówią o nadawaniu ról. Zestawiliśmy prompty z trzech naszych workflow i okazało się, że łączy je co innego: w każdym stoi zdanie o tym, czego dany agent robić nie ma.
- Agent AI kwalifikujący przetargi z Bazy KonkurencyjnościBaza Konkurencyjności publikuje setki zapytań ofertowych tygodniowo, a prawie żadne nie pasuje do konkretnego dostawcy. Ten workflow odsiewa oczywisty szum lokalnie, a resztę oddaje agentowi, który zwraca decyzję GO albo NO_GO wraz z pytaniami, jakie warto zadać zamawiającemu.


