1. Czym jest workflow w kontekście ChatGPT App
Skoro poradziliście sobie z autoryzacją, zasłużyliście na nagrodę. Przejdźmy do bardzo ciekawego tematu — workflow w ChatGPT App. Samo słowo „workflow” wielu osobom przywodzi na myśl flashbacki z diagramami BPMN i ponurym korporacyjnym softem. Spokojnie: w kontekście ChatGPT App interesuje nas znacznie lżejsza wersja.
W tym kursie przez workflow rozumiemy wieloetapowy scenariusz, w którym:
- jest jasny cel (np. dobrać prezent i doprowadzić do zakupu),
- są kolejne kroki (wywiad → generowanie opcji → doprecyzowanie → finał),
- w każdym kroku są role dla GPT, widżetu i narzędzi.
Ważne: workflow to nie „jedna metoda na serwerze MCP”. To kompozycja:
- rozumowania modelu (jakie pytania zadać, które narzędzie wywołać),
- wywołań narzędzi (MCP/Agents),
- kroków UI w widżecie,
- stanu po stronie backendu.
Czyli nie macie jednego „super‑narzędzia” solve_everything, lecz kilka prostych, uruchamianych na różnych etapach. I nie jednego „mega‑widżetu”, lecz niewielki zestaw ekranów/stadiów, każdy do własnego podzadania.
„Trójkąt odpowiedzialności” w workflow
Wygodnie myśleć o workflow jak o tańcu trzech uczestników:
| Rola | Zadanie w workflow | Przykład w GiftGenius |
|---|---|---|
| GPT | Mózg. Rozumie intencje użytkownika, decyduje, kiedy krok jest zakończony i który będzie następny. Może wywoływać narzędzia. | Rozumie „chcę coś dla geeka” i decyduje się wywołać search_items(category="geek"). |
| Widget | Twarz. Renderuje bieżący krok, pokazuje tylko to, co istotne, zbiera kliknięcia i wpisy. Przechowuje stan UI. | Pokazuje formularz „Dla kogo prezent?”, potem karty prezentów, a następnie przycisk „Kup”. |
| MCP/Agent | Ręce. Wykonuje ciężką i strukturalną pracę, waliduje dane, przechowuje stan biznesowy. | Przechowuje profil obdarowywanego, wykonuje zapytanie do katalogu prezentów, filtruje po budżecie. |
Te trzy role razem realizują ten sam scenariusz, ale na różnych poziomach: GPT decyduje „co dalej”, widżet pokazuje „co teraz”, a MCP odpowiada za to, co faktycznie dzieje się z danymi.
2. Przykład workflow na bazie GiftGenius
Weźmy znany już scenariusz GiftGenius — asystent do doboru prezentów. Można go opisać jako prostego liniowego kreatora.
Kolejność kroków może być taka:
- Zebrać podstawowe informacje o obdarowywanym.
- Określić budżet i ograniczenia.
- Wygenerować i przefiltrować pomysły na prezenty.
- Pokazać kandydatów, umożliwić polubienie/ukrywanie.
- Przejść do finalizacji (Checkout) lub zapisać zestawienie.
Ten sam scenariusz można przedstawić jako małą „maszynę stanów”:
stateDiagram-v2
[*] --> Profiling
Profiling --> ProfilingDone: profil wypełniony
ProfilingDone --> Browsing: wygenerowano pomysły
Browsing --> Refining: użytkownik doprecyzował filtry
Refining --> Browsing: zaktualizowana lista
Browsing --> Checkout: wybrano prezent
Checkout --> Success: zamówienie złożone
Success --> [*]
Tutaj:
- Profiling — krok zbierania odpowiedzi o obdarowywanym,
- Browsing/Refining — praca z listą kandydatów,
- Checkout — finalizacja,
- Success — końcowe potwierdzenie.
Zwróćcie uwagę: na diagramie nie ma żadnego przycisku ani fetch. To właśnie logiczne kroki, a konkretne ekrany UI, narzędzia i wywołania API nakładacie na nie z wierzchu.
3. Po co w ogóle dzielić zadanie na kroki
Jeśli kiedykolwiek tworzyliście „ankietę z 25 pytaniami na jednym ekranie”, to już wiecie po co. Ale rozłóżmy to na etapy.
Obciążenie poznawcze użytkownika
Człowiek ma ograniczone zasoby uwagi. Psychologowie lubią przywoływać prawo Millera o 7±2 obiektach w pamięci krótkotrwałej. W projektowaniu UX przekłada się to na bardzo praktyczną zasadę: im więcej pól i opcji pokazujecie jednocześnie, tym większa szansa, że użytkownik „zawieśnie”, zmęczy się albo zamknie kartę.
Formularz z 12 polami na jednym ekranie wewnątrz małego widżetu inline ChatGPT to niemal gwarantowany rage‑quit: użytkownik porzuca wszystko i po prostu zamyka kartę. Użytkownik przyszedł „porozmawiać”, a nie zdawać egzamin.
Jeśli zaś dzielicie zadanie na kroki:
- „Krok 1 z 4: opowiedz o osobie”,
- „Krok 2 z 4: wybierz budżet”,
- „Krok 3 z 4: obejrzyj propozycje”,
- „Krok 4 z 4: potwierdź wybór”,
to w danej chwili wszystko wygląda na wykonalne. Pasek postępu lub podpis kroków daje poczucie kontroli: wiadomo, co się dzieje i ile jeszcze zostało.
Obciążenie poznawcze modelu
Niespodzianka: model ma podobny problem. LLM to oczywiście nie człowiek, ale ma również ograniczoną „uwagę” i okno kontekstu. Jeśli prosicie GPT w jednym przebiegu:
- ustalić wszystko o obdarowywanym,
- poradzić sobie z budżetem,
- uwzględnić szczegóły dostawy,
- wybrać 10 opcji,
- wyjaśnić, dlaczego akurat te opcje,
to na każdy z tych podpunktów model zużywa część uwagi i tokenów. Im więcej niespowiązanych zadań w jednym żądaniu, tym większe ryzyko, że część zostanie wykonana pobieżnie lub z błędami.
Jeśli budujecie łańcuch kroków — w istocie to ten sam chain-of-thought, tylko jawnie rozłożony w interfejsie — najpierw model rozwiązuje wąskie zadanie „wyodrębnić profil”, potem „skorygować budżet”, potem „dobrać kandydatów”. Jakość rozumowania modelu (reasoning) na każdym etapie jest zauważalnie wyższa.
Utrzymywalność i debugowanie
Gdy wszystko jest upchnięte w jedno narzędzie i jeden ekran, debugowanie zamienia się w quest: „A w którym dokładnie miejscu zaczęło być źle?”
W wieloetapowym workflow niemal automatycznie zyskujecie:
- punkty logowania: step_started, step_completed, step_failed,
- czytelne miejsca do pomiaru konwersji (ile osób dotarło do kroku 3),
- zlokalizowane problemy: „sypie się tylko na kroku generowania pomysłów”.
To wszystko przyda się w module o analityce workflow, ale już teraz warto przyzwyczajać się do myślenia krokami.
4. Typy kroków w workflow i jak wyglądają w UI
Omówiliśmy już, po co dzielić zadanie na kroki. Teraz uporządkujmy same kroki i zobaczmy, jakie typowe „klocki” najczęściej spotyka się w ChatGPT App. Aby nie zjechać w chaotyczny zbiór ekranów, dobrze mieć „bibliotekę” typów kroków. W waszej aplikacji prawie zawsze będą się powtarzać pewne wzorce.
Oto podstawowa tabela:
| Typ kroku | Cel | Jak zwykle wygląda w ChatGPT App | Przykład w GiftGenius |
|---|---|---|---|
| Zbieranie danych (kreator) | Wypełnić złożony obiekt częściami | Niewielki formularz, „chipsy”, wybór opcji, wskaźnik postępu | „Dla kogo prezent?”, „Wiek?”, „Zainteresowania?” |
| Rozgałęzienie | Zdecydować, którą ścieżką iść dalej | Pytanie w czacie + proste opcje w UI | „Prezent dla dziecka → kategorie dziecięce” |
| Przegląd/potwierdzenie | Pozwolić użytkownikowi zweryfikować wyniki | Karta podsumowania + przyciski „Wstecz” / „Potwierdź” | „Oto co zrozumiałem — czy wszystko się zgadza?” |
| Krok końcowy | Zakończyć scenariusz i zaproponować kolejne działania | Ekran końcowy z wynikiem + follow‑upy w czacie | „Oto twoje prezenty, chcesz złożyć zamówienie?” |
Warto pamiętać: ten sam krok logiczny może ujawniać się zarówno w UI, jak i w czystej rozmowie tekstowej. Na przykład krok „zbieranie zainteresowań” może być:
- albo formularzem z tagami „sport”, „gry planszowe”, „kulinaria”,
- albo rozmową, w której GPT grzecznie dopytuje: „A czym się interesuje?”.
Często optymalna jest hybryda: GPT zadaje pytanie, użytkownik odpowiada tekstowo, a jednocześnie może klikać w chipsy wewnątrz widżetu.
5. Kto „prowadzi” workflow: GPT, widżet czy serwer?
Intuicyjnie chciałoby się powiedzieć: „Oczywiście widżet, przecież jesteśmy frontendowcami, wszystko kontrolujemy przez state”. Ale w świecie ChatGPT App to tak nie działa. Workflow to wspólna praca wszystkich trzech uczestników.
GPT jako orkiestrator
GPT:
- prowadzi dialog, zadaje pytania,
- decyduje, kiedy krok można uznać za zakończony,
- wybiera, kiedy wywołać narzędzie (np. „pora wygenerować prezenty”).
Dla niego wasz workflow wygląda jak zestaw podzadań. W system‑prompcie możecie opisać, jakie podzadania są i w jakiej kolejności zwykle je wykonywać, ale zostawiacie modelowi swobodę lekkiej adaptacji sekwencji.
Przykład mini‑instrukcji w system‑prompcie dla GiftGenius (pseudokod, bez dokładnej składni):
1. Najpierw doprecyzuj profil obdarowywanego (wiek, relacja, zainteresowania).
2. Następnie doprecyzuj budżet.
3. Gdy danych jest dość — wywołaj narzędzie suggest_gifts.
4. Po otrzymaniu kandydatów — pomóż użytkownikowi wybrać.
Najważniejsze: GPT nie zna (i nie powinien znać) szczegółów waszych komponentów React. Operuje krokami w kategoriach celu: „zebrać profil”, „dobrać pomysły”.
Widżet jako „twarz” kroku
Widżet:
- wyświetla dokładnie ten krok, który jest teraz istotny,
- przechowuje stan UI (wyróżniona karta, otwarta zakładka, lokalne pola formularza),
- może pokazywać wskaźnik postępu po krokach.
Najprostsze przedstawienie UI‑workflow w kodzie:
type GiftWorkflowStep =
| "profiling"
| "budget"
| "candidates"
| "checkout";
type GiftWidgetState = {
step: GiftWorkflowStep;
selectedGiftId?: string;
};
Wewnątrz widżetu React możecie przechowywać ten stan albo w zwykłym useState, albo — jeśli chcecie powiązać go z cyklem życia widżetu w ChatGPT — użyć useWidgetState z Apps SDK.
const [widgetState, setWidgetState] = useState<GiftWidgetState>({
step: "profiling",
});
Funkcje‑handlery w widżecie nie będą bezpośrednio „kupować prezentu”, lecz zmieniać krok i przekazywać potrzebne dane z powrotem do modelu/backendu.
MCP‑tools jako „ręce” workflow
MCP‑serwer:
- przechowuje stan biznesowy (profil, historię wyborów),
- waliduje kroki („nie można przejść do Checkout, jeśli nie wybrano prezentu”),
- wykonuje ciężką pracę: wyszukiwanie w katalogu, obliczenia cen, integrację z ACP.
Na przykład logiczniej, by decyzja „jakie prezenty pokazać” zapadała nie w widżecie, lecz w narzędziu MCP suggest_gifts, tak aby model mógł wywoływać je wielokrotnie podczas doprecyzowań.
Wychodzi więc taki podział:
- GPT — tekst i kolejność,
- widżet — wizualne przedstawienie bieżącego kroku,
- MCP — dane i inwarianty.
6. Jak opisać workflow w kodzie: mini state‑machine
Pamiętacie diagram stanów dla GiftGenius z początku lekcji? Teraz zapiszemy tę samą logikę w postaci prostych typów i funkcji — mini state‑machine w kodzie. Nie będziemy zamieniać waszej aplikacji w teoretyczny kurs o automatów skończonych, ale para prostych typów i funkcji bardzo ułatwia życie.
Typy kroków i konfiguracja
Zacznijmy od deklaratywnego opisu kroków. Weźmy znany nam typ GiftWorkflowStep (powtórzymy go tu dla czytelności) i opiszmy dla niego konfigurację:
type GiftWorkflowStep =
| "profiling"
| "budget"
| "candidates"
| "checkout";
type StepConfig = {
label: string;
isFinal?: boolean;
};
export const GIFT_WORKFLOW_STEPS: Record<GiftWorkflowStep, StepConfig> = {
profiling: { label: "Odbiorca" },
budget: { label: "Budżet" },
candidates: { label: "Warianty" },
checkout: { label: "Finalizacja", isFinal: true },
};
Teraz można dodać prostą funkcję przejścia:
export function getNextStep(
current: GiftWorkflowStep
): GiftWorkflowStep | null {
switch (current) {
case "profiling":
return "budget";
case "budget":
return "candidates";
case "candidates":
return "checkout";
default:
return null; // finał
}
}
To już daje wam:
- scentralizowaną listę kroków,
- jawne reguły przejść,
- możliwość szybkiej zmiany kolejności i logiki.
Użycie w widżecie
Najprostsza wersja „kreatora” w waszym widżecie może wyglądać tak:
function GiftWizard() {
const [step, setStep] = useState<GiftWorkflowStep>("profiling");
const handleStepComplete = () => {
const next = getNextStep(step);
if (next) setStep(next);
};
return (
<div>
<ProgressBar step={step} />
<StepContent step={step} onComplete={handleStepComplete} />
</div>
);
}
Komponent StepContent potrafi renderować różne podformularze w zależności od kroku:
function StepContent(props: {
step: GiftWorkflowStep;
onComplete: () => void;
}) {
const { step, onComplete } = props;
if (step === "profiling") {
return <ProfilingStep onNext={onComplete} />;
}
if (step === "budget") {
return <BudgetStep onNext={onComplete} />;
}
if (step === "candidates") {
return <CandidatesStep onNext={onComplete} />;
}
return <CheckoutStep />;
}
Uwaga: tu na razie nie dotykamy tego, jak GPT wybiera krok — to lokalna logika UI. Później możecie zsynchronizować ten step ze stanem serwera lub wiadomościami z narzędzi, ale do zrozumienia wieloetapowości to wystarczy.
7. Rozwijamy aplikację ćwiczeniową: od „mega‑formularza” do kreatora
Załóżmy, że do tej lekcji wasz widżet GiftGenius wyglądał jak „duży formularz”:
- imię obdarowywanego,
- wiek,
- zainteresowania,
- budżet,
- typ wydarzenia,
- checkboxy „potrzebna dostawa” i jeszcze pięć pól,
- a na dole jeden duży przycisk „Dobierz prezent”.
Do prototypu to często OK, ale gdy tylko chcecie scenariusz produktowy — czas pociąć na kroki.
Jak wyglądało „przedtem”
Karykaturalny przykład:
// Antywzorzec: jeden ogromny formularz
function GiftFormAllInOne() {
return (
<form>
{/* 10+ pól przemieszanych */}
{/* ... */}
<button type="submit">Dobierz prezent</button>
</form>
);
}
Typowe problemy:
- użytkownik nie rozumie, które pola są obowiązkowe,
- nie wiadomo, ile to zajmie czasu,
- GPT trudniej wytłumaczyć użytkownikowi, co się stało, i zrobić follow‑up.
Jak zrobić „potem”: kreator z trzech ekranów
Krok 1 — oddzielić profil od budżetu:
function ProfilingStep(props: { onNext: () => void }) {
const [recipientType, setRecipientType] = useState("");
const [interests, setInterests] = useState<string[]>([]);
const handleSubmit = () => {
// tutaj można wywołać narzędzie zapisu profilu
props.onNext();
};
return (
<div>
<h3>Dla kogo szukamy prezentu?</h3>
{/* pary przycisków radiowych / chipsów dla typu i zainteresowań */}
<button onClick={handleSubmit}>Dalej</button>
</div>
);
}
Krok 2 — budżet:
function BudgetStep(props: { onNext: () => void }) {
const [budget, setBudget] = useState<number | null>(null);
const handleSubmit = () => {
// można wywołać narzędzie walidacji budżetu
props.onNext();
};
return (
<div>
<h3>Jaki masz budżet?</h3>
{/* suwak albo input */}
<button onClick={handleSubmit} disabled={!budget}>
Dobierz warianty
</button>
</div>
);
}
Krok 3 — lista kandydatów:
function CandidatesStep(props: { onNext: () => void }) {
const [selectedId, setSelectedId] = useState<string | null>(null);
// tutaj pokazujecie już karty prezentów
// i pozwalacie wybrać jeden
return (
<div>
<h3>Wybierz odpowiednią opcję</h3>
{/* karty z onClick = setSelectedId */}
<button onClick={props.onNext} disabled={!selectedId}>
Przejdź do finalizacji
</button>
</div>
);
}
Tak, kodu jest trochę więcej, ale logika stała się prostsza:
- każdy krok rozwiązuje małe zadanie,
- model może osobno komentować przejścia między krokami,
- możecie logować/mierzyć każdy krok z osobna.
8. Antywzorce: jak nie zamienić workflow w potwora
Praktyka i obserwacje podobnych aplikacji pokazują kilka typowych błędów, których bardzo warto uniknąć.
Po pierwsze, nie próbujcie „wszystkiego rozrysować” złożonym diagramem BPMN, gdzie jest 30 stanów, 40 strzałek i płachta A0. W kontekście ChatGPT App ważniejsza jest intuicyjnie zrozumiała drabinka kroków niż formalna notacja. Wystarczą diagramy w rodzaju tego, który rysowaliśmy dla GiftGenius.
Po drugie, nie zamieniajcie aplikacji w jeden ogromny formularz, szczególnie wewnątrz widżetu inline. Użytkownik i tak jest w czacie; dodanie gęstego bloku UI powinno zmniejszać, a nie zwiększać obciążenie. Jeśli łapiecie się na myśli „tu jest 12 pól, ale wszystkie są ważne” — to niemal zawsze znak, że zadanie trzeba pociąć.
Po trzecie, nie róbcie kroków „na piękno”. Każdy krok musi mieć jasny cel: albo zebrać dane, albo zawęzić wybór, albo dać człowiekowi coś do potwierdzenia. Pusty ekran w stylu „jeszcze chwilka i koniec” z jednym przyciskiem „dalej” rzadko pomaga.
Na koniec, nie próbujcie ujawnić wszystkich możliwości aplikacji w pierwszych krokach. Szczegółowe rzeczy w rodzaju „zaawansowane filtry”, „specjalne warunki dostawy” można dodawać jako dodatkowe kroki tylko tym, którym są naprawdę potrzebne.
9. Proste ćwiczenie projektowe dotyczące workflow
Aby lepiej utrwalić materiał, spróbujcie na papierze (albo w IDE, ale bez kodu) zrobić następujące rzeczy.
Weźcie jedno zadanie. To może być:
- dobór prezentu (GiftGenius),
- rezerwacja podróży,
- zbudowanie planu nauki czegoś.
Podzielcie je na 3–5 kroków. Dla każdego kroku opiszcie:
- cel: co powinno być wiadomo/zrobione po tym kroku,
- format: co jest tu stosowniejsze — czysty tekst od GPT, widżet czy kombinacja.
Na przykład dla prostego „planu nauki TypeScriptu”:
- Krok „Ocena poziomu” — dialog (GPT zadaje kilka pytań) + krótki formularz samooceny.
- Krok „Cele” — dyskusja tekstowa + checkboxy celów w widżecie.
- Krok „Plan” — generowanie planu (lista) + przyciski „utrudnij/ułatw”.
- Krok „Potwierdzenie” — krótkie podsumowanie i przycisk „zapisz plan”.
Spróbujcie potem oszacować, jakie narzędzia mogłyby być użyte na każdym kroku, ale nie wchodźcie w szczegóły: narzędzia, ich włączanie/wyłączanie i przechowywanie stanu — to tematy kolejnych wykładów tego modułu.
10. Typowe błędy przy pracy z wieloetapowymi workflow
Błąd nr 1: próba rozwiązania wszystkiego jednym krokiem i jednym narzędziem.
Bardzo kusi stworzyć „duże sprytne narzędzie”, które i pyta, i analizuje, i samo dobiera, i samo finalizuje zakup. W praktyce pogarsza to i UX (jeden ciężki ekran), i jakość rozumowania modelu (reasoning) — zbyt wiele obowiązków w jednym wywołaniu. Prościej, niezawodniej i taniej w utrzymaniu jest rozbić zadanie na łańcuch 3–5 prostych kroków.
Błąd nr 2: niejawnye kroki ukryte w głowie developera.
Czasem w kodzie niby jest sekwencja działań, ale nigdzie nie jest jawnie opisana: brak typów kroków, konfiguracji, diagramu. W efekcie nikt w zespole nie potrafi sensownie odpowiedzieć, „co dzieje się w tej aplikacji od początku do końca”. Minimalny deklaratywny opis kroków i przejść oszczędza godziny debugowania.
Błąd nr 3: mieszanie kroków UI i logiki biznesowej.
Jeśli logika przejść między krokami jest zaszyta głęboko w komponentach React (w stylu if (isValid && hasBudget && !needsShipping) na onClick przycisku), staje się ona trudna do ponownego użycia i testowania. Lepiej mieć w miarę jawną „maszynę stanów” albo chociaż funkcję getNextStep, a UI jedynie ją wywołuje i wyświetla rezultat.
Błąd nr 4: ignorowanie roli GPT jako orkiestratora.
Zdarza się, że developer próbuje w pełni kontrolować scenariusz z widżetu: „sam zapytam o wszystko, model niech tylko dobiera”. W rezultacie ChatGPT przestaje wyglądać jak żywy asystent i zamienia się w silnik obliczeniowy pod formularzem. O wiele przyjemniej, gdy GPT aktywnie rozmawia, popycha do kolejnego kroku i sam inicjuje wywołania narzędzi — a wy pomagacie mu projektem kroków i instrukcjami.
Błąd nr 5: kroki bez jasnego celu.
Czasem w kreatorze pojawiają się „zbędne” kroki — szczerze mówiąc, po prostu dlatego, że tak ładniej. Użytkownik widzi „Krok 2 z 5”, ale na tym kroku w gruncie rzeczy nic od niego nie jest wymagane i nic się nie dzieje. Takie puste ekrany tylko zwiększają poczucie złożoności. Jeśli kroku nie da się sformułować jako „po nim na pewno wiemy X” lub „po nim użytkownik zrobił Y” — najpewniej nie jest potrzebny.
Błąd nr 6: zapomniany postęp i brak poczucia drogi.
Wieloetapowość bez wsparcia wizualnego zamienia się w czarną skrzynkę: użytkownik nie rozumie, gdzie jest i ile zostało. Nawet prosty tekstowy wskaźnik „Krok 2 z 4” czy poziome wyliczenie kroków w nagłówku widżetu wyraźnie zmniejsza niepokój. Ignorowanie tego efektu to jeden z powodów, dla których ludzie „odpadają” w połowie scenariusza, choć realnej trudności może tam wcale nie być.
GO TO FULL VERSION