← Back to Blog

Gdy AI zaczyna pisać oprogramowanie, które nie jest już proste

Gdy AI zaczyna pisać oprogramowanie, które nie jest już proste

Dziś tworzenie oprogramowania z pomocą AI często przebiega według prostego procesu:

  1. Napisz opis zadania (prompt).

  2. Pozwól AI przygotować analizę i proponowane rozwiązanie.

  3. Przygotuj skille, agentów i subagentów.

  4. Rozpocznij implementację.

  5. Pozwól AI napisać kod, przetestować go i naprawić wykryte problemy.

Na pierwszy rzut oka wygląda to na idealny workflow programistyczny. AI działa autonomicznie, rozdziela zadania między agentów, pisze testy i stopniowo kończy żądaną funkcjonalność.

A przy mniejszych projektach to podejście potrafi działać wyjątkowo dobrze.

Jeśli budujesz prosty sklep internetowy, pięciostronicową stronę firmową albo podstawowy system administracyjny, AI często poradzi sobie ze znaczną częścią pracy, osiągając bardzo dobre wyniki.

Dlaczego?

Ponieważ miliony programistów zbudowały już podobne oprogramowanie.

Wyobraź sobie dwa sklepy internetowe. Jeden sprzedaje zabawki, drugi jabłka.

Z perspektywy klienta to dwa różne biznesy. Z perspektywy architektury oprogramowania działają jednak bardzo podobnie:

  • Produkty uporządkowane w kategorie.

  • Zarządzanie cenami i stanami magazynowymi.

  • Koszyki zakupowe.

  • Obsługa zamówień.

  • Metody płatności.

  • Zarządzanie klientami.

Zmieniają się głównie dane, konkretne reguły biznesowe i niektóre funkcje. Podstawowe zasady architektury pozostają w dużej mierze takie same.

AI rozpoznaje te wzorce, ponieważ w trakcie treningu spotkała podobne struktury.

Problem zaczyna się, gdy przestajesz budować typową aplikację i zaczynasz rozwijać duże oprogramowanie klasy enterprise.

Co się dzieje, gdy system ma od 300 000 do 500 000 linii kodu?

Wyobraź sobie aplikację enterprise zawierającą setki tysięcy linii kodu, dziesiątki modułów, setki zależności i złożone reguły biznesowe.

Taki system mógł powstawać przez kilka lat. W tym czasie gromadziły się decyzje architektoniczne, wyjątki, historyczne zależności i reguły biznesowe.

Nie wszystkie są udokumentowane.

Jedna metoda może wpływać na dziesięć innych modułów. Zmiana jednego parametru może zakłócić fakturowanie, uprawnienia użytkowników lub obsługę zamówień.

Teraz wyobraź sobie, że wprowadzasz do tego środowiska agenta AI.

Dajesz mu zadanie:

„Zmodyfikuj proces płatności tak, aby obsługiwał dodatkową metodę płatności. Zachowaj kompatybilność wsteczną i przetestuj wszystko."

Agent tworzy plan, rozdziela pracę między subagentów, implementuje zmiany, uruchamia testy i zwraca wyniki.

Wszystko może wyglądać poprawnie.

Ale zaliczone testy nie oznaczają jeszcze, że oprogramowanie zachowało wszystkie istniejące reguły biznesowe.

I to prowadzi nas do problemu, który sześć miesięcy temu całkowicie zmienił moje podejście do agentów AI.

Eksperyment, który zmienił mój pogląd na systemy agentowe

Sześć miesięcy temu przeprowadziłem eksperyment, który sprawił, że zamiast po prostu budować więcej agentów i subagentów, poszedłem inną drogą.

Do tamtej pory działałem w oparciu o założenie, które podziela wielu programistów:

Im lepiej rozdzielę zadania między wyspecjalizowanych agentów i im więcej mechanizmów walidacji wprowadzę, tym bardziej niezawodny będzie wynik.

Jednak podczas moich eksperymentów natrafiłem na fundamentalne pytanie:

Jak agent może poprawnie zaimplementować regułę biznesową, skoro nawet nie wie, że ta reguła istnieje?

A jak inny agent ma wiarygodnie zweryfikować wynik, skoro również nie ma pełnych informacji o tym, jak system powinien się zachowywać?

Zacząłem badać, jak kontekst jest przekazywany między agentami.

Odkryłem, że sposób, w jaki informacje są przekazywane i interpretowane, może być jednym z najsłabszych punktów całego procesu.

Jak naprawdę działają agenci i subagenci?

W praktyce istnieją dwa popularne podejścia do komunikacji między agentami AI.

1. Model hierarchiczny – główny agent koordynuje subagentów

Ta architektura jest powszechnie nazywana Hub-and-Spoke lub topologią gwiazdy.

Zasada jest prosta:

  1. Użytkownik przekazuje zadanie głównemu agentowi.

  2. Główny agent analizuje zadanie i dzieli je na mniejsze części.

  3. Tworzy lub aktywuje subagenta A i przekazuje mu instrukcje.

  4. Subagent A wykonuje pracę i zwraca wynik.

  5. Główny agent ocenia wynik i może zlecić dalszą pracę subagentowi B.

  6. Gdy wszystkie części są ukończone, główny agent łączy wyniki.

Subagent A niekoniecznie wie, co robi subagent B. Komunikacja i wymiana informacji są koordynowane przez głównego agenta.

Zaleta: Scentralizowana kontrola, łatwiejsze śledzenie stanu, wyraźniejsza odpowiedzialność i mniejsze ryzyko niekontrolowanej komunikacji między agentami.

Wada: Główny agent staje się centralnym punktem, przez który interpretowane są instrukcje zadań i wyniki. Jeśli pominie ważne informacje podczas delegowania pracy, subagent może działać z niepełnym kontekstem.

2. Peer-to-Peer – agenci komunikują się ze sobą

Drugie podejście polega na bezpośredniej lub ciągłej komunikacji między agentami, na przykład przez wspólny wątek rozmowy lub system komunikatów (*Message Bus*).

Wyobraź sobie taki scenariusz:

  • Agent A pisze kod i publikuje zdarzenie CodeWritten.

  • Agent B, odpowiedzialny za testowanie, odbiera zdarzenie i uruchamia testy.

  • Agent C jednocześnie przygotowuje dokumentację.

  • Agenci nieustannie wymieniają się wynikami i reagują na zmiany.

Zaleta: Równoległe wykonywanie zadań, szybka wymiana informacji i mniejsza zależność od jednego centralnego agenta.

Wada: Bardziej złożona koordynacja, ryzyko pracy na nieaktualnych informacjach, sprzeczne modyfikacje oraz większa trudność w wyśledzeniu źródła błędów.

Oba podejścia mogą być niezwykle przydatne.

Ale żadne z nich samo nie rozwiązuje fundamentalnego problemu.

Agent może mieć doskonale zdefiniowane zadanie, ale bez zrozumienia rzeczywistej logiki biznesowej systemu może stworzyć rozwiązanie poprawne technicznie, a błędne z perspektywy biznesu.

Gdzie w agentowych workflow powstają błędy?

AI nie jest deterministycznym kompilatorem, który przekłada instrukcje wprost na kod źródłowy. Model językowy interpretuje dostępne informacje i generuje rozwiązania na podstawie tego kontekstu.

Gdy brakuje informacji, może przyjąć błędne założenia. Gdy dostępne informacje są niekompletne lub sprzeczne, może wybrać nieodpowiednie podejście.

Przyjrzyjmy się typowemu workflow dla większego zadania.

Krok 1 - Interpretacja promptu użytkownika

Główny agent otrzymuje zadanie i próbuje zrozumieć żądaną zmianę.

Na tym etapie może przeoczyć zależność, źle zrozumieć ograniczenie albo założyć coś, co nigdy nie zostało wprost powiedziane.

Krok 2 - Tworzenie instrukcji dla subagenta

Główny agent tworzy bardziej szczegółowy opis zadania. Wybiera z oryginalnego promptu informacje, które uważa za istotne.

Jeśli jednak nie zna pewnych reguł biznesowych, nie może ich poprawnie przekazać dalej.

Krok 3 - Implementacja

Subagent otrzymuje instrukcje, analizuje część bazy kodu i wybiera strategię implementacji.

Może wytworzyć składniowo poprawny, wysokiej jakości kod, jednocześnie nieumyślnie zmieniając zachowanie, które powinno pozostać nietknięte.

Krok 4 - Ocena wyniku

Główny agent otrzymuje wynik pracy subagenta, ocenia go i decyduje, czy zadanie jest ukończone.

Ale nadal może działać w oparciu o te same niekompletne założenia co wcześniej.

Krok 5 - Testowanie i naprawa błędów

Następują testy jednostkowe, testy integracyjne, testy E2E, analiza statyczna i przeglądy dokumentacji.

Te mechanizmy znacząco poprawiają niezawodność oprogramowania, ale mają ograniczenia.

Test weryfikuje konkretne oczekiwane zachowanie. Jeśli ważnej reguły biznesowej brakuje w specyfikacji testu, implementacja może przejść każdy test, naruszając tę regułę.

A gdy AI naprawia jeden problem, może nieumyślnie wpłynąć na inną część systemu.

Powstaje znajomy cykl:

Implementacja → Testowanie → Poprawka → Regresja → Kolejne testowanie → Kolejna poprawka.

Dlatego samo zwiększanie liczby agentów czy częstsze powtarzanie testów nie gwarantuje automatycznie poprawnego wyniku.

Dlaczego błędy mogą się kumulować w łańcuchu agentów?

Rozważmy uproszczony model matematyczny.

Załóżmy, że mamy trzy następujące po sobie kroki, każdy z hipotetycznym 95% prawdopodobieństwem poprawnego wykonania.

Jeśli kroki są niezależne i wszystkie trzy muszą się udać, prawdopodobieństwo wynosi:

0.95 × 0.95 × 0.95 = 0.8574

To około 85,7% prawdopodobieństwa, że wszystkie trzy kroki się powiodą.

Przy dziesięciu takich niezależnych krokach wynik wyniósłby:

0.95¹⁰ ≈ 59,9%

To ilustracyjne obliczenie, a nie zmierzony wskaźnik sukcesu agentów AI. W rzeczywistych systemach błędy nie zawsze są niezależne, mechanizmy walidacji mogą wychwycić pomyłki, a poszczególne kroki mogą naprawiać wcześniejsze niepowodzenia.

Przykład pokazuje jednak ważną zasadę:

Niezawodność pojedynczych agentów nie gwarantuje automatycznie niezawodności całego łańcucha.

Gdy niekompletne instrukcje są wielokrotnie interpretowane na kolejnych etapach, pojawiają się dodatkowe okazje do błędnych decyzji.

Dlatego uważam, że samo dodawanie kolejnych agentów, testów i mechanizmów walidacji nie wystarcza.

Musimy zmienić sposób, w jaki AI otrzymuje informacje o samym systemie.

Kluczowa różnica: testy weryfikują wyniki, logika biznesowa wyznacza granice

Konwencjonalne podejście do tworzenia oprogramowania z AI jest reaktywne.

Przekazujesz wymaganie, AI implementuje rozwiązanie, a testy służą potem do ustalenia, czy coś się nie zepsuło.

To na pewno lepsze niż brak testów.

Ale nadal istnieje fundamentalna słabość:

Testy nie potrafią wiarygodnie walidować reguł biznesowych, o których nikt nie wie i które nie są częścią specyfikacji testowej.

Dlatego uważam, że lepszym podejściem jest przekazanie AI informacji o rzeczywistym zachowaniu systemu, zanim rozpocznie się implementacja.

Nie tylko co trzeba zmienić, ale także:

  • Jakie reguły biznesowe dotyczą zmienianego kodu.

  • Które inne moduły zależą od tej funkcjonalności.

  • Które wejścia i wyjścia muszą pozostać kompatybilne.

  • Które scenariusze muszą pozostać niezmienione.

  • Jakie istnieją wyjątki i historyczne ograniczenia.

  • Które części implementacji AI może modyfikować, a które musi zachować.

To znacząco zmniejsza ilość zachowań, które AI musi wywnioskować samodzielnie.

Dwa podejścia do tego samego zadania

Podejście A - Prompt + testowanie

AI otrzymuje zadanie, wybiera implementację na podstawie dostępnego kontekstu, tworzy rozwiązanie i uruchamia testy.

Jeśli testy są niekompletne, naruszenia istniejących reguł biznesowych mogą pozostać niewykryte.

Podejście B - Prompt + logika biznesowa + testowanie

AI otrzymuje zadanie wraz z odpowiednimi regułami, zależnościami, kontraktami i ograniczeniami.

Dzięki temu wie, jakie zachowanie musi zostać zachowane, zanim rozpocznie się implementacja.

Testy robią wtedy więcej niż wykrywanie błędów. Weryfikują także konkretne kontrakty biznesowe.

Różnica nie polega na tym, że przestajemy testować.

Różnica polega na tym, że staramy się zapobiegać błędom, zanim zostaną wprowadzone.

When AI starts writing software that is no longer simple — screenshot 1

Praktyczny przykład: dodanie nowej metody płatności

Wyobraź sobie, że mamy plik CheckoutService.ts, który obsługuje płatności w aplikacji e-commerce.

Chcemy dodać płatności kartą jako dodatkową metodę płatności.

Opcja A: Konwencjonalny prompt

Zadanie:

> Dodaj płatności kartą do CheckoutService.ts. Zachowaj istniejącą funkcjonalność i uruchom wszystkie testy.

AI modyfikuje kod, dodaje nową gałąź płatności i aktualizuje testy.

Wszystkie testy przechodzą.

Zadanie zostaje oznaczone jako ukończone.

System zawiera jednak ważną regułę biznesową:

Konta firmowe muszą używać przelewu bankowego jako domyślnej metody płatności.

Reguła została wprowadzona kilka lat temu. Programista, który ją zaimplementował, już nie pracuje w firmie. Reguła nie jest wyraźnie udokumentowana i nie istnieje dedykowany test regresyjny.

AI wprowadza płatność kartą jako metodę domyślną dla wszystkich klientów.

Z perspektywy implementacji nowa funkcjonalność działa poprawnie.

Z perspektywy logiki biznesowej system jest zepsuty.

A testy nie wykryły problemu.

Opcja B: Ustrukturyzowane zadanie z logiką biznesową w AITM

Teraz wyobraź sobie, że AI otrzymuje to samo żądanie, ale tym razem zadanie zawiera odpowiedni kontrakt biznesowy, powiązane zmienne, odnośniki do historycznych zadań i precyzyjne granice dozwolonych zmian.

Zadanie mogłoby wyglądać tak:

READ CLAUDE.md first.

TASK:

Add card payment as an additional payment method

in CheckoutService.ts.

Contract:

%CHECKOUT-019 — "For company accounts
(companyId != null), bank transfer must remain
the default payment method. Card payment may
be offered only as an additional option."

Related variables:

BL.CHECKOUT.PAYMENTMETHOD_DEFAULT
BL.CHECKOUT.PAYMENTMETHOD_OPTIONS

Related task:

#<link to the task that originally implemented bank-transfer-as-default checkout>

In scope:

- Add a new "card" option to the available payment methods in CheckoutService.ts.

- Expose it as a selectable option in the existing payment method selection flow.

Out of scope:

- Changing the default payment method for any account type.

- Any UI/checkout-flow redesign beyond adding the new option.

- New payment provider integration logic beyond the method registration itself.

Must not break:

- Existing default payment selection logic (company accounts → bank transfer stays default).

- Company account checkout behavior end-to-end.

- Existing bank transfer processing path.

- Compatibility with the current payment API contract.

File path:

src/Services/CheckoutService.ts
Confirm the exact path via contractsForFile before editing.

Verify:

- Company account checkout still selects bank transfer by default
  (companyId != null).

- Card payment appears as a selectable, non-default option.

- Existing bank transfer processing is unchanged.

- Run unit and integration tests covering CheckoutService.

Więcej informacji o tym, jak to działa w AITM: https://aitm.cz/Docs/KnowledgeSharing

Dlaczego ten format jest ważny?

Na pierwszy rzut oka może wyglądać na zwykły, bardziej szczegółowy prompt.

Prawdziwa różnica polega jednak na tym, że zadanie jest połączone z informacjami, które można pobrać i zweryfikować względem rzeczywistego projektu.

1. Kontrakt %CHECKOUT-019

Identyfikator %CHECKOUT-019 to nie tylko tekstowa notatka.

Jest to ilustracyjny identyfikator kontraktu, który agent może pobrać za pomocą operacji GraphQL, takich jak contractsForFile lub contractsForVariable.

Zamiast polegać wyłącznie na regule zapisanej w prompcie, agent może pobrać jej ustrukturyzowaną reprezentację i zweryfikować ją względem aktualnej bazy kodu.

2. Zmienne logiki biznesowej _BL.

Identyfikatory takie jak _BL.CHECKOUT.PAYMENT_METHOD_DEFAULT i _BL.CHECKOUT.PAYMENT_METHOD_OPTIONS reprezentują logikę biznesową wyrażoną w języku komunikacji AITM.

Pomagają powiązać konkretne wymaganie z regułami i zmiennymi, które determinują zachowanie systemu.

3. Odwołanie do powiązanego zadania

Sekcja Related task odwołuje się do oryginalnego zadania, w którym zaimplementowano regułę biznesową.

Daje to AI dodatkowy kontekst, nie tylko o tym, jak system zachowuje się obecnie, ale też dlaczego podjęto daną decyzję.

4. Jasno określone granice zmian

Sekcje In scope, Out of scope i Must not break definiują trzy osobne kategorie:

  • Co AI musi zaimplementować.

  • Czego AI nie może implementować.

  • Jakie istniejące zachowanie AI musi zachować.

Zamiast otrzymywać otwarte zadanie, które może dowolnie interpretować lub rozszerzać, AI dostaje precyzyjnie zdefiniowany zakres implementacji.

5. Weryfikacja przed napisaniem kodu

Ścieżka pliku nie jest automatycznie uznawana za poprawną.

Agent ma polecenie najpierw użyć contractsForFile, potwierdzić rzeczywistą ścieżkę i zidentyfikować powiązane kontrakty.

Dopiero potem powinien zacząć modyfikować kod.

6. Walidacja promptu przez TPV

Ważną częścią podejścia AITM jest walidator promptów TPV.

Sprawdza on obowiązkowe sekcje zadania, zanim zostanie ono przekazane do wykonania.

Weryfikuje na przykład obecność definicji zakresu, ograniczeń, kontraktów, ścieżek plików i wymagań weryfikacji.

Przenosi to część zapobiegania błędom z testowania gotowego kodu na przygotowanie samego zadania.

Uwaga: Identyfikatory kontraktów i zmienne logiki biznesowej w tym przykładzie są ilustracyjnymi zastępnikami. W prawdziwym projekcie optymalizator pobiera je przez GraphQL z konkretnego projektu. Nie należy ich zgadywać ani generować bez weryfikacji.

Co zmienia się przy tym podejściu?

W podejściu konwencjonalnym agent najpierw interpretuje otwarte zadanie i sam decyduje, które pliki, zależności i reguły biznesowe są istotne.

W AITM zadanie jest powiązane z konkretnymi kontraktami, zmiennymi logiki biznesowej, historycznymi zadaniami i jasno określonymi granicami zmian.

Agent może więc podejmować decyzje w oparciu o weryfikowalne informacje, a nie polegać głównie na założeniach.

I właśnie tu widzę fundamentalną różnicę.

Logika biznesowa nie jest już tylko częścią dokumentacji. Staje się częścią samego procesu kontroli implementacji.

To zasada, na której opiera się AITM

Kiedy zaczynaliśmy projektować AITM (AI Task Manager), nie chcieliśmy budować kolejnego systemu, który uruchamia agentów, rozdziela zadania i dopiero potem sprawdza ich wyniki.

Skupiliśmy się na innym pytaniu:

Co, jeśli AI mogłoby otrzymywać odpowiednią logikę biznesową bezpośrednio z istniejącego kodu źródłowego, zanim dokona jakichkolwiek zmian?

Nie tylko dokumentację, którą ktoś napisał rok temu.

Nie tylko ogólne instrukcje zapisane w skillu.

I nie tylko kilka plików, które agent akurat wybierze.

Zamiast tego ustrukturyzowane informacje opisujące, jak naprawdę zachowuje się dana część systemu, jakie kontrakty ją regulują i jakie inne komponenty od niej zależą.

Podstawową zasadą AITM jest więc wzbogacanie roboczego promptu o logikę biznesową zidentyfikowaną w odpowiednich częściach bazy kodu.

Agent otrzymuje nie tylko informację o tym, co musi zrobić, ale także o tym, co musi zachować.

Jest to szczególnie ważne w dużych systemach, gdzie pojedynczy prompt może nie zawierać każdej istotnej zależności czy ograniczenia.

Logika biznesowa jako barierki ochronne dla AI

Pomyśl o logice biznesowej jak o barierkach ochronnych wzdłuż drogi.

Bez barierek AI może pójść wieloma różnymi ścieżkami. Niektóre prowadzą do poprawnego rozwiązania, inne naruszają ukryte reguły systemu.

Dostarczając odpowiednie kontrakty i ograniczenia, znacząco zawężamy przestrzeń niepożądanych decyzji.

AI nadal może samodzielnie wybierać strategie implementacji, algorytmy i struktury kodu.

Ale musi przestrzegać znanych reguł biznesowych.

Późniejsze testowanie weryfikuje, czy te reguły rzeczywiście zostały zachowane.

To fundamentalna zmiana filozofii.

Nie próbujemy po prostu naprawiać błędów, które tworzy AI. Staramy się zmniejszyć prawdopodobieństwo, że te błędy w ogóle zostaną wprowadzone.

Czy to znaczy, że nie potrzebujemy już agentów i testów?

Absolutnie nie.

Agenci są przydatni do równoległego wykonywania, wyspecjalizowanych działań i automatyzacji dużych zadań.

Testy jednostkowe, integracyjne i E2E pozostają niezbędnymi elementami zapewniania jakości oprogramowania.

Ale orkiestracja agentów i automatyczne testowanie nie zastąpią znajomości logiki biznesowej.

Jeśli agent nie rozumie, co system musi zachować, nawet doskonale zorganizowany zespół subagentów nie rozwiąże zasadniczego problemu.

A jeśli testy nie obejmują istotnych scenariuszy, każdy test może przejść, a aplikacja nadal będzie zachowywać się błędnie z biznesowego punktu widzenia.

Właściwe podejście to nie wybór między logiką biznesową a testowaniem. To ich połączenie.

Najpierw zidentyfikuj rzeczywiste zachowanie systemu.

Potem wyraź to zachowanie jako jasne reguły i kontrakty.

Następnie przekaż te reguły AI razem z zadaniem.

Dopiero potem przejdź do implementacji, walidacji i testowania.

Takie podejście może zmniejszyć liczbę niepotrzebnych poprawek, regresji i powtarzanych cykli implementacji.

Podsumowanie: nie chodzi o liczbę agentów. Chodzi o jakość informacji.

W prostych aplikacjach AI może dostarczać znakomite wyniki nawet przy stosunkowo krótkich instrukcjach.

Ale przy oprogramowaniu enterprise liczącym pół miliona linii kodu nie wystarczy zakładać, że agent wszystko poprawnie zrozumie, odkryje każdą zależność, a potem bezbłędnie przetestuje własną pracę.

Im większy system, tym ważniejsze jest zrozumienie i ochrona jego rzeczywistego zachowania biznesowego.

Możesz mieć dziesięciu agentów współpracujących idealnie. Ale jeśli żaden z nich nie zna krytycznej reguły biznesowej, razem mogą stworzyć doskonale przetestowane rozwiązanie, które jest zasadniczo błędne.

Dlatego w AITM stosujemy inne podejście.

Najpierw kontekst, reguły i kontrakty.

Potem implementacja.

A na końcu walidacja i testowanie.

Bo celem nie jest to, by AI napisało jak najwięcej kodu w jak najkrótszym czasie.

Celem jest, by AI zmieniło dokładnie to, co trzeba zmienić, nie psując tego, co już działa.

www.aitm.cz