1000 zadań QA. Naiwne podejście: każde przez LLM. Koszt: drobny kredyt hipoteczny.
Moje podejście: większość ticketów nigdy nie widzi LLM. Koszt: grosze.
Ta sama dokładność. Ten sam audit trail. Lepszy sen.
A za cztery tygodnie rachunek przestaje się chować.
Zły domyślny ruch
Każdy post o AI w QA który przewija mi się na feedzie mówi tę samą rzecz w różnych wariantach. Niech AI napisze ci testy. Niech AI wygeneruje scenariusze. Niech AI sprawdzi czy aplikacja wygląda OK.
Na demo wygląda pięknie. Na produkcji się sypie.
Wzorzec: agent czyta surowe HTML z Jiry, parsuje, zgaduje selektory, halucynuje intencję użytkownika, pisze test, uruchamia. Połowa razów test przechodzi z niewłaściwego powodu. Druga połowa wywala się bo Playwright timeoutuje na popupie którego LLM nie widział.
Budowałem to trzy miesiące temu. Działało na demo. Sypało się na realnych ticketach.
Potem odwróciłem architekturę. Mapa była do góry nogami.
Kontekst przed LLM
AI to drugi krok, nie pierwszy.
Pierwszy krok to deterministyczny pipeline inżynierski który podaje AI czysty, ustrukturyzowany, zwalidowany kontekst. LLM nigdy nie widzi surowej Jiry. Nigdy nie parsuje HTML. Nigdy nie zgaduje selektorów CSS. Kiedy model dostaje pierwszy token, każdy input został już pobrany, znormalizowany, otypowany i zwalidowany.
Pomyśl o tym tak: AI jako senior dev robiący code review na dobrze przygotowanym PR vs. AI jako stażysta z poleceniem “ogarnij tę Jirę”. Ten sam model. Przeciwne wyniki.
Zasada: deterministyczny harness wokół LLM, nie odwrotnie. Kod który daje ten sam output dla tego samego inputu. Zawsze. Bez prawdopodobieństwa. Bez czujki. LLM jest mały, ograniczony, weryfikowalny - jeden komponent w systemie, nie sam system.
To jest kanapka.
Kanapka i matematyka
Trzy warstwy:
- Deterministyczny input - równoległe pobieranie z Jiry, Figmy, Playwrighta. Parsing, wzbogacanie, typowanie. Czysty kod.
- Decyzja AI - mały, ograniczony zakres. Model widzi ustrukturyzowany JSON, zwraca jedno z N zwalidowanych werdyktów.
- Deterministyczny output - typowany obiekt idzie do publishera który pisze do Jiry, dołącza obrazki, robi audit record.
LLM widzi może 5% scope’u pipeline’u. Pozostałe 95% to kod z testami.
Oto co to znaczy przy skali. Weź realny e-commerce workload QA: 1000 ticketów miesięcznie.
Scenariusz: 1000 zadań QA e-commerce miesięcznie
Naiwnie "LLM wszędzie":
- Średnio 8K tokenów input + 2K output na zadanie
- $0.03/1K input + $0.15/1K output (Claude Sonnet)
- Na zadanie: $0.24 + $0.30 = $0.54
- Miesięcznie: $540 + retry + failures ~ $700-900
Deterministic-first (mój):
- ~70% zadań: zero LLM (static checks, pattern matching, CSS diff)
- ~30% zadań: LLM tylko na przygotowanym JSON context
- Średnio 2K input + 500 output na wywołanie LLM
- Na zadanie (te z LLM): $0.06 + $0.075 = $0.135
- Miesięcznie: $0.135 x 300 = $40
Ta sama dokładność. ~18x taniej. Audit trail nienaruszony.
Weź tabelę. Przelicz dla swojego scenariusza. Matematyka nie kłamie.
Podział 70/30 to representative baseline, nie hardcoded SLA. W realnych produkcyjnych runach rusza się z workloadem - czasem 60%, czasem 80% wychodzi bez LLM. Kosmetyczne regresje skrzywiają w stronę więcej deterministycznych wyjść; niejednoznaczne osądy UX skrzywiają w stronę więcej wywołań LLM. Tak czy inaczej: deterministyczna podłoga łapie pierwsza, LLM widzi tylko co zostaje.
Dwie uwagi jeśli jesteś na subskrypcji Claude Max
Teraz, maj 2026, wywołania Agent SDK i claude -p dzielą okno twojej subskrypcji Claude Code. Więc naiwne “LLM wszędzie” nie pojawia się jako linijka na fakturze - pojawia się jako 5-godzinne okno parujące przed obiadem. Matematyka dolarowa się ukrywa, ale produktywne godziny dnia nie.
To się zmienia 15 czerwca 2026.
Anthropic wydziela programmatic usage do osobnego miesięcznego kredytu, billowanego po pełnych stawkach API. Claude Agent SDK, claude -p, Claude Code GitHub Actions i third-party narzędzia zbudowane na Agent SDK - wszystko przechodzi na osobny budget po standardowej cenie API. Twój interaktywny Claude Code zostaje na subskrypcji. Twoje agentic pipelines przechodzą na pay-per-token.
Czyli tabela kosztów powyżej przestaje być teoretyczna dla każdego kto uruchamia QA workflows oparte na Agent SDK. Od 15 czerwca naiwne “LLM wszędzie” to wprost linijka na rachunku - a “deterministyczna podłoga najpierw” przestaje być nice-to-have. Staje się forcing function.
Lepiej zaprojektować deterministyczną podłogę teraz, niż odkryć rachunek w lipcu.
Brama decyzyjna
Większość decyzji QA daje się rozstrzygnąć deterministycznymi sprawdzeniami - CSS diff przeciwko baseline, pixel diff z tolerancją, detekcja regresji a11y. Bez interpretacji. Pass albo fail, z powodem.
Oto kształt bramy:
// Deterministyczna brama decyzyjna - większość zadań kończy tutaj
// AI nic nie widzi. Zero tokenów.
function decideQAPath(task: QATask): QAVerdict {
// Warstwa 1: statyczne deterministyczne sprawdzenia
if (task.cssBaseline && cssDiff(task.current, task.baseline) === 0) {
return { verdict: "PASS", reason: "css-identical", llmNeeded: false };
}
if (task.visualBaseline && pixelDiff(task.snap, task.baseline) < 0.001) {
return { verdict: "PASS", reason: "visual-identical", llmNeeded: false };
}
// Warstwa 2: strukturalne sprawdzenia (nadal deterministyczne)
if (hasA11yRegression(task.aria, task.baselineAria)) {
return { verdict: "FAIL", reason: "a11y-regression", llmNeeded: false };
}
// Dopiero tu wchodzi LLM - ustrukturyzowany JSON context już gotowy
return { verdict: "AMBIGUOUS", reason: "needs-judgment", llmNeeded: true };
}
Trzy deterministyczne sprawdzenia. Trzy wczesne wyjścia. Koszt tokenów: zero. Jeśli wszystkie trzy przepuszczą do AMBIGUOUS, LLM zostaje wywołany - ale tylko na zadaniach które naprawdę wymagają osądu.
Większość ticketów wychodzi zanim jakikolwiek model się obudzi. Pozostała mniejszość trafia do LLM z otypowanym obiektem QATask który ktoś albo coś już zwalidował. Tokeny idą na osąd, nie na parsowanie.
Dlaczego to ma znaczenie przy skali
Główna liczba z mojej produkcji: 94 ticketów QA przetworzonych w 2.5 dnia na jednym projekcie. Klasyczne manualne podejście dla tego samego scope: tydzień pracy zespołu, lekko dwa. Z tym stackiem: jeden inżynier, pół tygodnia, pełen audit trail.
Pozostałe rzeczy które się trzymają przy skali:
- Deterministyczne wyjścia trzymają krzywą kosztów płaską. Nie płacisz tokenów za jasne diffy.
- Audit trail nienaruszony - każdy werdykt ma reason code, każde wywołanie LLM ma swój input bundle przyklejony. Możesz odtworzyć każdą decyzję jutro.
- Failure modes są bounded. Flaky test nadal się wywali - ale wywala się tak samo za każdym razem, z tymi samymi logami, i fixujesz go raz.
Głębszy powód to nie koszt. To blast radius. Kiedy AI siedzi w warstwie I/O, każdy flaky Playwright łączy się z każdą halucynacją LLM. Failures się stackują. Nie da się ich debugować, reprodukować, zaufać im.
Kiedy AI siedzi tylko w warstwie osądu, z deterministyczną podłogą pod spodem i deterministycznym publisherem nad nią, failures są bounded. Linijka do której ciągle wracam: jeśli twój agent AI robi więcej niż osądza, masz problem z deterministyczną podłogą.
Co dalej
To dopiero kręgosłup. Realny produkcyjny system ma dziesięć konkretnych warstw architektonicznych, każda z własnym wzorcem, własnymi gotchas, własnym powodem żeby być deterministyczna zanim LLM wejdzie.
Jutro publikuję pełną mapę. Dziesięć warstw, A do J. Co siedzi w każdej. Które cztery wypuszczam jako code drops przez najbliższe 8 tygodni. Które sześć zostaje w pitch-mode na razie i dlaczego.
Jeśli kiedykolwiek zastanawiałeś się dlaczego twoje demo “AI QA” działało a produkcja się sypała - jutrzejszy odcinek nazywa każdą lukę którą musiałem załatać.
To nie magia. To kanapka.