Ten wpis otwiera serię use-case’ów: zamiast teorii - konkretne wdrożenia podejścia everything-is-a-code na żywych projektach, z kodem i wnioskami. Kolejne znajdziecie pod tagiem use-case.
Projekt, którego nikt nie chce ruszać
Każdy z nas ma taki projekt. U mnie to ledo - małe CLI w Go, które napisałem w 2021 roku, bo miałem dość wklepywania docker-compose -f docker/docker-compose.yml -f docker/docker-compose.dev.yml up -d po sto razy dziennie. Ledo owija docker-compose (i podman-compose) w pojęcie trybów: w .ledo.yml deklarujesz, że tryb dev to takie a takie pliki compose, tryb test inne - i od tej pory piszesz tylko ledo container up.
Narzędzie robi swoje od pięciu lat. Vendorowane zależności, sto parę commitów, kilka firm używa go w codziennej pracy. Klasyczne legacy w najlepszym wydaniu: działa, więc nikt go nie dotyka.
Aż przyszły agenty.
Scenka z życia: proszę agenta w jednym z projektów o dopisanie kroku testów do pipeline’u. Agent widzi w repo pliki compose, więc oczywiście generuje gołe docker compose -f ... -f ... up, omijając ledo szerokim łukiem. Poprawiam, tłumaczę. Za drugim razem używa już ledo, ale wymyśla flagę --timeout do uponce, której nie ma. Za trzecim - wpisuje w .ledo.yml blok container: zamiast docker:, bo przecież „tak wygląda logiczniej”. Parser czyta docker:, więc konfiguracja po cichu wychodzi pusta.
I to jest moment, w którym można się obrazić na LLM-y. Albo zrozumieć, co się właściwie stało.
Agent to nowy w zespole - tylko bez onboardingu
Agent zachowywał się dokładnie tak, jak zachowałby się nowy programista pierwszego dnia w projekcie: robi rzeczy „na czuja”, na bazie tego, co widział gdzie indziej. Różnica jest taka, że człowiekowi robimy onboarding, a agentowi - nie. Cała wiedza o tym, jak się pracuje w tym projekcie, siedziała w jednym miejscu: w mojej głowie.
W duchu EIAC wniosek nasuwa się sam: kontekst projektu też jest kodem. Jeśli infrastruktura, design i polityki mogą być kodem - wersjonowanym, review’owalnym, testowalnym - to wiedza plemienna o pięcioletnim CLI tym bardziej. Wdrażanie LLM w starym projekcie to nie jest „podłączanie AI”. To refaktoring wiedzy: z głowy do repozytorium.
Poniżej proces, który przeszedłem z ledo, krok po kroku. Da się go powtórzyć w dowolnym legacy.
Krok 0 - spis wiedzy plemiennej
Zanim cokolwiek napiszesz, zbierz listę rzeczy, które wiesz tylko Ty. Mój patent: nie siadałem do tego „na sucho”, tylko zbierałem halucynacje agentów. Każdy błąd agenta to nieudokumentowana reguła projektu. Po dwóch tygodniach miałem listę:
.ledo.ymlużywa kluczadocker:, niecontainer:- parser czyta tylko ten pierwszy;ledo container downkasuje wolumeny,pruneczyści wszystko - te komendy nigdy nie mogą trafić do CI bez guardu;- do CI służy
ledo container uponce- odpala stack raz i kończy z kodem wyjścia głównego serwisu; uponcenie przyjmuje żadnych flag, aledo image pushbierze wersję pozycyjnie, nie przez--tag;- każdy tryb w
modes:musi wskazywać istniejące pliki compose, amain_servicemusi być w bazowym pliku.
Zauważcie: żadna z tych rzeczy nie wynika z kodu w sposób oczywisty. Wszystkie wynikają z decyzji sprzed lat, których uzasadnienie pamiętam tylko ja. To jest właśnie definicja legacy.
Krok 1 - AGENTS.md, czyli onboarding w repo
Pierwszy artefakt: AGENTS.md - otwarty standard pliku z instrukcjami dla agentów, który rozumieją Claude, Copilot, Cursor i reszta towarzystwa. Zasada, którą sobie przyjąłem: krótko. Ten plik siedzi w kontekście agenta praktycznie zawsze, więc płacisz za każdą linijkę. Trafiły tam tylko dwie rzeczy: golden path i guardraile.
## Golden-path commands
ledo container up [-b|-l|-n] # start the stack for the current mode
ledo container uponce # run once, exit with main service's code (use in CI)
ledo image build [version] # build project image (FQN = registry/namespace/name)
ledo mode list | select <m> # list / switch modes
## Must-know guardrails
- `.ledo.yml`'s container block uses the **`docker:`** key (not `container:`).
- Destructive - never run in CI: `ledo container down`, `rm`, `prune`.
Sam AGENTS.md wystarczył, żeby zniknęła połowa problemów. Ale tylko w repo ledo - a ja przecież potrzebowałem, żeby agenty umiały ledo w innych projektach.
Krok 2 - skill: wiedza na żądanie, nie w twarz
Druga warstwa to skill - katalog .apm/skills/ledo/ z trzema poziomami szczegółowości (progressive disclosure):
SKILL.md- kiedy się aktywować (praca z.ledo.yml, compose, Taskfile, pipeline’y) i mentalny model narzędzia: tryby, główny serwis, resolucja od git roota.reference.md- kompletna matryca komend i flag plus schemat.ledo.yml. W skillu stoi wprost: consult it before emitting anyledo ...invocation so you never invent a flag. To zdanie zabiło halucynowane flagi w stu procentach przypadków u mnie.templates/- osiem plików copy-and-adapt: bazowy compose + warianty dev/test,ledo.yml,Taskfile.ymli trzy gotowe pipeline’y CI: GitHub Actions, GitLab CI i Gitea Actions.
Ten podział to nie kosmetyka. Gdybym wkleił całą referencję do AGENTS.md, spaliłbym kontekst agenta przy każdym zadaniu, także tych niezwiązanych z ledo. Skill ładuje się tylko wtedy, gdy jest potrzebny - a wtedy agent ma wszystko, łącznie z szablonami, których nie musi wymyślać.
Krok 3 - z katalogu robi się paczka: APM
I tu jest clou całej historii. Skill w repo ledo uczy agenta pracy nad ledo. Ale ledo jest narzędziem, którego używam w innych projektach - i tam też chcę mieć agenta, który je zna. Ręczne kopiowanie skilla między repozytoriami? Dziękuję, już to przerabiałem z konfigami edytorów :)
Rozwiązanie: Agent Package Manager (APM) - menedżer paczek dla wiedzy agentowej (wpis w katalogu). Dokładnie ta sama mechanika co npm czy go modules, tylko zamiast bibliotek dystrybuujesz skille i instrukcje. Repo ledo dostało manifest apm.yml:
name: ledo
version: 1.6.2
description: >-
Drive the ledo (LeadDocker) CLI - scaffold .ledo.yml, mode-aware
docker-compose files, CI pipelines (GitHub/GitLab/Gitea), and Taskfiles.
type: hybrid # skill (na żądanie) + instructions (zawsze aktywne)
targets:
- claude
- copilot
includes: auto # bierz wszystko z .apm/
Typ hybrid oznacza, że paczka niesie dwie rzeczy naraz: skill (ładowany na żądanie) i always-on instructions - krótkie reguły przypięte do wzorców plików (**/.ledo.yml, **/docker-compose*.yml, **/.gitea/workflows/*.yml…), które pilnują guardraili przy każdej edycji tych plików, nawet gdy skill się nie aktywował.
Jedna zasada, której warto pilnować jak niepodległości: .apm/ jest jedynym źródłem prawdy. Pliki w .claude/ czy .github/ są generowane przez apm install - nie edytuje się ich ręcznie, tak samo jak nie edytuje się ręcznie node_modules/.
Krok 4 - instalacja w dowolnym projekcie
Konsumpcja wygląda tak, jak powinna wyglądać każda zależność - deklaratywnie i z pinem do wersji:
# apm.yml w Twoim projekcie
name: my-app
version: 0.1.0
dependencies:
apm:
- paramah/ledo#v1.6.2 # pin do taga wydania
apm install # resolves dependencies into apm_modules/
apm install --target claude # deploy skilla do .claude/
apm install --target copilot # albo .github/copilot-instructions.md
Od tego momentu w projekcie-konsumencie proszę agenta: „dodaj CI z testami i publikacją obrazu” - i dostaję pipeline, który wygląda tak samo niezależnie od tego, czy projekt żyje na GitHubie, GitLabie, Gitei czy Forgejo (workflowy Gitea Actions są składniowo zgodne z GitHub Actions, więc szablon jest niemal wspólny). Wzorzec zawsze ten sam: instalacja ledo → ledo mode select test → ledo container uponce na testy, a na tagach login do rejestru → ledo image build <wersja> → ledo image push <wersja>. Zero wymyślonych flag, zero container down w CI, zero gołego docker compose.
Co się realnie zmieniło
Trzy rzeczy, które widzę po kilku miesiącach:
Agent przestał być turystą. W świeżym projekcie z zainstalowaną paczką agent od pierwszego prompta używa ledo poprawnie - łącznie z rzeczami, o których nowy człowiek w zespole dowiedziałby się dopiero po tygodniu (albo po skasowaniu wolumenów na stagingu…).
Wiedza dostała wersjonowanie. Pin paramah/ledo#v1.6.2 znaczy, że wiedza agentowa aktualizuje się tak samo jak każda inna zależność: świadomym bumpem, z changelogiem, przez PR - pełna mechanika SemVer i Conventional Commits, tylko że przedmiotem wersjonowania jest kontekst, nie kod. Jak zmienię zachowanie CLI, konsumenci dostaną nową wiedzę razem z nową wersją - a nie „kiedyś, jak sobie przypomnę”.
Legacy przestało być karą. To jest dla mnie największe zaskoczenie: pięcioletni projekt, którego nikt nie chciał ruszać, stał się łatwiejszy w utrzymaniu niż niejeden świeży - bo cała wiedza o nim jest jawna, spakowana i instalowalna.
Przepis na Twój legacy
Uogólniając proces z ledo na dowolny stary projekt:
- Zbieraj halucynacje, nie pisz z głowy. Puść agenta na typowe zadania i notuj każdy błąd - to gotowa lista guardraili.
- AGENTS.md na start, ale krótki. Golden path + guardraile. Wszystko, co długie, wynieś poziom niżej.
- Skill z progressive disclosure. Opis aktywacji → pełna referencja → szablony. Agent ma sprawdzać referencję, nie zgadywać.
- Szablony zamiast opisów. Jeden działający
gitlab-ci.ymlwtemplates/jest wart więcej niż strona prozy o tym, jak taki plik powinien wyglądać. - Spakuj to. Manifest
apm.yml, typhybridjeśli masz i skill, i reguły per-plik,.apm/jako źródło prawdy. - Pinuj wersje. Wiedza agentowa to zależność jak każda inna - traktuj ją tak w
apm.ymlkonsumenta.
Zwróćcie uwagę, że w tym procesie nie zmieniłem w samym ledo prawie nic. Nie przepisywałem legacy „pod AI”. Dopisałem do niego warstwę kontekstu - i to wystarczyło.
Polecam wziąć na warsztat swój najbardziej zakurzony projekt i przejść te sześć kroków. Najstarszy kod w firmie zna najwięcej odpowiedzi na pytanie „dlaczego tak” - szkoda, żeby znały je tylko dwie osoby i żadna z nich nie była agentem :)
Wnioski dla EIAC
Case ledo jest mały, ale wnioski z niego skalują się na całą tezę Everything Is A Code. Cztery, które zabieram ze sobą:
Kontekst agentowy to pełnoprawny artefakt platformy. Obok kodu, infrastruktury, designu i polityk pojawia się piąta rzecz, którą trzeba trzymać w repo: wiedza o tym, jak się w projekcie pracuje. Ma swoje pliki, swój format, swój lifecycle. W modelu poziomów agentowego wytwarzania to jest dokładnie ten fundament, bez którego nie ma mowy o wyższej autonomii - agent bez skodyfikowanego kontekstu utknie na poziomie „zdolnego stażysty” na zawsze.
Golden path działa na agentów tak samo jak na ludzi. Platform engineering od lat powtarza: nie zmuszaj ludzi do pamiętania, daj im wydeptaną ścieżkę. Okazuje się, że agent jest idealnym konsumentem golden path - bo w przeciwieństwie do człowieka zawsze czyta dokumentację, o ile tylko ta jest w jego kontekście. Platforma w erze agentów to w dużej mierze właśnie to: te same golden paths, tylko podane w formacie, który agent instaluje jak zależność.
Guardraile to policy-as-code dla wiedzy. Lista „czego agentowi nie wolno” (destrukcyjne komendy poza CI, wymyślanie flag, edycja generowanych plików) niczym nie różni się koncepcyjnie od polityk, które egzekwujemy na infrastrukturze. Reguła, której nie da się załadować do kontekstu agenta, podzieli los polityki z wiki - nikt (i nic) jej nie przestrzega.
Neutralność wobec forge’a to exit-by-design w małej skali. Paczka, która generuje ten sam pipeline na GitHubie, GitLabie, Gitei i Forgejo, oznacza, że wiedza projektu nie jest zakładnikiem żadnego dostawcy - dokładnie ta sama logika, która stoi za suwerennym IDP z wyjściem wpisanym w architekturę. Kodyfikując kontekst, przy okazji dostajesz przenośność. Za darmo.
Krótko: EIAC nie kończy się na infrastrukturze i designie. Wiedza plemienna była ostatnią rzeczą w projekcie, która żyła poza repozytorium - i właśnie przestała mieć wymówkę.
Materiały online
- ledo (LeadDocker) - repo z kompletną paczką APM w
.apm/ - Agent Package Manager - dokumentacja i quickstart
- AGENTS.md - otwarty standard instrukcji dla agentów
- Gitea Actions i Forgejo Actions - zgodność składniowa z GitHub Actions
- Compose Specification - na czym to wszystko stoi