
Automatyzacja workflow Dify + Make + ClickUp skróciła tworzenie 40 briefów contentowych z 30 godzin do 4 godzin miesięcznie — ale droga do tego wyniku wymagała 3 przebudów, eliminacji halucynacji URL-i i fundamentalnej zmiany podejścia do roli LLM-a w pipeline.
To jest historia o tym, jak zbudowałem automatyzację generowania briefów dla artykułów sponsorowanych — od pierwszego naiwnego “to będzie proste” przez LLM-a, który wymyślał nieistniejące linki, po workflow składający się z 7 nodów, który robi w 6 minut to, co wcześniej zajmowało 45.
Ale przede wszystkim to jest historia o tym, czego nauczyłem się o granicach przydatności dużych modeli językowych. Bo okazuje się, że najważniejszą umiejętnością przy budowaniu automatyzacji z AI nie jest promptowanie. Jest nią wiedzieć, kiedy LLM-a w ogóle nie używać.
Kluczowe liczby i fakty procesu
| Metryka | Przed automatyzacją | Po automatyzacji | Zmiana |
| Czas na 1 brief | 45 min | ~9 sekund (batch) | -99% |
| Czas na 40 briefów/mies. | 30 godzin | 4 godziny | -87% |
| Liczba nodów w Dify | 10 (v1) | 7 (finalna) | -30% |
| Czas przetwarzania workflow | — | 5–7 min na batch | — |
| Powtarzalność struktury | zmienna | 100% identyczna | — |
| Oszczędność roczna | — | ~312 godzin | — |
Spis treści
Punkt wyjścia. Powtarzalna schematyczna praca, która zabiera cenny czas specjalisty
40 briefów miesięcznie po 45 minut każdy to 30 godzin pracy — pełne 4 dni robocze poświęcone na zadanie, które jest powtarzalne, schematyczne i podatne na błędy ludzkie.
Żeby zrozumieć skalę problemu, trzeba wiedzieć czym jest brief contentowy w kontekście artykułów sponsorowanych. Kiedy klient zamawia kampanię content marketingową, jednym z elementów realizacji jest publikacja artykułów sponsorowanych na zewnętrznych portalach. Zanim copywriter usiądzie do pisania, potrzebuje briefu — dokumentu, który precyzuje co ma napisać.
Co zawiera brief contentowy
| Element briefu | Opis | Przykład |
| Tytuł artykułu | Propozycja tytułu z frazą główną | “Leasing samochodu 2026 — kompletny poradnik” |
| Fraza główna | Główne słowo kluczowe do pozycjonowania | “leasing samochodu” |
| Frazy wspierające | Dodatkowe frazy do osadzenia w treści | “leasing operacyjny”, “rata leasingu” |
| Nagłówki H2 | Struktura artykułu | “Leasing operacyjny vs finansowy” |
| Domena wydawcy | Portal, na którym pojawi się artykuł | portal-motoryzacyjny.pl |
| Linki z anchorami | URL + anchor text do osadzenia w treści | “sprawdź ofertę leasingu” → klient.pl/leasing |
| Uwagi do tekstu | Wytyczne specyficzne dla klienta | “Unikać porównań z konkurencją” |
Jeden taki brief to 45 minut pracy. Ale prawdziwy problem leży gdzie indziej — przy 40 briefach miesięcznie błędy się kumulują. Pominięta fraza, zduplikowana domena, zapomniany anchor text. A jakość briefów jest nierówna, bo zależy od dyspozycji dnia, obłożenia pracą i liczby wypitych kaw.
Dlaczego ten stack — ClickUp + Make + Dify
Kluczowa decyzja architektoniczna — każda warstwa robi dokładnie jedną rzecz i nie wie o istnieniu pozostałych.
| Narzędzie | Rola w pipeline | Dlaczego akurat to |
| ClickUp | Hub zarządzania zadaniami — trigger i output | Briefy i tak lądują tutaj jako taski dla copywriterów |
| Make (dawne Integromat) | Orkiestrator — transport danych między systemami | Najlepsza obsługa JSON-a i iteratorów spośród narzędzi no-code |
| Dify (self-hosted) | Silnik AI — przetwarzanie treści przez łańcuch LLM-ów | Wizualny builder workflow, wystawianie jako API, open-source |
| ngrok | Tunel do lokalnego serwera Dify | Dane nie lecą przez dodatkowe chmurowe pośredniki |
Architektura na serwetce:
ClickUp → webhook → Make → HTTP do Dify API (ngrok) → Make → ClickUp
Dify hostuję lokalnie, na własnym serwerze. Do wystawiania API na zewnątrz używam ngrok, który tuneluje ruch. To oznacza pełną kontrolę nad danymi — jedynym zewnętrznym elementem jest sam model LLM.
Wybrałem Make zamiast Zapiera czy n8n, bo Make ma najlepszą obsługę zagnieżdżonego JSON-a i wbudowane iteratory — przy 40 briefach w jednym batchu obie te rzeczy są krytyczne.
Wybrałem Dify zamiast LangChain, bezpośredniego API OpenAI czy Flowise z jednego powodu — Dify pozwala wizualnie budować łańcuchy LLM-ów, mieszać je z Code nodami i Template nodami (Jinja2), a efekt końcowy wystawić jako jedno API. Widzę co się dzieje, mogę debugować wizualnie, a Make odpytuje endpoint jednym HTTP requestem.
Pierwsze zderzenie z rzeczywistością. 3 problemy, które zmieniły projekt
Pierwszy prototyp miał 10 nodów i robił dokładnie to, co chciałem — w teorii. W praktyce LLM zaczął halucynować URL-e, ignorować instrukcje dystrybucji domen i gubić briefy.
Problem 1 – Halucynowane URL-e
Dałem modelowi listę domen wydawców i poprosiłem o przypisanie ich do briefów. Prompt wyraźnie mówił: “użyj TYLKO domen z poniższej listy”. Model je widział, rozumiał polecenie — i mimo to generował własne URL-e. Idealne adresy do nieistniejących podstron na prawdziwych domenach.
Gdybym nie sprawdzał outputu ręcznie, copywriter dostałby brief z martwymi linkami. Klient dostałby artykuł z martwymi linkami. Dlatego też ostatecznie specjalista sam będzie wypełniał pole z domenami (ceny tych domen są ruchome, więc na ten moment ciężko to zautomatyzować)
Problem 2 – LLM jako samozwańczy strateg
Poprosiłem model o round-robinowe przypisanie linków — żeby każdy artykuł miał przypisane zróżnicowane linki z anchorami. LLM konsekwentnie wybierał jeden “najlepszy” link z anchorem i przypisywał ją do większości briefów. Przeformułowywałem prompt, dodawałem przykłady, wzmacniałem instrukcje. Nic — model był przekonany, że wie lepiej.
To nie jest bug. LLM optymalizuje pod “najlepszą” odpowiedź, nie pod “najbardziej sprawiedliwą dystrybucję”. To fundamentalna cecha modeli językowych — i fundamentalna przeszkoda, jeśli potrzebujesz deterministycznej logiki.
Problem 3 – 1 brief zamiast 7
Przy większej liczbie fraz kluczowych model “gubił” briefy. Zamiast wygenerować osobny brief dla każdego klastra tematycznego, scalał je w jeden mega-brief albo pomijał połowę. Z 10 oczekiwanych briefów dostawałem 3. Albo 1.
Podsumowanie problemów
| Problem | Przyczyna | Rozwiązanie |
| Halucynowane URL-e | LLM generuje “pasujące” linki zamiast używać listy | Przeniesienie przypisania do Code node’a |
| Brak round-robin | LLM optymalizuje pod “najlepszą” odpowiedź | Deterministyczna pętla for z modulo |
| Gubienie briefów | Limit uwagi modelu przy dłuższym output | Iteration node — 1 brief per przebieg pętli |
Lekcja, która zmieniła wszystko — podział na zadania językowe i deterministyczne
LLM jest świetny w zadaniach wymagających rozumienia języka. Jest fatalny w zadaniach wymagających precyzji i deterministycznej logiki. Oddzielenie tych dwóch typów zadań to punkt zwrotny każdego projektu automatyzacji opartego o AI.
Kiedy to zdanie w końcu do mnie dotarło — nie jako abstrakcyjna zasada, ale jako doświadczenie po dniach debugowania — zacząłem patrzeć na każdy node inaczej. Przy każdym zadaniu pytałem: “Czy to wymaga rozumienia języka?”.
| Zadanie | Czy wymaga języka? | Kto powinien robić? | Rezultat |
| Generowanie briefu z fraz kluczowych | Tak — kreatywność, kontekst | LLM | Tytuł, frazy, nagłówki |
| Osadzanie anchorów w treści briefu | Tak — naturalność języka | LLM | Anchor w kontekście zdania |
| Przypisanie linków round-robin | Nie — deterministyczny rozkład | Kod (pętla for + modulo) | Równomierny rozkład |
| Parsowanie nagłówków H2 | Nie — split po znacznikach | Kod (parser) | Pewny i powtarzalny |
| Scalanie outputów w JSON | Nie — formatowanie danych | Make (JSON Parse + Iterator) | Czysta tablica obiektów |
Przypisanie linków round-robin to pętla for z licznikiem modulo. Przeniosłem to do Code node’a i problem zniknął natychmiast. Żadnych preferencji, żadnego “w mojej ocenie ten link z anchorem lepiej pasują”. Po prostu: link 1, link 2, link 3, link 1, link 2, link 3.
Zasada! Jeśli zadanie można opisać jako algorytm — nie używaj do niego LLM-a.
Ewolucja workflow — od 10 nodów do 7
Każda kolejna wersja workflow była prostsza od poprzedniej. Budowanie automatyzacji opartej o AI to przede wszystkim usuwanie złożoności, nie dodawanie.
Porównanie wersji
| Cecha | Wersja 1 (10 nodów) | Wersja 2 (8 nodów) | Wersja 3 — finalna (7 nodów) |
| Klasteryzacja fraz | LLM wymyśla klastry | Eliminacja — iteracja po H2 | Iteracja po H2 |
| Przypisanie linków | LLM (halucynacje) | Code node (Python) | Code node (Python) |
| Scalanie outputów | Code node + Template | Code node | Przeniesione do Make |
| Parsowanie | Code node (Python) | Code node (Python) | Parameter Extractor (natywny) |
| Format briefu | Rozbudowany (outline, SEO, konkurencja) | Uproszczony | Uproszczony |
| Outputy END | 3 osobne (brief i linki) | 3 osobne | 1 skonsolidowany JSON |
| Stabilność | Krucha — “trzymaj kciuki” | Lepsza | Przewidywalna |
Wersja 1. “Zróbmy wszystko” (10 nodów)
Klasteryzacja fraz przez LLM → generowanie briefów w iteracji → osobne przypisanie domen przez LLM → osobne umieszczanie anchorów przez LLM → Code node scalający → Template z raportem Markdown → END z trzema outputami. Działało, ale wystarczył niespodziewany format JSON-a albo pusty string zamiast tablicy — i cały pipeline się sypał.
Wersja 2. “Ile H2, tyle briefów” (8 nodów)
Kluczowa zmiana: wyrzuciłem klasteryzację fraz przez LLM. Iterowanie po nagłówkach H2 artykułu źródłowego daje lepsze i bardziej przewidywalne rezultaty. Ile H2 w artykule, tyle briefów powstanie. Zero zgadywania.
Wyrzuciłem też raport Markdown i uproszczony format briefu (bez outline’u, SEO guidelines i analizy konkurencji). Copywriter czyta opis taska w ClickUp, nie dwudziestostronicowy dokument.
Wersja 3. “Python odpada” (7 nodów)
Code nody w Pythonie wywalały błędy w Dify — JSONDecodeError z pustego stringa, problemy z formatem inputów. Zamiast walczyć z debugowaniem edge case’ów, zamieniłem Code node na Parameter Extractor — natywny node Dify, który wyciąga strukturę z tekstu za pomocą LLM-a, ale zwraca ją jako zdefiniowany schemat. Scalanie outputów przeniosłem do Make.
Ironicznie, ta wymuszona błędami decyzja dała najczystszą architekturę. Dify przetwarza treść. Make transportuje dane. Żadna warstwa nie wchodzi w kompetencje drugiej.
Finalna architektura Dify
START → Parameter Extractor → ITERATION (Briefy per H2) → TEMPLATE (Join) → Python (Przypisanie linków z anchorami) → END
7 nodów. Każdy robi dokładnie jedną rzecz.
Jak to działa krok po kroku
Cały pipeline od triggera w ClickUp do gotowych tasków dla copywriterów trwa 5–7 minut:
→ Nowy task w ClickUp odpala webhook — Make przechwytuje zdarzenie i zbiera dane: frazy kluczowe, nagłówki H2, linki z anchorami.
→ Make składa JSON i wysyła POST do Dify API przez ngrok (tuneluje ruch do lokalnego serwera).
→ Dify klasteryzuje frazy po nagłówkach H2 — ile nagłówków w artykule źródłowym, tyle briefów powstanie. Bez zgadywania, bez “kreatywnych” decyzji modelu.
→ Każdy klaster przechodzi przez Iteration node — LLM generuje brief z tytułem, frazą główną, frazami wspierającymi i propozycją nagłówków.
→ Code node przypisuje linki wydawców round-robin — deterministycznie, po kolei, bez faworyzowania. Pętla for z licznikiem modulo.
→ Osobny LLM node osadza anchory w kontekście każdego briefu — tu model jest w swoim żywiole, bo to zadanie językowe.
→ Gotowy JSON wraca do Make — tablica obiektów, gdzie 1 obiekt = 1 brief ze wszystkim, co potrzebne.
→ Make iteruje po tablicy i tworzy osobne taski w ClickUp. Jeden brief, jeden task, gotowy do wysłania copywriterowi.
Make jako orkiestrator — pułapki integracji
Dify jest czystym procesorem — dostaje JSON, zwraca JSON, nie wie nic o ClickUp. Make obsługuje całą logikę transportu danych. Ta separacja jest świadoma.
Scenariusz w Make: webhook odbiera event z ClickUp → moduł HTTP wysyła POST do Dify API → JSON Parse → Iterator rozbija tablicę → moduł ClickUp Create Task tworzy zadania. 4 moduły po triggerze.
Pułapki, które kosztowały godziny debugowania
| Pułapka | Objaw | Rozwiązanie | Czas stracony |
| Escapowanie JSON-a | Entery i cudzysłowy z ClickUp rozbijały body requestu | Jawne encodowanie tekstu przed wrzuceniem do body | ~2h |
| Timeout Make | Domyślne 40s za krótkie — request przerywany | Ustawienie na 120–180 sekund | ~1h |
| Publish w Dify | Zmiany widoczne w Preview, ale Make dostaje starą wersję | Kliknięcie “Publish” po każdej zmianie w Dify | ~1h |
| Zmienne wpisane ręcznie | LLM dostaje literalny string “frazy_kluczowe” zamiast wartości | Podpięcie zmiennych przez selektor {x}, nie wpisywanie ręczne | ~1.5h |
| Puste inputy z Make | JSONDecodeError w Code nodzie Dify | Walidacja inputu + default value na Fail Branch | ~2h |
Dify ma dwie wersje workflow — roboczą (draft) i opublikowaną (published). Make odpytuje opublikowaną wersję. Jeśli zmienisz coś w Dify i nie klikniesz “Publish”, Make nadal widzi starą wersję. Godzina szukania błędu w Make, który był w jednym nieklikniętym przycisku.
Dify od kuchni. Co warto wiedzieć przed budowaniem?
Dify nie jest narzędziem no-code — jest narzędziem low-code z wizualnym interfejsem. Pod spodem nadal musisz rozumieć JSON, Jinja2, formatowanie promptów i obsługę błędów.
Typy nodów w Dify i ich zastosowanie
| Typ node’a | Co robi | Kiedy używać | Gotcha |
| LLM | Odpytuje model z promptem | Zadania językowe — generowanie, analiza, klasyfikacja | Niedeterministyczny output |
| Code | Wykonuje Python/JavaScript | Deterministyczna logika — parsowanie, formatowanie, round-robin | Dify nie obsługuje wszystkich bibliotek |
| Template | Formatuje tekst przez Jinja2 | Łączenie danych, formatowanie outputu | To NIE jest LLM — nie rozumie instrukcji słownych |
| Parameter Extractor | Wyciąga strukturę z tekstu przez LLM | Zamiennik Code node’a dla parsowania | Wolniejszy niż Code, ale stabilniejszy |
| Iteration | Pętla po tablicy | Generowanie wielu briefów — 1 brief per przebieg | Mnożnik czasu — 10 iteracji × czas LLM |
Kluczowe obserwacje z praktyki
Template node ≠ LLM. Wrzucenie do Template node’a instrukcji “Proszę, połącz poniższe briefy” nie zadziała. Template node formatuje za pomocą Jinja2, nie myśli. Trzeba mu dać czysty szablon:
[{% for brief in arg1 %}{{ brief | trim }}{% if not loop.last %},{% endif %}{% endfor %}]
Jedna linia. Zero instrukcji słownych.
Hosting lokalny + ngrok. Darmowy plan ngrok zmienia URL po każdym restarcie — trzeba aktualizować endpoint w Make. Płatny plan daje stały subdomain. Alternatywnie: Docker na VPS, ale wtedy wraca kwestia bezpieczeństwa danych.
Error handling. Każdy LLM node powinien mieć Fail Branch z Default Value ({}). Bez tego jeden timeout modelu rozbija cały pipeline.
Wyniki: 30 godzin → 4 godziny miesięcznie
Automatyzacja skróciła czas tworzenia 40 briefów z 30 godzin do 4 godzin miesięcznie — oszczędność 26 godzin (87%). W skali roku to ponad 312 godzin zwróconych zespołowi.
| Metryka | Ręcznie | Automatycznie | Różnica |
| Czas na 1 brief | 45 min | ~9s (w batchu) | -99% |
| Czas na 40 briefów | 30h | 4h (z weryfikacją) | -87% |
| Powtarzalność formatu | Zmienna | 100% identyczna | — |
| Ryzyko pominięcia frazy | Wysokie | Brak (dane z inputu) | — |
| Duplikacja linków | Zdarza się | Wykluczona (round-robin) | — |
| Skalowalność | Liniowa (nowy klient = nowe godziny) | Stała (nowy klient = 1 task) | — |
4 godziny to czas razem z weryfikacją wyników. Sprawdzam każdy batch ręcznie przed wysłaniem do copywriterów, bo LLM potrafi wygenerować coś, co wygląda dobrze, ale nie jest dobrze.
Trzecia korzyść, mniej oczywista — skalowalność. Przy ręcznym procesie każdy nowy klient oznacza proporcjonalnie więcej godzin pracy. Przy automatyzacji każdy nowy klient to jeden dodatkowy task w ClickUp. Reszta dzieje się sama. Bariera wzrostu przestaje być operacyjna.
5 zasad budowania automatyzacji opartych o AI
Jeśli budujesz własną automatyzację z LLM-em — w Dify, LangChain, Flowise czy cokolwiek innego — te zasady zaoszczędzą ci tygodnia debugowania.
Zasada 1. Zacznij od najprostszego flow
Moja wersja 1 miała 10 nodów, klasteryzację, Code nody w Pythonie i 3 osobne outputy. Gdybym zaczął od 4 nodów i dodawał złożoność dopiero wtedy, gdy była potrzebna, zaoszczędziłbym tydzień. Overengineering na etapie prototypu to pułapka, w którą wpada prawie każdy.
Zasada 2. Dziel zadania na językowe i deterministyczne
Przy każdym nodzie pytaj: czy to wymaga rozumienia języka? Jeśli nie, nie używaj LLM-a. Round-robin, parsowanie, formatowanie, filtrowanie — to kod. LLM jest drogi (tokeny), wolny (sekundy per request) i niedeterministyczny (różny output przy tym samym inpucie). Kod jest tani, szybki i przewidywalny.
Zasada 3. Testuj z Make od pierwszego dnia
Preview w Dify to nie to samo co wywołanie API z Make. Inne formatowanie inputów, inne timeouty, inna obsługa błędów. Im wcześniej połączysz oba końce integracji, tym wcześniej zobaczysz prawdziwe problemy — escapowanie JSON-a, timeout, zmienne podpięte jako tekst zamiast przez selektor.
Zasada 4. Każda warstwa robi jedną rzecz
Dify przetwarza treść. Nie wie, skąd przyszły dane ani dokąd trafią. Make transportuje dane. Nie wie, co jest w briefie. ClickUp zarządza zadaniami. Nie wie, że w tle pracuje AI. Separacja pozwala debugować, wymieniać i skalować każdą warstwę niezależnie.
Zasada 5. Automat generuje, człowiek waliduje
Sprawdzam każdy batch briefów zanim trafi do copywriterów. Nie dlatego, że nie ufam automatyzacji, ale dlatego, że wiem, iż LLM potrafi wygenerować coś, co wygląda poprawnie, ale nie jest poprawne. 4 godziny weryfikacji miesięcznie to nie koszt. To ubezpieczenie jakości.
Czego nie da się zautomatyzować (i nie warto próbować)?
Automatyzacja jest świetna w zabieraniu ludziom pracy, którą nienawidzą. Jest fatalna w zabieraniu im pracy, którą powinni robić.
| Zadanie | Dlaczego zostaje u człowieka |
| Ocena jakości briefu | Wymaga znajomości klienta, branży i kontekstu strategicznego |
| Decyzje strategiczne | Priorytetyzacja fraz, budżet linkbuildingowy, dobór wydawców |
| Relacje z copywriterami | Feedback, korekty stylu, dopasowanie tonu do marki klienta |
| Walidacja outputu | LLM potrafi generować pozornie poprawne, ale błędne treści |
| Sprawdzenie fraz w Ahrefs | API ahrefs jest za drogi a można za darmo połączyć się poprzez Claude z MCP Ahrefs i zweryfikować frazy ręcznie |
Co dalej?
Workflow działa produkcyjnie i reaguje na każdy nowy task w workspace. Trigger w Make automatycznie wykrywa nowe zadania w ClickUp, więc wystarczy stworzyć task z odpowiednimi danymi i reszta dzieje się sama.
Kolejne kroki:
→ Error handling — żeby przy nieudanym przetworzeniu Dify task w ClickUp dostawał flagę “do ręcznego przeglądu” zamiast cichego błędu.
→ Walidacja outputu po stronie Make — sprawdzenie, czy JSON zawiera wszystkie wymagane pola i czy przypisany link faktycznie istnieje na liście.
→ Fine-tuning mniejszego modelu (np. Qwen) na zebranym datasecie briefów. Duży model jest świetny do prototypowania, ale kiedy wiem dokładnie jaki output chcę, mały dedykowany model będzie szybszy, tańszy i bardziej przewidywalny. To jednak temat na osobny artykuł.
→ Ostateczne sprawdzenie fraz w ahrefs – tutaj prosty powód, API ahrefs jest za drogi a można za darmo połączyć się poprzez Claude z MCP Ahrefs i zweryfikować frazy ręcznie.
Podsumowanie
Automatyzacja briefów contentowych nie jest problemem technologicznym, ale problemem projektowym. Narzędzia są dostępne. API otwarte. Dokumentacja w większości istnieje. Prawdziwe wyzwanie to zrozumienie, gdzie kończy się rola LLM-a, a zaczyna rola kodu. Gdzie kończy się rola procesora, a zaczyna rola orkiestratora. I przede wszystkim — akceptacja, że pierwsza wersja będzie zła, i to jest w porządku.
7 nodów. 4 godziny zamiast 30. I LLM, który w końcu przestał kłamać o linkach.

Specjalizuję się w technicznym SEO oraz Generative Engine Optimization (GEO), pomagając markom budować widoczność zarówno w klasycznych wynikach Google, jak i w odpowiedziach generowanych przez AI. Na co dzień łączę pozycjonowanie z automatyzacją procesów — projektuję i wdrażam pipeliny no-code i low-code oraz tworzę dedykowane narzędzia dla agentów AI, które skalują powtarzalne zadania SEO. Od 2024 roku pracuję z witrynami e-commerce, serwisami contentowymi i stronami usługowymi, realizując audyty techniczne, wdrożenia structured data i strategie content marketingowe. Na tym blogu dzielę się wiedzą z pogranicza SEO, AI i automatyzacji — od semantycznej analizy treści, przez optymalizację pod LLM-y, po eksperymenty z nowymi formatami wyszukiwania.
Więcej artykułów
#3 SEOLab: Jak budować treści, by wyświetlać się w AI Overview?
#2 SEOLab: Google AI Studio, plik llms.txt oraz wpływ BING na pozycjonowanie w Chat GPT
AI, brand mentions i przyszłość SEO. Wnioski z Festiwalu SEO 2025 oczami zespołu KWISS
Sezonowość a SEO – jak dostosować strategię pozycjonowania do trendów sezonowych?
#9 SEOLab. Dlaczego dobre procesy to za mało, żeby rosnąć jako agencja?
