6 min readDe Kicked Team
Workflow-ul nostru de dezvoltare asistată de AI: fișiere de plan, guardrail-uri și diff-uri revizuite
Workflow-ul concret pe care îl folosim ca să livrăm software cu agenți AI de programare: un PLAN.md scris de un om, milestone-uri care nu se pot strica reciproc, CI ca poartă strictă și diff-uri mici, revizuite. Ce automatizăm, ce rămâne la oameni și ce facem când agentul o ia razna.
- AI
- Agentic Development
- DevOps
- Best Practices
Am livrat până acum trei tool-uri open-source de infrastructură — nftably, birdy și meerkat — cu agenți AI de programare făcând cea mai mare parte din scris. Nu ca experiment: ca workflow real de producție. Acest articol este workflow-ul în sine, suficient de detaliat ca să-l poți fura. Pentru contextul conceptual, începe cu ce este de fapt dezvoltarea agentică; pentru rezultate, vezi studiul de caz.
Totul începe cu un PLAN.md scris de un om
Înainte ca un agent să atingă repo-ul, un om scrie documentul de design. Ale noastre conțin, în ordine:
- Ce este lucrul respectiv, într-un paragraf — și, la fel de important, ce nu este. „Un router, făcut bine. Fără agenți, fără controller, fără flotă."
- Arhitectura — componente, granițe, cine cu cine comunică
- Modelul de date — definiții reale de tabele, nu impresii
- Milestone-uri — fiecare livrabil de sine stătător
- Non-obiective explicite — funcționalitățile pe care în mod deliberat nu le construim
Regula pentru milestone-uri din planul lui birdy este cea pe care o aplicăm acum peste tot:
Fiecare milestone este utilizabil de sine stătător și nu poate strica nimic din ce cel anterior nu atinsese deja.
Pentru birdy asta a însemnat: este un viewer read-only în care poți avea încredere înainte să scrie vreodată o configurație. Ordinea nu a fost întâmplătoare — ne-a permis să punem un tool beta pe un router real încă de la primul milestone, pentru că primul milestone nu putea strica nimic.
De ce un document și nu o conversație? Pentru că o conversație este efemeră, iar un document este durabil. Agenții pierd contextul între sesiuni; un PLAN.md în repo înseamnă că fiecare sesiune pornește de la același adevăr de referință. Un document de design este pur și simplu un prompt mai bun: este versionat, poate fi revizuit și ne obligă pe noi să decidem lucrurile grele — modelul de obiecte, semantica de siguranță — înainte să înceapă generarea, în loc să lăsăm agentul să le decidă din întâmplare, la mijlocul unui diff.
Guardrail-urile
Agentul lucrează în interiorul unui gard. Gardul este plictisitor, și tocmai asta e ideea:
- CI la fiecare modificare. Build, vet, lint, suita completă de teste. Agentul trebuie să lase CI-ul verde; un pipeline roșu înseamnă respingere automată, fără discuție.
- Linterele și formatterele ca lege. Dezbaterile de stil cu un agent sunt vorbe în vânt. Codifică regulile; tool-urile le impun gratuit.
- Agentul scrie teste odată cu codul. Apoi noi revizuim testele mai atent decât codul, pentru că un agent poate scrie cod cu formă de test care nu verifică nimic. (Mai multe despre asta în ghidul nostru practic pentru review-ul codului scris de AI.)
- Diff-uri mici, întotdeauna. O felie de milestone, o modificare care poate fi revizuită. Când un agent produce un diff de 2.000 de linii, nu îl revizuim eroic — îl respingem și tăiem task-ul mai mic.
- Fără secrete în buclă. Agenții primesc medii de dezvoltare și fixture-uri, niciodată credențiale de producție. Când agenții chiar trebuie să atingă infrastructură reală, accesul respectiv este proiectat deliberat — un subiect suficient de mare încât am scris despre el separat, în cum dăm agenților AI acces la infrastructură reală.
Împărțirea muncii
Formularea curată: agentul scrie, omul decide.
Exemplul concret la care revenim mereu este auto-revert-ul armat. Atât nftably, cât și birdy aplică configurații pe o mașină live — un firewall, un router BGP — prin care de obicei ești conectat tu însuți. O regulă greșită te blochează afară; un filtru BGP greșit te scoate de pe internet. Așa că ambele tool-uri aplică modificările ca o tranzacție atomică, cu un timer armat: dacă nu confirmi în fereastra de timp, mașina revine singură la ultima configurație bună.
Niciun agent nu a propus asta. A venit de la un om care a editat nftables de mână prin SSH și a simțit frica aceea specifică de a apăsa Enter. Agentul a implementat-o apoi — mașina de stări, timerul, calea de rollback, testele — rapid și bine. Asta e împărțirea muncii într-o singură funcționalitate: semantica de siguranță este o decizie de design luată de cineva cu cicatrici; implementarea este muncă la care agentul e cu adevărat bun.
Aceeași separare s-a păstrat peste tot: oamenii au deținut modelul de date, regulile de proprietate asupra configurației („acest tool deține întregul fișier pe care îl generează"), decizia de a refuza generarea configurațiilor care arată a route leak. Agenții au deținut CRUD-ul, rendererele, plumbing-ul de UI, packaging-ul și sincronizarea documentației.
Încheie fiecare sesiune actualizând planul
Contextul agentului moare când se termină sesiunea. Repo-ul este singura memorie care supraviețuiește. Așa că ultimul act al fiecărei sesiuni de lucru este actualizarea planului și a documentației: ce s-a livrat, ce a deviat de la design, ce urmează. Sesiunea următoare — agent sau om — începe citind-o.
Asta te ține și onest în privința deviațiilor. Planul lui birdy poartă acum o notă care listează tot ce s-a livrat altfel decât în design. Nota aceea este o funcționalitate, nu o rușine: planul este o consemnare a intenției, iar diferența dintre intenție și realitate este locul unde trăiește judecata inginerească.
Când agentul o ia razna
O va face. Mirosul eșecului este mereu același: complexitate în creștere fără progres în creștere — un diff care tot crește, editări tot mai ciudate, cazuri speciale stivuite peste cazuri speciale. Ce funcționează:
- Fă revert devreme. În clipa în care o sesiune miroase a greșit, aruncă diff-ul. Codul de agent este ieftin de regenerat; asta schimbă economia revert-ului. Raționamentul de tip sunk-cost despre cod generat este un bug în tine.
- Re-specifică, nu te certa. Un agent care se chinuie într-un fir lung a fost de obicei otrăvit de propriul context. Cearta cu el adaugă și mai mult context prost. Resetează, îmbunătățește descrierea task-ului cu ce ai învățat, pornește curat.
- Taie task-ul mai mic. De nouă ori din zece, „agentul nu poate face asta" înseamnă „task-ul era de fapt două task-uri".
- Ia-l înapoi. Unele probleme — concurență subtilă, un algoritm cu adevărat nou — sunt mai rapid de scris de mână decât de specificat. Să știi care e care este de fapt abilitatea.
Workflow-ul, ca listă de verificare
- Omul scrie PLAN.md — arhitectură, model de date, milestone-uri, non-obiective
- Milestone-uri ordonate după încredere — fiecare utilizabil de sine stătător, niciunul nu-l poate strica pe cel dinainte
- CI, lintere și teste ca porți stricte — agentul le ține verzi sau diff-ul moare
- Agentul scrie, omul decide — semantica de siguranță și modelele de obiecte nu se deleagă niciodată
- Diff-uri mici, review real — respinge și re-taie în loc să revizuiești eroic diff-uri mari
- Actualizează planul la finalul sesiunii — repo-ul este singura memorie care supraviețuiește
- Revert devreme, re-specifică, nu te certa — codul generat e ieftin; timpul tău nu e
Am ajuns aici livrând — și făcând greșelile de început pe propriile noastre tool-uri, nu pe ale unui client. Dacă preferi să sari peste partea asta, ajutăm echipele să pună pe picioare dezvoltarea agentică cu aceste guardrail-uri deja la locul lor. Hai să vorbim.