Kiedy agent kończy pracę, zwykle słyszysz jedno zdanie: “Gotowe, wszystko działa”. I zaczyna się zgadywanie - sprawdzać, nie sprawdzać, czytać diffa, czy od razu klikać w aplikację?
Mateusz Wróbel, senior software engineer w Trivago, ma na to prostą odpowiedź. W rozmowie w podcaście Opanuj.AI ujął to tak:
Środowisko testowe jest po to, żeby dać agentowi narzędzia do tego, żeby udowodnił, że robota jest zrobiona.
Mateusz pracuje w branży od ponad 16 lat, zaczynał od PHP i jQuery, a od 2023 roku buduje rozwiązania oparte o LLM-y. Poniżej najważniejsze praktyki z jego doświadczeń; własne obserwacje zaznaczam osobno.
Najpierw infrastruktura, potem funkcje
Przykład z prywatnego projektu Mateusza: własna klawiatura na Androida obsługiwana wyłącznie mikrofonem, docelowo zamieniona w asystenta głosowego.
Pierwsze commity nie zawierały ani linijki logiki klawiatury. Był to zestaw kontenerów z Android Studio i emulatorami oraz akcje CI, które budowały obrazy i wysyłały je do rejestru, żeby później dało się je po prostu pobrać w workflow.
Już przy pierwszym funkcjonalnym commicie testy uruchamiały aplikację i przechodziły całą ścieżkę end-to-end (E2E): od klawiatury zainstalowanej na Androidzie, przez API Mateusza, aż po model, który na jego maszynie zamienia mowę na tekst.
Jak sam mówi, wszystkie jego prywatne projekty zaczynają się od testów. Najpierw przygotowuje sposób sprawdzenia oczekiwanych zachowań i pełne środowisko, w którym aplikację da się uruchomić i przetestować.
Wynik testów to dopiero pierwszy artefakt
Skoro środowisko testowe już istnieje, można nim wygenerować kolejne dowody: screenshoty, nagrania wideo czy diagramy relacji w bazie danych.
Mateusz zwraca uwagę, że samo przeklikiwanie aplikacji przez agenta często pokazuje mu, że coś jednak nie działa. Miał być przycisk, a przycisku nie ma - więc agent sam zaczyna to poprawiać. Większość takich poprawek wygląda według Mateusza tak samo: agent próbował udowodnić, że coś działa, okazało się, że nie działa, więc to naprawił.
Drugi wariant to czysta eksploracja. Mateusz daje agentowi aplikację i prosi o sprawdzenie, czy zaczynając od totalnego zera da się utworzyć wszystko, co potrzebne do pracy. Czasem wychodzi luka, o której nie pomyślał ani on, ani model.
Dopiero na końcu wchodzi człowiek. Mateusz bierze wynik i sam z niego korzysta, bo to on zamówił tę funkcję i to on jest teraz użytkownikiem końcowym. Nawet jeśli oznacza to zbudowanie pakietu instalacyjnego aplikacji Android (APK) na komputerze i zainstalowanie go na telefonie.
Głupio proste prompty
Zapytałem Mateusza, czy po takiej inwestycji w infrastrukturę same prompty nie stają się… trochę niechlujne.
Staram się sprowadzić wszystko do tego, żeby to było głupio proste.
Jego argument: tempo pracy z agentami jest tak duże, że ciągłe myślenie o każdym aspekcie wyczerpuje twoją uwagę. A nie wszystko jest na tyle ważne, żeby poświęcać temu czas przy obecnym stanie modeli.
Dlatego Mateusz może być w prompcie bardziej ogólny i podać samą ideę. W temat wchodzi głębiej dopiero wtedy, gdy z rozmowy wyjdzie coś naprawdę interesującego.
Wymienia też dwa warunki. Jakiś workplan, czyli tekstowy plan zadań dla agenta, i tak musi powstać, bo z jednego zdania nie da się puścić modelu - jak mówi, nawet samego siebie nie da się tak puścić na pisanie aplikacji. A środowisko musi pozwolić agentowi sprawdzić wymagane zachowania: przeszedł daną ścieżkę, odświeżył stronę, zapisane dane się odtworzyły.
Wtedy, według Mateusza, można przez dwa dni nie dotykać kodu i dostać działającą aplikację. Potem przegląda architekturę i bazę na podstawie artefaktów, spisuje uwagi do refaktoru, a następnego dnia ma to gotowe.
W opisanym przez niego wariancie kosztuje to dzień dodatkowej pracy, za to odciąża głowę. Mateusz zastrzega przy tym, że wiele zależy od rodzaju aplikacji i zakresu swobody, na jaki chcemy pozwolić agentowi.
”Nie rób estymat” w AGENTS.md
Mateusz ma wrażenie, że wcześniejsze modele szły na skróty: budowały absolutne minimum i odkładały część pracy, bo “zajmie to za dużo czasu”.
Tyle że ta estymacja była zdaniem Mateusza kompletnie oderwana od rzeczywistości - i nie była argumentem ani dla modelu, ani dla niego. Dlatego trafiło to wprost do AGENTS.md: żadnych estymat. Chodzi o to, żeby model nie ucinał uzgodnionego zakresu na podstawie własnej estymaty.
W tym kontekście Mateusz mówi też o MVP (minimum viable product), czyli minimalnej wersji produktu służącej sprawdzeniu pomysłu:
Nie chcemy MVP, mnie nie interesuje MVP. Ja chcę mieć zrobione dobrze.
Według Mateusza po tej zmianie zniknęła potrzeba pilnowania modelu krok po kroku w trakcie konwersacji. Można go puścić, poczekać na wynik i dopiero wtedy zdecydować, czy gdzieś wchodzić głębiej.
Workplany bez szczegółów implementacji
Workplan agent tworzy na podstawie rozmowy o zadaniu. Mateusz opowiadał, że jeszcze około pół roku przed nagraniem ich plany zawierały szczegóły implementacyjne: które pliki ruszyć, jakie klasy napisać.
W opisanym procesie plany są niezależne od języka i frameworka: określają, co ma zostać zrobione. Implementację prowadzi workflow TDD (test-driven development), czyli praca od testu przez kod spełniający jego wymagania do refaktoryzacji. Agent sam implementuje, robi review i refaktoryzuje.
Bo po co mamy sprawdzać kod, zanim jeszcze on został napisany i dowieziony?
Mateusz zauważa, że to duża bariera dla programistów przywiązanych do tego, jak wygląda kod. Ja dorzuciłem w rozmowie swoją intuicję: coraz łatwiej przewidzieć efekt funkcjonalny, choć kod za każdym razem wygląda inaczej.
Mówiłem o wydaniu modelowi 10 razy tego samego polecenia i uzyskaniu 10 działających realizacji. To ilustracja mojego doświadczenia, nie wynik benchmarku ani gwarancja skuteczności.
Skille dopisywane po błędach
Ile instrukcji potrzeba, żeby to działało? Według Mateusza mniej, niż się wydaje. W projekcie reactowym w Trivago mają 4-5 subagentów, czyli pomocniczych agentów do konkretnych zadań, i łącznie około 15 skilli - instrukcji prowadzących ich przez te zadania.
Do tej liczby wliczają się skille współdzielone między projektami: tworzenie workplanów oraz prowadzenie workflow TDD i BDD (behavior-driven development). W BDD wymagania opisuje się przez oczekiwane zachowania systemu.
Nowy skill powstaje dopiero wtedy, kiedy agent zrobi coś głupiego.
Przykład: Storybook ma być w konkretnym miejscu, więc powstał skill opisujący, gdzie jest Storybook, do czego służy i kiedy go uruchamiać. Workflow TDD mówi z kolei, że dowodem zmiany w komponencie UI jest screenshot albo test wizualny, i odsyła do tego skilla.
Druga zasada to standaryzacja. Workplany w projektach, przy których pracuje Mateusz, zawsze lądują w tym samym miejscu, niezależnie od tego, czy to .NET, czy frontend. W prywatnych projektach poszedł dalej: każdy projekt wygląda tak samo, więc nie potrzebuje osobnych skilli wyjaśniających układ każdego projektu.
Architektura sprawdzana deterministycznie
Brak determinizmu modeli nie oznacza braku determinizmu w projekcie. Mateusz od lat korzystał w projektach JavaScriptowych z ESLinta z pluginem do importów. Można w ten sposób wymusić, żeby inne moduły korzystały wyłącznie z publicznego wejścia index.ts, zamiast importować wewnętrzne pliki.
Do zapisania takich ograniczeń służą na przykład reguły eslint-plugin-import, w tym no-internal-modules.
Jak mówi, to prosta rzecz - trzeba tylko wiedzieć, że takie narzędzia istnieją. A jak nie istnieją, można je dziś po prostu napisać.
Tak powstał ArchSpec Mateusza, narzędzie do sprawdzania architektury w różnych językach. Porównuje zadeklarowaną architekturę z modelem wyodrębnionym z faktycznego kodu, a nie z tym, co „wypluje” agent.
W rozmowie Mateusz mówił o definicji w YAML-u; obecne README opisuje plik architecture.spec.toml. W momencie nagrania narzędzie obsługiwało Rusta, .NET/C# i Go. Mateusz zapowiadał też obsługę Reacta, choć przyznawał, że zastąpienie dependency-cruisera będzie trudne.
Agent, który psuje
Mateusz ma też własny podział ról między dewelopera a specjalistę od jakości. Jego zdaniem deweloper, który pisze testy integracyjne i end-to-end, powinien dostarczyć działającą aplikację - jak deweloper budujący dom, który ma stać, mieć okna i drzwi.
W tym podziale specjalista od jakości nie powinien klikać, czy przycisk działa. Ma oceniać, czy zrobiliśmy dobrą aplikację, a nie czy działającą.
To samo przenosi na agentów. Skoro AI potrafi coś popsuć albo się gdzieś włamać, to jeden agent może coś zbudować albo zabezpieczyć, a drugi próbuje to zepsuć i robi raport z testów eksploracyjnych. Wynik wraca do pierwszego agenta, który to poprawia.
Sprawdzanie nie musi kończyć się na testach E2E i analizie statycznej. Uzupełnieniem może być agent, któremu dajesz link do własnego środowiska testowego i mówisz: spróbuj się tu włamać. Jego raport dostarcza kolejnych ustaleń do sprawdzenia, a nie gwarancji, że znalazł wszystkie problemy.
Co z tego wziąć
Jeśli miałbym wybrać trzy rzeczy do przetestowania od jutra:
- Zanim agent zbuduje pierwszą funkcję, daj mu środowisko, w którym sam udowodni, że działa - testy E2E, screenshoty, nagrania.
- W planie opisz oczekiwane zachowania. Do AGENTS.md dopisz, żeby agent nie ucinał uzgodnionego zakresu na podstawie własnych estymat.
- Architekturę pilnuj deterministycznie, a skille dopisuj dopiero po tym, jak agent zrobi coś głupiego.
W pełnym wywiadzie z Mateuszem Wróblem rozmawiamy z Mateuszem także o jego domowej infrastrukturze do pracy z agentami, powodach odchodzenia od dostawców chmurowych i własnej bramce, która przełącza się między dostawcami modeli w razie awarii. Na stronie odcinka znajdziesz również pełną transkrypcję rozmowy.