Przejdź do treści
coden

Programowanie z agentami AI: zadanie, testy i kontrola

Jak napisać agentowi zadanie z kryteriami akceptacji, dlaczego pracować małymi krokami, eksperyment z testowaniem mutacyjnym (ile błędów wykrywają testy szczęśliwej ścieżki, przypadki brzegowe i testy właściwości), kto powinien pisać testy i na co uważać.

10 minut Matěj Žalmánek 2026-10-16

Seria Podstawy AI Część 51 z 52
  1. Mapa sztucznej inteligencji: co jest czym i jak to do siebie pasuje
  2. Krótka historia sztucznej inteligencji: od Turinga do modeli językowych
  3. Dane, model, trening, inferencja: podstawowe pojęcia na jednym przykładzie
  4. Jak czytać zapis matematyczny: symbole, indeksy, sumy i kwantyfikatory
  5. Zbiory i relacje: klocki, z których składają się definicje w AI
  6. Funkcje i odwzorowania: dlaczego każdy model AI jest funkcją
  7. Logika i dowody: reguły, według których rozumuje AI
  8. Grafy i drzewa: struktura, na której opierają się przeszukiwanie i sieci neuronowe
  9. Algebra liniowa dla uczenia maszynowego: wektory, macierze i dlaczego AI głównie mnoży
  10. Pochodne, gradient i reguła łańcuchowa: jak model ustala, w którą stronę się uczyć
  11. Spadek gradientu: jak uczy się model
  12. Czym jest prawdopodobieństwo: od rzutu kostką do aksjomatów Kołmogorowa
  13. Prawdopodobieństwo warunkowe i twierdzenie Bayesa: jak zmienić ocenę, gdy dowiesz się czegoś nowego
  14. Zmienna losowa i dystrybuanta: jedna funkcja, która mówi o rozkładzie wszystko
  15. Funkcja gęstości i funkcja prawdopodobieństwa: dlaczego zmienna ciągła ma w punkcie prawdopodobieństwo zero
  16. Wartość oczekiwana, wariancja i kowariancja: gdzie leży rozkład, jak jest szeroki i co z czym się wiąże
  17. Przegląd rozkładów prawdopodobieństwa: Bernoulliego, dwumianowy, Poissona, jednostajny, normalny i wykładniczy
  18. Prawo wielkich liczb i centralne twierdzenie graniczne: dlaczego średnie zachowują się tak przewidywalnie
  19. Statystyka i estymacja parametrów: największa wiarygodność, MAP i przedziały ufności
  20. Teoria informacji: entropia, entropia krzyżowa i dywergencja KL — skąd się biorą funkcje straty
  21. Przeszukiwanie przestrzeni stanów: BFS, DFS, UCS i A* z animacjami
  22. Gry i przeciwnik: minimax, przycinanie alfa-beta i Monte Carlo tree search
  23. Spełnianie ograniczeń: backtracking, propagacja ograniczeń i AC-3 na sudoku i mapie czeskich krajów
  24. Logika i systemy z bazą wiedzy: wnioskowanie w przód i wstecz, rezolucja i systemy ekspertowe
  25. Planowanie: STRIPS, świat klocków, heurystyki z relaksacji i planowanie w agentach AI
  26. Przeszukiwanie lokalne i symulowane wyżarzanie: komiwojażer przez czeskie miasta wojewódzkie
  27. Algorytmy genetyczne: populacja, krzyżowanie, mutacja i selekcja na plecaku na wycieczkę
  28. Strategie ewolucyjne i programowanie genetyczne: od reguły jednej piątej do prawa Keplera
  29. Optymalizacja kolonią mrówek: jak ślad feromonowy znajduje krótką drogę
  30. Optymalizacja rojem cząstek: bezwładność, własne doświadczenie i doświadczenie roju
  31. Neuroewolucja: ewolucja wag i kształtu sieci neuronowych oraz algorytm NEAT
  32. Zbiory rozmyte i funkcje przynależności: jak zapisać „trochę ciepło”
  33. Logika rozmyta a prawdopodobieństwo: dlaczego „trochę ciepło” nie znaczy „prawdopodobnie ciepło”
  34. Logika rozmyta: t-normy, implikacje i reguły JEŻELI–TO
  35. Sterowanie rozmyte: Mamdani i Sugeno od wentylatora po wahadło na wózku
  36. Klasteryzacja rozmyta: algorytm fuzzy c-means i punkty między skupieniami
  37. Systemy neuro-rozmyte (ANFIS): reguły rozmyte, które uczą się z danych
  38. Łańcuchy Markowa: macierz przejścia, rozkład stacjonarny i PageRank
  39. Ukryte modele Markowa: algorytm Viterbiego i nieuczciwe kasyno
  40. Sieci bayesowskie: dlaczego trawa jest mokra i co z tego wynika dla zraszacza
  41. Filtr Kalmana: jak z niedokładnych pomiarów oszacować, gdzie jest samochód i jak szybko jedzie
  42. Rodzaje uczenia maszynowego: nadzorowane, nienadzorowane, półnadzorowane i inne
  43. Prompty, kontekst i RAG: jak dać modelowi właściwe informacje
  44. Wariacyjne autoenkodery (VAE): nowe obrazki z ciągłej przestrzeni latentnej
  45. Generatywne sieci przeciwstawne (GAN): fałszerz kontra detektyw
  46. Modele dyfuzyjne: jak z czystego szumu powstaje obraz
  47. Procesy decyzyjne Markowa: stany, akcje, nagrody i równania Bellmana
  48. Q-learning i DQN: uczenie się wartości akcji od tabeli po sieć neuronową
  49. Policy gradient i PPO: uczenie się bezpośrednio polityki
  50. Jak działa agent AI: model językowy w pętli z narzędziami
  51. Programowanie z agentami AI: zadanie, testy i kontrola
  52. Ocena i bezpieczeństwo systemów AI: jak mierzyć i jak pilnować

Pełny program serii Gotowe: 52 z 83 tematów

Czego się dowiesz
  • Co powinno się znaleźć w zadaniu dla agenta, żeby wiedział, kiedy skończył.
  • Ile błędów wykrywają testy o różnej dokładności i dlaczego przypadki brzegowe mają znaczenie.
  • Jakie błędy popełniają agenci i jak je znaleźć przy kontroli.

Warto wiedzieć wcześniej: Jak działa agent AI: model językowy w pętli z narzędziami, Jak podchodzić do programowania z agentami AI

W poprzedniej części omówiliśmy, jak agent działa od środka. Ta część jest praktyczna: jak zlecać mu pracę, jak ją sprawdzać i jak nie stracić orientacji w tym, co dzieje się w projekcie. Większość rad da się streścić jednym zdaniem — musisz dać agentowi sposób, by sam rozpoznał, że skończył, a sam musisz mieć sposób, by to sprawdzić. Na eksperymencie pokażemy, jak bardzo to ważne.

Nawiązuje do części Jak działa agent AI i Jak podchodzić do programowania z agentami AI, gdzie jest więcej o roli człowieka i o tym, dlaczego warto pozwolić agentowi najpierw zaproponować rozwiązanie.

1. Zadanie: co, gdzie i jak poznać, że gotowe

Definicja — kryteria akceptacji

Kryteria akceptacji to weryfikowalne warunki, które wynik musi spełnić, aby zadanie było ukończone: konkretne zachowanie („dla pustego koszyka zwraca 0 CZK”), testy, które muszą przejść, polecenie, które musi wykonać się bez błędu. W odróżnieniu od opisu celu da się o nich jednoznacznie rozstrzygnąć, czy są spełnione.

Mówiąc prościej

„Posprzątaj pokój” to cel. „Na podłodze nic nie leży, łóżko jest pościelone, a kosz wyniesiony” to kryteria akceptacji. Dopiero z nimi da się powiedzieć, czy jest posprzątane — a dziecko (albo agent) wie, kiedy może przestać.

Definicja — specyfikacja jako warunek wstępny i zobowiązanie

Precyzyjnie kryteria akceptacji można zapisać trójką Hoare’a (C. A. R. Hoare, 1969; dzisiejszy zapis z nawiasami klamrowymi): {P} C {Q} mówi, że jeśli przed uruchomieniem programu C zachodzi warunek P, a C się zakończy, to potem zachodzi warunek Q. P to warunek wstępny (czego program może oczekiwać od wejścia), Q to zobowiązanie (co musi być prawdą o wyniku). Program jest poprawny względem specyfikacji, gdy trójka zachodzi dla każdego stanu spełniającego P.

{ castka ≥ 0 }   s := sazba(castka)   { s = 0 dla castka < 1 000;  s = 0,05 dla 1 000 ≤ castka < 5 000;  s = 0,1 w pozostałych przypadkach }

castka ≥ 0
warunek wstępny: za ujemną kwotę funkcja nie odpowiada — jest tu po to, by było jasne, czego testować nie musimy i czego musi pilnować wywołujący
s := sazba(castka)
program, o którym mowa; specyfikacja nie mówi nic o tym, jak jest napisany, więc agent może ją spełnić dowolnie
s = 0 / 0,05 / 0,1
zobowiązanie: dokładnie trzy przedziały i ich granice (≤ albo <) — właśnie tu najczęściej popełnia się błędy, dlatego do kryteriów akceptacji należą wartości 999, 1 000, 4 999 i 5 000
Wiersz „Gotowe, gdy” w zadaniu poniżej to to samo zobowiązanie, zapisane tak, by dało się je sprawdzić testem.

Dobre zadanie dla agenta ma cztery części. Nie dlatego, że to rytuał, ale dlatego, że każda odpowiada jednej rzeczy, którą agent w przeciwnym razie musi zgadywać:

Cel: Na stronie koszyka wyświetl rabat zależny od kwoty (od 1 000 CZK 5 %, od 5 000 CZK 10 %).

Kontekst: Obliczanie ceny jest w src/kosik.js, szablon w pohledy/kosik.ejs.
Podobnie liczy się dostawę w funkcji doprava() — trzymaj się tego samego stylu.

Ograniczenia: Nie zmieniaj formatu danych w bazie. Żadnych nowych bibliotek.

Gotowe, gdy:
- funkcja sazba(castka) zwraca 0 / 0,05 / 0,1, a testy w test/kosik.test.js przechodzą,
- dodasz testy dla granic 999, 1 000, 4 999 i 5 000 CZK,
- npm test kończy się bez błędu i pokażesz mi różnice (git diff).

Kontekst oszczędza agentowi szukania (a tobie tokenów — zob. koszt kontekstu). Ograniczenia nie pozwalają mu „rozwiązać” problemu inaczej, niż chcesz. A kryteria akceptacji dają mu informację zwrotną, bez której długie zadania się rozsypują.

2. Małe kroki, częste kontrole

W części o agentach obliczyliśmy, że zadanie z dwudziestu kroków, z których każdy udaje się w 90 %, bez kontroli wychodzi tylko w 12 % przypadków. Ta sama zasada dotyczy ciebie: im większy kawałek pracy agent oddaje naraz, tym trudniej go sprawdzić i tym droższa jest poprawka. Praktyczne konsekwencje:

  • Jedna zmiana = jedno zadanie. Dużą rzecz podziel na kroki, które da się sprawdzić osobno (najpierw obliczenie, potem wyświetlanie, potem zmiana danych).
  • System kontroli wersji jako siatka bezpieczeństwa. Przed każdym zadaniem czysty stan w gicie, po nim commit. Gdy coś się zepsuje, wracasz jednym poleceniem.
  • Czytaj różnice, nie podsumowanie. Agentowe „gotowe, wszystko działa” to twierdzenie. Różnice w kodzie (git diff) i wynik testów to dowody.

Psukces = pn

p
prawdopodobieństwo, że jeden krok się uda; jest tu, bo każdy krok to kolejna okazja do błędu
n
liczba kroków między dwiema kontrolami; jest w wykładniku, bo prawdopodobieństwa niezależnych kroków się mnożą — i z każdym kolejnym krokiem bez kontroli szansa spada geometrycznie, nie liniowo
Psukces
szansa, że cały odcinek między kontrolami pójdzie dobrze i nic nie trzeba będzie przerabiać
W uproszczeniu: kroki zawodzą niezależnie, a błąd wychodzi na jaw dopiero przy kontroli.
Przykład — ile pracy oszczędza kontrola co pięć kroków

Bez kontroli: 0,920 = 0,1216, czyli 12 %. Z kontrolą co pięć kroków: 0,95 = 0,5905 dla każdego z czterech odcinków.

Załóżmy, że kontrola zawsze wykrywa błąd, a zepsuty odcinek robi się od nowa. Liczba prób do pierwszego sukcesu ma rozkład geometryczny o wartości oczekiwanej 1 / Psukces. Całe zadanie bez kontroli kosztuje więc średnio 20 / 0,1216 ≈ 165 kroków, z kontrolą co pięć 4 · 5 / 0,5905 ≈ 34 kroków, a z kontrolą po każdym kroku 20 / 0,9 ≈ 22 kroków. Małe kroki nie zwiększają szansy, że jeden krok się uda — zmniejszają to, ile pracy idzie do kosza przy błędzie.

3. Testy jako zabezpieczenie: eksperyment

Jak bardzo pomagają testy? Weźmy pięć małych funkcji, jakie agent pisze na co dzień — średnią, rok przestępny, skracanie tekstu, wyszukiwanie binarne i rabat zależny od kwoty — i zróbmy z nich celowo zepsute wersje.

Definicja — testowanie mutacyjne

Mutant to kopia programu z jedną drobną automatyczną zmianą: < zamiast <=, - 1 zamiast + 1, || zamiast &&, inna stała. Zestaw testów wykrywa mutanta, gdy co najmniej jeden test na nim zawiedzie. Odsetek wykrytych mutantów mierzy, jak dobrze testy pilnują błędów. Mutanty, które zachowują się tak samo jak oryginał (równoważne), się nie liczą.

Mówiąc prościej

Próba czujnika dymu: celowo zapalasz małą świeczkę i patrzysz, czy zapiszczy. Tutaj celowo wstawiasz do kodu mały błąd — dokładnie taki, jaki robią ludzie i agenci — i patrzysz, czy testy to wykryją.

Z kodu źródłowego pięciu funkcji powstało automatycznie 32 mutantów. 3 z nich na 2 000 losowych wejść nigdy nie różniło się od oryginału (na przykład a[s] <= x zamiast a[s] < x w wyszukiwaniu binarnym, gdzie równość obsłużył już poprzedni wiersz), więc zostaje 29 prawdziwych błędów. Przeciwko nim cztery poziomy testów, każdy zawiera także poprzednie:

  • Szczęśliwa ścieżka — jeden lub dwa typowe przykłady na funkcję. Takie testy powstają, gdy powie się tylko „dodaj testy”.
  • Przypadki brzegowe — pusta tablica, granice przedziałów (999, 1 000, 4 999, 5 000 CZK), lata 1900, 2000 i 2100, tekst dokładnie na granicy długości.
  • Właściwości — 200 losowych wejść i reguły, które muszą zachodzić zawsze: wynik skracania ma najwyżej max znaków i jest początkiem tekstu, znaleziony indeks naprawdę wskazuje szukaną liczbę, średnia zgadza się z inaczej zapisanym obliczeniem.
0 %25 %50 %75 %100 % 0 z 29 brak 15 z 29 szczęśliwa ścieżka 26 z 29 + brzegowe 28 z 29 + właściwości poziom testów (kumulatywny, każdy zawiera poprzednie) wykryte błędy (% z 29)
Ile z 29 błędów wykryją testy

Testy szczęśliwej ścieżki łapią tylko 15 z 29 błędów (52 %). Przechodzą nawet z funkcją, która dla pustej tablicy zwraca 1, z rabatem, który zaczyna się dopiero od 1 001 CZK, albo z wyszukiwaniem binarnym, które w tablicy z jednym elementem nic nie znajduje. Dodanie przypadków brzegowych podnosi odsetek do 90 %, testy właściwości do 97 %.

funkcjamutantówszczęśliwa ścieżka+ brzegowe+ właściwości
prumer5455
jePrestupny8557
zkrat3233
najdi6366
sazba7177

MS = |O| / ( |M| − |E| )

MS
wynik mutacyjny (mutation score) — odsetek prawdziwych błędów, które zestaw testów łapie — wysokość słupka na wykresie
|O|
liczba wykrytych mutantów (co najmniej jeden test na nich zawiódł albo się wysypały lub zapętliły); to, co testy potrafią
|M|
wszystkie wytworzone mutanty — pula błędów, względem której mierzymy testy
|E|
mutanty równoważne; odejmuje się je, bo nie różnią się od oryginału, więc żaden test nie może ich wykryć — inaczej nawet doskonałe testy nie doszłyby do 100 %

U nas |M| = 32 i |E| = 3, więc mianownik wynosi 29. Szczęśliwa ścieżka: 15 / 29 = 0,517; z brzegowymi 26 / 29 = 0,897; z właściwościami 28 / 29 = 0,966. Procedura, z której wzięły się liczby:

dla każdej funkcji f:
    oryginał = skompiluj(kod f)
    dla każdego operatora (z → na) i każdego wystąpienia z w kodzie:
        mutant = skompiluj(kod, w którym to wystąpienie z zastąpiono na)
        jeśli mutant na 2 000 losowych wejść nigdy nie różni się od oryginału:
            równoważny — nie liczy się, następny
        dla każdego poziomu testów u:
            wykryty[u] = któryś test poziomu u na mutancie zawodzi,
                         wysypuje się albo zapętla (bezpiecznik po 10 000 przebiegach)
MS(u) = liczba wykrytych na poziomie u / liczba nierównoważnych

Najciekawszy jest rok przestępny. Przez przypadki brzegowe przechodzą mutanty, które za przestępny uznają każdy parzysty rok albo które wykluczają lata podzielne przez dziesięć — czyli także rok 2020. Testy z latami 1900, 2000 i 2100 tego nie wykryją, bo na nie przypadkiem odpowiadają poprawnie. Test właściwości z losowymi latami znajduje oba błędy. Jedyny mutant, który przetrwał wszystko, to (rok % 4 === 0 && rok % 100 !== 0) || rok % 200 === 0: różni się tylko dla lat podzielnych przez 200, ale nie przez 400 (200, 600, 1000…), a wśród 200 losowych lat żadnego takiego nie było. Nawet losowe testy nie są wszechmocne.

Pprzetrwa = ( 1 − q )n

q
odsetek wejść, na których mutant różni się od oryginału; 1 − q to szansa, że jedno losowe wejście go nie wykryje
n
liczba losowych wejść; wejścia losuje się niezależnie, więc szanse „nie wykrył” się mnożą
Pprzetrwa
prawdopodobieństwo, że mutanta ominą wszystkie n wejścia — błąd przejdzie, choć właściwość jest napisana poprawnie
Losowe testy niezawodnie łapią błędy, które ujawniają się często; rzadkie błędy — tylko przy bardzo wielu wejściach.
Przykład — dlaczego przetrwał mutant z rokiem podzielnym przez 200

Test właściwości losuje lata od 0 do 2 399. Mutant rok % 200 różni się od oryginału tylko w 6 z nich (200, 600, 1000, 1400, 1800, 2200), więc q = 6 / 2400 = 0,0025, a przy n = 200 przetrwa z prawdopodobieństwem (1 − 0,0025)200 = 0,606 — mniej więcej w sześciu próbach na dziesięć. To, że przetrwał, nie było więc pechem, ale oczekiwanym wynikiem.

Mutant rok % 2 różni się dla 600 lat (q = 0,25): przetrwa z prawdopodobieństwem 0,75200 ≈ 10-25, czyli praktycznie nigdy. Mutant rok % 10 różni się dla 96 lat (q = 0,04) i przetrwa z prawdopodobieństwem 0,96200 = 0,00028.

Ile wejść byłoby potrzeba, aby mutant z rokiem 200 został złapany z prawdopodobieństwem 95 %? Z (1 − q)n ≤ 0,05 wynika n ≥ ln 0,05 / ln(1 − q) = −2,996 / −0,00250 ≈ 1 196,8, czyli 1 197 wejść. Taniej jest dodać przypadek brzegowy rok 200 albo 600 — kto zna regułę kalendarza, wie, gdzie szukać.

4. Kto powinien pisać testy

Testy w eksperymencie pisaliśmy na podstawie zadania (co funkcja ma robić), nie kodu. To istotne. Gdy agent napisze kod i od razu testy do niego, grozi, że testy tylko powtórzą to, co kod robi — łącznie z jego błędami. Przejdą i niczego nie dowodzą. Pomaga:

  • Testy (albo przynajmniej ich lista) najpierw. Pozwól agentowi najpierw napisać testy na podstawie zadania, przeczytaj je, a dopiero potem kod. Kryteria akceptacji z zadania to właśnie ta lista.
  • Wymienić przypadki brzegowe. Puste wejście, jeden element, granice przedziałów, liczby ujemne, znaki diakrytyczne. Agent często uzupełni je sam, ale tylko wtedy, gdy ich chcesz.
  • Właściwości tam, gdzie się da. „Posortowana tablica pozostaje posortowana”, „zakodować i odkodować = pierwotny tekst”, „nowe obliczenie daje to samo co stare”. Biblioteki takie jak fast-check (JavaScript) czy Hypothesis (Python) same generują losowe wejścia.
Definicja — testowanie oparte na właściwościach (property-based testing)

Zamiast konkretnych par wejście–wyjście zapisuje się właściwość, która musi zachodzić dla wszystkich wejść, a narzędzie sprawdza ją na wielu losowo wygenerowanych wejściach. Gdy znajdzie kontrprzykład, zwykle zmniejsza go do najprostszego zawodzącego przypadku. Pomysł spopularyzowała biblioteka QuickCheck (Koen Claessen i John Hughes, 2000).

Mówiąc prościej

Nie pytasz „ile to jest 7 + 5”, tylko „czy zawsze a + b to to samo co b + a?” — i pozwalasz komputerowi wypróbować tysiąc losowych par. Znajdzie przypadki, o których byś nie pomyślał.

Właściwość to zdanie z kwantyfikatorem „dla wszystkich”. Dla funkcji zkrat z eksperymentu test zapisuje ją tak:

∀ t, m ≥ 1: |v| ≤ m ∧ ( |t| ≤ m ⇒ v = t ) ∧ ( |t| > m ⇒ v = t[0, |v| − 1) + „…” ),  gdzie v = zkrat(t, m)

∀ t, m ≥ 1
dla każdego tekstu i każdej długości — dlatego da się to sprawdzać na losowych wejściach i nie musimy znać poprawnego wyniku z góry
|v| ≤ m
główna obietnica funkcji: wynik się mieści; łapie mutanta, który zapomina wliczyć „…” (slice(0, max))
|t| ≤ m ⇒ v = t
krótki tekst się nie zmienia; bez tego przeszłaby funkcja, która skraca zawsze
v = t[0, |v| − 1) + „…”
skrócony wynik jest początkiem pierwotnego tekstu i kończy się wielokropkiem; bez tego przeszłaby funkcja, która zwraca na przykład pusty tekst
t[0, k) to pierwsze k znaków tekstu t. Właściwość nie mówi, ile dokładnie znaków zostanie — tylko co musi zachodzić; przez to jest ogólniejsza niż jeden konkretny przykład.

Narzędzie do testowania opartego na właściwościach robi wtedy mniej więcej to:

dla i = 1 … N:                       # N to zwykle od 100 do 1 000
    x = wygeneruj losowe wejście
    jeśli właściwość(x, f(x)) nie zachodzi:
        # zmniejszanie: szukaj prostszego wejścia, na którym nadal zawodzi
        dopóki istnieje y = uprość(x), na którym właściwość nie zachodzi:
            x = y                    # krótszy tekst, mniejsza liczba, krótsza tablica
        zgłoś kontrprzykład x
zgłoś „przeszło N wejść”             # to nie dowód, tylko dobra wiadomość

Ostatni wiersz jest istotny. Testy, nawet losowe, nie dowodzą poprawności — tylko szukają kontrprzykładów. Edsger Dijkstra ujął to w 1969 roku tak, że testowanie może wykazać obecność błędów, nigdy ich brak. Prawdopodobieństwo, że rzadki błąd się prześlizgnie, obliczyliśmy wyżej.

5. Na co uważać

Agenci popełniają inne błędy niż ludzie. Najczęstsze, których warto szukać przy kontroli:

  • „Gotowe” bez weryfikacji. Agent ogłasza sukces, nie uruchomiwszy testów, albo uruchomił je tylko częściowo. Żądaj wyniku testów.
  • Zmiana testów zamiast kodu. Gdy test zawodzi, najprostsza „naprawa” to zmienić oczekiwaną wartość albo test usunąć. W różnicach szukaj zmian w testach.
  • Wyciszone błędy. Pusty catch, wartość domyślna zamiast błędu, na sztywno wpisany wynik dla wejścia testowego.
  • Praca ponad zadanie. Przepisany plik, który nie ma związku z zadaniem, nowa biblioteka, „ulepszony” format danych. Ograniczenia w zadaniu i małe kroki trzymają to w ryzach.
  • Sekrety i nieodwracalne kroki. Hasła w kodzie, usuwanie plików, zapis do produkcyjnej bazy danych, wysłanie do zdalnego repozytorium. Takie akcje zostaw do zatwierdzania.

6. Nie stracić orientacji

Agent między sesjami niczego nie pamięta. To, co ma wiedzieć za każdym razem — jak projekt się uruchamia i testuje, jakie są konwencje, czego unikać — należy do pliku z instrukcjami w katalogu głównym projektu, który agent czyta na początku. Wpisuj tam to, na co musiałeś zwrócić agentowi uwagę więcej niż raz. A to, co wiesz tylko ty (dlaczego coś jest zrobione tak, co próbowano i nie działało), należy do commitów i dokumentacji — dla agenta i dla siebie za pół roku.

Ostatnia rada jest najprostsza: bądź przy tym. Niekoniecznie przy komputerze — agent może pracować sam, a ty zajrzysz, gdy będzie potrzebował decyzji. Dlatego powstał coden: zadanie, zatwierdzanie kroków i kontrolę wyniku masz w telefonie, podczas gdy agent pracuje na twoim komputerze.

7. Podsumowanie

  • Dobre zadanie: cel, kontekst (pliki, wzorce), ograniczenia i weryfikowalne kryteria akceptacji.
  • Małe kroki, commit po każdym i sprawdzanie różnic w kodzie oraz wyniku testów, a nie podsumowania.
  • W eksperymencie testy szczęśliwej ścieżki wykryły 52 % błędów, z przypadkami brzegowymi 90 %, z właściwościami 97 %.
  • Testy pisz (albo zatwierdzaj) na podstawie zadania i najlepiej przed kodem, inaczej tylko powtórzą błędy implementacji.
  • Pilnuj zmian w testach, wyciszonych błędów, pracy ponad zadanie i nieodwracalnych kroków.

Chcesz to wypróbować? Poproś agenta AI, żeby uruchomił na twoim projekcie narzędzie do testowania mutacyjnego (Stryker dla JavaScriptu, mutmut dla Pythona) i pokazał ci mutanty, które przetrwały. Każdy z nich to test, którego brakuje.

Masz inne zdanie? Napisz na support@coden-app.com.

Agent na twoim komputerze, sterowany z telefonu