Dlaczego modułowe monorepo nadaje się dla agentów kodujących: widzieć wszystko, edytować niewiele
Agenty ślepe typu Polyrepos oraz nieustrukturyzowane monoreposy zalewają je. Otwarty kontekst, inkapsulacja oraz rzeczywisty graf zależności umożliwiają efektywne działanie modułowego monorepo dla agentów.
Źródła: The Shine of the Modular Monorepo in the Agentic Era
Stary spór z nowymi implikacjami
Od lat inżynierowie dzielą się na dwie grupy. Jedna trzyma cały kod w jednym repozytorium, a druga przydziela każdej części osobne miejsce przechowywania, przy czym często dochodzi do kompromisów. Nikt nie ma całkowicie racji, a ci, którzy tak twierdzą, zazwyczaj opierają się na doświadczeniach z jednego projektu. Gdy zapyta się, czy monorepo, czy polyrepo jest lepsze, prawdziwa odpowiedź brzmi „to zależy”: od tego, jak duży jest system, jak ściśle są ze sobą powiązane jego komponenty, kto należy do zespołu oraz jak często wypuszczane są nowe wersje. Kilka słabo powiązanych ze sobą usług powinno znajdować się w oddzielnych repozytoriach. Produkt ściśle powiązany z wspólnymi kontraktami wskazuje na przeciwny kierunek.
Agenty kodujące jeszcze bardziej zaostrzają tę kwestię. Gdy powierzy się im zadanie obejmujące frontend, wspólną bibliotekę oraz kontrakt backendu, struktura repozytorium przestaje być kwestią gustu. Jej konsekwencje widoczne są w jakości kodu, w częstotliwości, z jaką agent musi zgadywać, oraz w stopniu jego dezorientacji. Przykład ten pochodzi z środowiska TypeScript NX obsługującego sześć platform. To określony punkt widzenia, który nie będzie odpowiadał wszystkim, więc należy go traktować jako mocno utrzymywaną opinię mającą na celu rozpoczęcie dyskusji. Cztery słowa podsumowują tę tezę: widzieć wszystko, dotykać niewiele.
Pierwsza przeszkoda: mury, za którymi agent nie może zajrzeć
Wyobraźmy sobie podzielony świat, w którym funkcjonują większość zespołów: jeden repozytorium frontendu, dwa repozytoria usług backendowych, pakiet shared-types w prywatnym rejestrze oraz repozytorium infrastruktury. Granice te mają sens, a każdy element ma swojego właściciela.
Załóżmy, że agent w repozytorium frontendu otrzymuje polecenie zmiany sposobu wywoływania endpointu należącego do repozytorium usług, do którego nie ma dostępu. Bez mechanizmu do odczytu zgaduje, jak powinna wyglądać odpowiedź. Stary szablon typu lub pojedynczy przykład testowy stają się jego dowodem. Kod kompiluje się na lokalnym komputerze, ale po integracji prawdopodobnie będzie błędny. Każda granica między repozytoriami to ściana, za którą agent nie może zajrzeć, więc zastępuje ją wiarygodnym założeniem. To, co chroni ludzi, sprawia, że agenci pozostają spragnieni informacji.
Zespoły radzą sobie z tym problemem na trzy główne sposoby, a niektóre z rozwiązań są dobre:
- Git submodules umieszczają repozytoria zależności wewnątrz głównego repozytorium, dzięki czemu struktura plików wygląda spójnie. Agent zyskuje możliwość odczytu wszystkich plików, ale za zwykłą cenę: komitety przyklejone do określonego stanu ulegają zmianom, utrzymywanie aktualności staje się uciążliwe, a proces pracy nie zadowala nikogo.
- Przestrzenie robocze IDE z wieloma korzeniami umożliwiają Cursorowi lub VS Code indeksowanie kilku repozytoriów razem, co jest przydatne, gdy celem jest jedynie przeglądanie ich zawartości. Ustrój ten należy jednak do jednej maszyny, a nie do projektu, przez co agent otrzymuje mnóstwo plików bez grafu zależności. Wie on o istnieniu kodu, ale nie o tym, co od czego zależy.
- Syntetyczne monorepozytoria stanowią poważną alternatywę. Na przykład Polygraph z NX łączy oddzielne repozytoria w jeden graf zależności, pozostawiając kod tam, gdzie jest. Agent koordynujący korzysta z tego grafu, aby określić, do których repozytoriów dotrze zmiana, uruchamia agenta w każdym z nich i otwiera odpowiednie prośby o pull request, jednocześnie śledząc procesy CI we wszystkich miejscach. Jest to rozwiązanie najbliższe zachowaniu monorepozytorium w ramach struktury typu polyrepo.
Należy okazać szacunek podejściu syntetycznemu, ale spójrzmy, co ono tak naprawdę robi: tworzy tunele przez mury, które pozostają nienaruszone. Inżynierowie wkładają ogromny wysiłek w warstwę narzędziową, aby odtworzyć widoczność, jaką monorepo zapewnia strukturalnie bez żadnych kosztów. A gdy takich narzędzi nie ma, człowiek pełni rolę tunelu – czyta dane z usługi B, przenosi informacje do agenta w usłudze A, wkleja definicje typów do czatu i działa jako kurier pomiędzy zamkniętymi sesjami.
Druga przeszkoda: bezstrukturalny bałagan
Zatem wszystko trafia do jednego repozytorium i sprawa jest załatwiona? Nie do końca. Monorepo bez wewnętrznej struktury radzi sobie jeszcze gorzej, ponieważ kusi. Wszystko jest widoczne, co wydaje się wystarczające. W rzeczywistości istnieje jeden ogromny katalog aplikacji, biblioteki, które importują się wzajemnie ze wszystkich stron, brakuje narzuconych granic oraz jasności co do tego, która część należy do kogo.
Tutaj otwarty kontekst szkodzi. Agent, który widzi wszystko, nie otrzymuje żadnych wskazówek co do tego, co można pominąć. Okno wypełnia się kodem znajdującym się blisko na dysku, ale nierelacyjnym do zadania; jedna edycja wpływa na elementy importowane, których nikt nie śledzi, a na kluczowe pytanie – jak ta zmiana wpływa na całość – odpowiada się „prawdopodobnie na wszystko”. Widoczność bez struktury to hałas, a nie kontekst, dlatego przechowywanie całego kodu w jednym repozytorium nie jest rozwiązaniem.
Trzy filary modularnego monorepo
Modularne monorepo odnosi sukces, robiąc jednocześnie trzy rzeczy. Zignorowanie choćby jednej z nich prowadzi do niepowodzenia.
Otwarty kontekst. Jedno drzewo zawiera wszystko, a agent może przemieszczać się po nim: interfejs użytkownika, warstwę serwerową, biblioteki wspólne, testy oraz umowy typów, które je łączą, wszystko to w jednej sesji. Żadnych barier, żadnych domysłów, żadnych kurierów. Plan rozwoju NX najwyraźniej podkreśla ten element, i to słusznie, ponieważ agent, który w jednej iteracji odczyta producenta umowy oraz wszystkich jej konsumentów, będzie mógł dokonywać lepszych modyfikacji.
Encapsulacja. Biblioteki są ograniczone i udostępniają wyraźne, publiczne interfejsy, dzięki czemu agent nie musi mieć całego systemu w pamięci. Pracuje on z określonym fragmentem. To właśnie ta zasada umożliwia współistnienie możliwości widzenia wszystkiego przy jednoczesnym minimalnym angażowaniu się w szczegóły, bez niej zaś otwarty kontekst przeradza się w problem nr dwa.
Prawdziwy graf zależności, wraz z narzędziami do jego badania. To jest element, który ludzie niedoceniają. NX traktuje ten graf jako artefakt pierwszej klasy, który można analizować. Zamiast szukać informacji i mieć nadzieję na wywnioskowanie struktury, agent może uruchomić nx show projects, otworzyć nx graph, zapytać, jakie zmiany są wpływowe, i otrzymać precyzyjną odpowiedź, którą maszyna może przetworzyć. Ta mapa znajduje się w repozytorium, a nie na wiki czy w pamięci doświadczonego inżyniera, i jest wykonywalna.
Wspólnie rozwiązują one czterosłowną tezę: widzenie wszystkiego to pierwszy filar, dotykanie niewielu elementów to drugi filar, a wiedza o tym, które z tych elementów należy dotknąć, to trzeci filar – most, który umożliwia bezpieczne połączenie pierwszych dwóch.
Zdobywanie i weryfikacja
Agenty działają w pętli polegającej na pobieraniu kontekstu, modyfikowaniu kodu, sprawdzaniu tych zmian i powrocie do tego procesu. Wszystkie działania związane z utrzymaniem porządku w monorepo służą jednej z dwóch celów: taniego pozyskiwania kontekstu lub taniego sprawdzania dokonanych zmian.
- Mocne typy (acquire). Wspólna biblioteka typów zapewnia agentowi umowę, którą może odczytać, a kompilator może egzekwować. To rozwiązuje problem „ślepego agenta” z pierwszego etapu, ponieważ nie trzeba zgadywać struktury odpowiedzi, gdy jest ona zapisana i sprawdzona. Typy pełnią również rolę dokumentacji, która nigdy nie staje się przestarzała.
- Zasady dotyczące brudów kodu i granic modułów (sprawdzić). Dzięki funkcji
@nx/enforce-module-boundariesw NX zakazane importy powodują błąd zamiast przejść niezauważone, a informacja o błędzie trafia do pętli samego agenta jako informacja zwrotna. Jeśli agent podłączy bibliotekę interfejsu użytkownika do warstwy danych, zasada to odrzuca, a architektura jest wtedy ustalana na podstawie tego niepowodzenia, bez konieczności ręcznego jej zapisywania. - TDD i powiązane testy (sprawdzić). Narzędzie
nx affectedumożliwia szybką weryfikację. Po edycji fragmentu kodu agent uruchamia tylko te testy, które znajdują się poniżej niego, i szybko widzi wynik – czerwony lub zielony – bez konieczności czekania na pełny zestaw testów czy wątpliwości co do skuteczności zmiany. Krótkie pętle sprawiają, że praca z agentem przypomina budowanie, a nie opiekę nad czymś. - Umiejętności oraz pliki AGENTS.md lub CLAUDE.md (nabycie). Uruchomienie polecenia
npx nx configure-ai-agentsw przestrzeni roboczej instaluje serwer MCP, umiejętności agenta oraz pliki z zasadami projektowania. Umiejętności są dodawane na żądanie, a nie wszystkie naraz w pole instrukcji, więc sposób tworzenia biblioteki jest poznawany dokładnie w momencie jej tworzenia. Pomagają one również agentowi w wyszukiwaniu informacji w grafie zamiast tylko przeszukiwania tekstu, co nawiązuje do trzeciego filaru. - Atomowe przewodniki dla poszczególnych modułów (nabycie). Każda biblioteka może zawierać krótki plik README lub AGENTS.md, dostarczający lokalnego kontekstu dokładnie w miejscu, gdzie agent właśnie się pojawił. Wejście do tej biblioteki przywołuje jej kontrakt oraz zasady projektowania, bez konieczności pobierania całej reszty struktury.
Jeśli prześledzić tę listę, widać sekwencję: pozyskiwanie, weryfikacja, weryfikacja, pozyskiwanie, pozyskiwanie, chociaż kolejność ta jest przypadkowa. Każda z możliwości odpowiada jednej z tych dwóch czynności. Modularne monorepo to nie jedna funkcja przeznaczona dla agentów, lecz wiele małych funkcji, które sprawiają, że proces pozostaje szybki i efektywny.
Argumenty przeciwko
Nikt nie czerpie korzyści z prezentacji sprzedażowych, więc warto rozważyć przeciwwagę. Okna kontekstowe stale się powiększają, a narzędzia do zarządzania wielorakimi przestrzeniami roboczymi oraz syntetyczne monorepo coraz bardziej skracają tę luki. Skeptyk mógłby uznać zaletę monorepo za tymczasowy efekt obecnych ograniczeń, który zniknie przy wystarczająco dużym oknie kontekstowym oraz przydatnych narzędziach do pracy między repozytoriami. Bardziej precyzyjna wersja tego argumentu nie dotyczy okien kontekstowych. Polygraph pokazuje, że graf zależności można odbudować w ramach polyrepo, więc struktura często przypisywana monorepo nie może należeć wyłącznie do nich.
Każda wersja błędnie ocenia źródło korzyści. Nigdy nie chodziło o czytanie większej ilości surowego tekstu – chodzi o jego strukturę. Większe okno umożliwia agentowi zagubionemu w drobnych szczegółach dalsze poszukiwania bez wskazania właściwych drzwi. Graf syntetyczny również stanowi strukturę, która wyjaśnia, dlaczego działa, ale ta struktura jest odbudowywana i utrzymywana na podstawie podziału, a nie wynika bezpośrednio z układu. Surowy kontekst rozwija się wraz z modelem, struktura – dzięki dyscyplinie, a struktura przekształca możliwość widzenia wszystkiego w zagrożenie w atut. Gdy okna się powiększają, monorepo pozbawione modułów staje się bardziej ryzykowne, ponieważ „brama” staje się szersza. To przymiotnik ponosi ten ciężar.
Co ujawniła era agentów
Wykresy projektu, granice modułów oraz wspólne typy kiedyś wydawały się udogodnieniami dla zespołu ludzi. Era agentów ujawniła, czym one przez cały czas były: interfejsem dla nieludzkich współpracowników. Architektura opracowana z myślą o ludzkim myśleniu okazała się w rzeczywistości inżynierią kontekstu na poziomie repozytorium, wiele lat przed pojawieniem się tego terminu. To sprawia, że ponownie w modzie stają się rozwiązania inne niż monorepozytoria. Modułowe monorepozytorium cicho odpowiedziało na pytanie, którego nikt jeszcze nie zadał. Widzieć wszystko, dotykać niewiele – a agenci jedynie to uwyraźnili.
Literatura pokrewna
- Praktyczne notatki: Tworzenie platformy enterprise agentic przystosowanej do przyszłości — Szczegółowy przewodnik po Praktycznych notatkach: Tworzenie platformy enterprise agentic przystosowanej do przyszłości: umowy, sprawdzenia oraz miejsca na kod do wklejenia dla zespołów wdrażających ten model.
- Ornith-1.0: Modele kodowania typu open-weight od 9B do 397B pod licencją MIT — Co zapowiada wydanie Ornith-1.0 na SWE-Bench i Terminal-Bench, jak trenuje ono szkielet z rozwiązaniem oraz co to może oznaczać dla zamkniętych agentów kodujących.