G.STANCUTA
Publicat · 2026 · 01 · 308 min de citit

Conduce Agentul: Cum să livrezi cu adevărat cod în producție cu AI

  • ai-agents
  • developer-tools
  • workflow
  • field-notes

Agentul AI nu este operatorul. Tu ești. Iată modelul mental, arhitectura memoriei și disciplina de verificare care transformă o sesiune haotică cu un LLM într-o buclă de livrare fiabilă.

Toată lumea vrea să vorbească despre ce poate face modelul. Nimeni nu vrea să vorbească despre partea care determină cu adevărat dacă codul este livrat: operatorul. Acela ești tu. Agentul este un executor foarte capabil, fără memorie pe termen lung, fără conștientizare situațională și fără niciun interes dacă pull request-ul funcționează. Tu le ai pe toate trei. În momentul în care uiți asta, începi să produci resturi la scară în loc de software.

Livrez cod în producție cu agenți AI de programare de suficient timp cât să am un sistem repetabil. Nu este magie. Este disciplină aplicată unui nou tip de unealtă.

Diagramă izometrică a unui operator uman care conduce un agent AI printr-o conductă de sarcini descompuse
Operatorul modelează fiecare pas. Agentul execută.

Specificație, nu dorință

Calitatea rezultatului tău este limitată de calitatea intrării tale. Nu este o metaforă, este un fapt mecanic despre cum funcționează modelele de limbaj. Prompt-urile vagi produc cod vag. O dorință sună astfel: "adaugă autentificare în aplicație." O specificație sună astfel: "implementează autentificarea bazată pe JWT folosind modelul User existent din src/models/user.ts, protejează toate rutele de sub /api/v1/ cu excepția /api/v1/auth/login și /api/v1/auth/refresh, stochează refresh token-ul într-un cookie HTTP-only și scrie unit teste pentru middleware în src/middleware/__tests__/auth.test.ts."

Diferența nu este de stil. Este densitate de semnal. Fiecare constrângere pe care o omiți este o decizie pe care agentul o ia în locul tău, iar agentul nu are nicio idee cum arată arhitectura ta, ce a convenit echipa ta marți trecută sau ce bibliotecă terță ai interzis acum șase luni. Tu știi. Pune-o în prompt.

Descompune în pași verificabili

Sarcinile agentice lungi eșuează la granița dintre subsarcini. Agentul pierde firul, halucinează un import sau schimbă silențios interfața pe care ar fi trebuit să o păstreze. Soluția este descompunerea: împarte munca în pași în care fiecare pas are o condiție de ieșire clară și verificabilă.

Nu "construiește funcționalitatea." În schimb: (1) scrie stratul de date cu tipuri și teste, oprește-te, (2) scrie stratul de servicii împotriva acelor tipuri, oprește-te, (3) conectează handler-ul HTTP, oprește-te, (4) rulează întreaga suită de teste și raportează eșecurile. Fiecare oprire este un punct de control în care inspectezi rezultatul înainte de a continua. Tu ești orchestratorul. Tu decizi când pasul N este suficient de bun pentru a începe pasul N+1.

  1. 01Definește mai întâi contractul de date (tipuri, schemă, fixture-uri).
  2. 02Implementează logica de bază împotriva acelui contract.
  3. 03Conectează stratul de integrare (HTTP, event bus, CLI).
  4. 04Verifică într-un pas separat cu o fereastră de context proaspătă.

Menținând pașii mici, menții și fereastra de context curată. O modificare de 200 de linii este revizuibilă. Una de 2000 de linii este un risc.

Arhitectura trăiește în mintea ta (și în Markdown)

Iată adevărul brutal despre agenții AI de programare: nu au memorie între sesiuni. Agentul care ți-a scris middleware-ul de autentificare ieri nu știe astăzi că există. Va inventa cu plăcere un alt pattern, va importa o bibliotecă conflictuală sau va viola convenția pe care ai stabilit-o, nu pentru că este neglijent, ci pentru că nu i-ai spus niciodată.

Aici fișierele markdown de memorie devin cea mai importantă parte a stivei tale. Nu prompt-uri inteligente. Nu mesaje de sistem. Fișiere markdown persistente și versioniate care trăiesc în repository și sunt încărcate în context la începutul fiecărei sesiuni. Agentul le citește și dintr-odată are cunoștințele instituționale pe care altfel le-ar lipsi.

Fișierul markdown nu este documentație pentru oameni. Este memoria de lucru a agentului. Scrie-l în consecință.

Pattern-ul este simplu: un AGENTS.md la rădăcina proiectului, cu secțiuni pentru decizii arhitecturale, convenții de denumire, comenzi de rulat, pattern-uri interzise și capcane cunoscute. Menține-l actualizat pe măsură ce codul evoluează. Tratează-l cu aceeași disciplină cu care ai trata un README.md care afectează cu adevărat comportamentul la runtime, pentru că în fluxul tău de lucru AI, o face.

md
# AGENTS.md — Project Memory for AI Coding Agents

## Architecture

- Monorepo: apps/web (Next.js), apps/api (Hono on Bun), packages/shared (types + utils)
- Database: Postgres via Drizzle ORM. Schema lives in packages/db/schema.ts.
- Auth: JWT in Authorization header for API, HTTP-only cookie for web client. Use the helpers in packages/shared/src/auth.ts — do NOT roll your own.
- State: Zustand stores in apps/web/src/stores/. No Redux, no Context API for app state.

## Conventions

- File naming: kebab-case for files, PascalCase for components/classes.
- All API routes return { data, error, meta } — use the ResponseEnvelope type from packages/shared.
- Services live in src/services/, handlers in src/handlers/. Services contain business logic, handlers do HTTP concerns only.
- Tests co-located: src/services/__tests__/auth-service.test.ts next to src/services/auth-service.ts.

## Commands

```bash
bun run dev          # start all apps in parallel
bun run test         # run full test suite
bun run db:migrate   # apply pending migrations
bun run typecheck    # tsc --noEmit across all packages
```

## Forbidden Patterns

- Do NOT use `any` in TypeScript. Use `unknown` and narrow.
- Do NOT import from `apps/api` in `apps/web` or vice versa. Use packages/shared.
- Do NOT use `console.log` in production code. Use the logger in packages/shared/src/logger.ts.

## Known Gotchas

- Drizzle's `db.query.*` API requires the relational schema to be passed at client init time. See packages/db/client.ts.
- Hono middleware runs in declaration order. Auth middleware must be registered before route handlers.
- The web app uses the App Router. Do not use getServerSideProps or pages/api — those are dead.

Acel fișier este încărcat la începutul fiecărei sesiuni a agentului. Agentul cunoaște acum pattern-urile interzise, locațiile helper-elor, convenția de denumire a fișierelor de test și comenzile de rulat. Acționează pe baza acestor cunoștințe în mod fiabil pentru că le citește, nu le deduce din structura codului.

Verifică într-un pas separat

Aceasta este regula pe care cei mai mulți o sar, și este cea care îi costă cel mai mult. Nu cere aceluiași context de agent care a scris codul să îl și verifice. Contextul este părtinitor. Agentul are un model al a ceea ce a intenționat să scrie, iar acel model îl va face să rateze ceea ce a scris de fapt.

Pornește o sesiune nouă. Încarcă AGENTS.md. Încarcă diff-ul sau fișierele modificate. Dă agentului un prompt de verificare: "Revizuiește următoarele modificări față de convențiile din AGENTS.md. Raportează orice încălcări, teste lipsă, erori de tip și bug-uri logice. Nu sugera îmbunătățiri, raportează doar eșecurile." Contextul proaspăt nu are nicio atașare față de munca anterioară. Citește ceea ce este cu adevărat acolo.

Schemă a unei bucle de verificare în două etape: sesiunea de scriere și sesiunea de verificare separată, conectate printr-un fișier markdown de memorie
Pasul de scriere și pasul de verificare împart o singură sursă de adevăr: fișierul markdown de memorie.

Asociază asta cu un pas de verificare automatizat pe care agentul îl poate rula singur. Bucla de mai jos nu este ingenioasă, este pur și simplu disciplinată:

ts
// scripts/verify-loop.ts
// Run with: bun run scripts/verify-loop.ts
// Iterates: typecheck → test → lint. Prints first failure and exits.

import {execSync} from 'child_process';

const steps = [
  {name: 'typecheck', cmd: 'bun run typecheck'},
  {name: 'test',      cmd: 'bun run test --bail'},
  {name: 'lint',      cmd: 'bun run lint'},
] as const;

for (const step of steps) {
  console.log(`\n--- ${step.name} ---`);
  try {
    execSync(step.cmd, {stdio: 'inherit'});
    console.log(`${step.name}: PASS`);
  } catch {
    console.error(`${step.name}: FAIL — stopping.`);
    process.exit(1);
  }
}

console.log('\nAll checks passed.');

Agentul rulează acest script după fiecare modificare non-trivială. Dacă eșuează, agentul îți raportează eșecul. Tu decizi dacă iterezi sau faci rollback. Script-ul este determinist. Agentul nu face judecăți despre dacă testele "trec mai mult sau mai puțin".

Păstrează arhitectura în mintea ta

Fișierul markdown descarcă convențiile și comenzile. Nu descarcă judecata arhitecturală. Trebuie să știi în continuare de ce există stratul de servicii, de ce autentificarea se află într-un pachet partajat, de ce ai ales Drizzle în locul Prisma. Agentul poate urma pattern-uri. Nu poate raționa despre dacă pattern-urile sunt încă adecvate pentru problema pe care o rezolvi acum.

Când o sarcină necesită o decizie arhitecturală, ia-o tu înainte de a deschide sesiunea cu agentul. Scrie decizia în AGENTS.md înainte de a cere agentului să o implementeze. Secvența este: tu decizi, tu documentezi, agentul implementează. Nu: agentul implementează, tu descoperi decizia luată și fie o accepți, fie o anulezi.

  • Tu deții graful de dependențe. Agentul nu știe ce costă adăugarea unui nou pachet.
  • Tu deții modelul de date. Modificările de schemă sunt greu de inversat. Nu le delega niciodată fără o specificație scrisă.
  • Tu deții granița de securitate. Agentul va implementa orice flux de autentificare descrii, inclusiv pe cele greșite.
  • Tu deții release-ul. Agentul nu are niciun interes dacă producția rămâne activă.

Bucla în practică

O sesiune reală arată astfel. Identifici o sarcină. Scrii o specificație cu suficiente constrângeri astfel încât agentul să nu aibă ambiguitate cu privire la locațiile fișierelor, limitele interfețelor și criteriile de acceptare. Încarci AGENTS.md și fișierele sursă relevante. Îi dai agentului pasul unu din munca descompusă. Produce un rezultat. Îl citești. Dacă este bun, treci la pasul doi. Când toți pașii sunt finalizați, pornești o sesiune nouă pentru pasul de verificare. Verificatorul raportează eșecurile. Trimiți eșecurile înapoi la contextul de implementare sau le corectezi tu însuți.

Întreaga buclă este poate cu treizeci la sută mai lentă decât a da prompt-uri la întâmplare și a spera. Produce cod care nu te jenează la review și nu te trezește la 3 dimineața.

Schimbarea în modelul mental este simplă: încetează să întrebi ce poate face modelul și începe să întrebi ce oferi tu, ca operator. Calitatea specificației, calitatea descompunerii, calitatea fișierului de memorie, disciplina de verificare. Acestea sunt variabilele pe care le controlezi. Controlează-le, și agentul devine un adevărat multiplicator de forță. Ignoră-le, și ai un autocomplete scump.

Portofoliu · Indicator
Desenat de
G. STANCUTA
Disciplină
AI & AUTOMATION
Locație
MORTER · SÜDTIROL
Stare
Disponibil
Limbi
IT · EN · RO · DE+
Stack
PLOI · HETZNER
Revizie
REV 2026.A
2026

© 2026 Gabriel Stancuta · jumpinotech.com — Proiectat cu AI, construit să funcționeze singur.