Ingegneria dell'harness: usare Codex in un mondo agent-first
Di Ryan Lopopolo, membro dello staff tecnico
Negli ultimi cinque mesi, il nostro team ha condotto un esperimento: sviluppare e distribuire una beta interna di un prodotto software con zero righe di codice scritte manualmente.
Il prodotto ha utenti interni giornalieri e tester alpha esterni. Viene rilasciato, distribuito, si rompe e viene corretto. La differenza è che tutte le righe di codice, inclusa la logica dell'applicazione, i test, la configurazione della CI, la documentazione, l'osservabilità e gli strumenti interni, sono state generate da Codex. Stimiamo di averlo fatto in circa un decimo del tempo che sarebbe stato necessario per scrivere il codice a mano.
Gli umani guidano. Gli agenti eseguono.
Abbiamo scelto intenzionalmente questo vincolo per costruire solo ciò che era necessario a incrementare la velocità di sviluppo di ordini di grandezza. Abbiamo avuto settimane per consegnare quello che alla fine si è rivelato essere un milione di righe di codice. Per farlo, dovevamo capire cosa cambia quando il compito principale di un team di ingegneria del software non è più scrivere codice, ma progettare ambienti, specificare l'intento e costruire cicli di feedback che permettano agli agenti Codex di svolgere un lavoro affidabile.
Questo post illustra ciò che abbiamo imparato costruendo un prodotto completamente nuovo con un team di agenti: cosa non ha funzionato, cosa si è amplificato e come massimizzare ciò che davvero scarseggia: il tempo e l'attenzione umana.
Il primo commit in un repository vuoto è stato effettuato alla fine di agosto 2025.
Lo scaffold iniziale (struttura del repository, configurazione CI, regole di formattazione, configurazione del package manager e framework dell'applicazione) è stato generato da Codex CLI usando GPT‑5, a partire da un piccolo insieme di template preesistenti. Persino il file AGENTS.md iniziale, che istruisce gli agenti su come operare nel repository, è stato scritto da Codex stesso.
Non c'era alcun codice preesistente scritto da esseri umani su cui ancorare il sistema. Fin dall'inizio, il repository è stato modellato dall'agente.
Cinque mesi dopo, il repository contiene circa un milione di righe di codice tra logica dell'applicazione, infrastruttura, strumenti, documentazione e strumenti interni per sviluppatori. In quel periodo, sono state aperte e integrate circa 1.500 pull request, con un piccolo team di soli tre ingegneri a guidare Codex. Questo si traduce in una capacità media di elaborare 3,5 PR al giorno per ingegnere e, sorprendentemente, tale capacità è aumentata con la crescita del team fino a sette ingegneri. È importante sottolineare che non si è trattato di output fine a sé stesso: il prodotto è stato utilizzato internamente da centinaia di utenti, inclusi utenti esperti interni che lo usano quotidianamente.
Durante l'intero processo di sviluppo, gli esseri umani non hanno mai contribuito direttamente con alcun codice. Questa è diventata una filosofia centrale per il team: nessun codice scritto manualmente.
La mancanza di programmazione manuale ha portato a un nuovo tipo di lavoro ingegneristico, focalizzato sui sistemi, sulla struttura del progetto e sull'ottimizzazione delle risorse.
I progressi iniziali sono stati più lenti di quanto ci aspettassimo, non perché Codex non fosse capace, ma perché l'ambiente era sottospecificato. All'agente mancavano gli strumenti, le astrazioni e la struttura interna necessari per avanzare verso obiettivi di alto livello. Il compito principale del nostro team di ingegneria è diventato quello di consentire agli agenti di svolgere un lavoro utile.
In pratica, questo significava lavorare in profondità: scomporre obiettivi più ampi in blocchi costitutivi più piccoli (design, codice, revisione, test, ecc.), sollecitando l'agente a costruire tali blocchi e utilizzandoli per rendere possibili compiti più complessi. Quando qualcosa andava storto, la soluzione raramente era “metterci più impegno“. Poiché l'unico modo per fare progressi era far sì che Codex svolgesse il lavoro, gli ingegneri umani intervenivano nel compito e chiedevano: “quale capacità manca e come facciamo a renderla al tempo stesso leggibile e applicabile per l'agente?“.
Gli esseri umani interagiscono con il sistema quasi esclusivamente tramite prompt: un ingegnere descrive un'attività, esegue l'agente e gli permette di aprire una pull request. Per completare una PR, istruiamo Codex a: rivedere le proprie modifiche localmente, richiedere ulteriori revisioni specifiche da parte di agenti, sia localmente che nel cloud, rispondere a qualsiasi feedback fornito da un essere umano o da un agente, e iterare in un ciclo finché tutti gli agenti revisori non sono soddisfatti. Questo è noto come Ralph Wiggum Loop(si apre in una nuova finestra). Codex utilizza direttamente i nostri strumenti di sviluppo standard (gh, script locali e competenze incorporate nel repository) per raccogliere il contesto senza che le persone debbano copiare e incollare nella CLI.
Le persone possono revisionare le pull request, ma non sono obbligate a farlo. Nel tempo, abbiamo indirizzato quasi tutto lo sforzo di revisione verso una gestione tra agenti.
Con l'aumento della capacità di elaborazione del codice, il limite principale è diventato la capacità di QA umana. Poiché il vero limite è rappresentato dal tempo e dall'attenzione umana, abbiamo lavorato per aggiungere più capacità all'agente rendendo elementi come l'interfaccia utente dell'applicazione, i log e le metriche dell'app direttamente leggibili da Codex.
Per esempio, abbiamo reso l'app avviabile per git worktree, in modo che Codex potesse lanciare e gestire un'istanza per ogni modifica. Abbiamo anche integrato il protocollo Chrome DevTools nel runtime dell'agente e creato competenze per lavorare con istantanee del DOM, screenshot e navigazione. Questo ha permesso a Codex di riprodurre i bug, convalidare le correzioni e ragionare direttamente sul comportamento dell'interfaccia utente.

Abbiamo fatto lo stesso per gli strumenti di osservabilità. I log, le metriche e le tracce sono esposti a Codex tramite uno stack di osservabilità locale che è effimero per qualsiasi worktree. Codex opera su una versione completamente isolata di quell'app, inclusi i suoi log e le sue metriche, che vengono eliminati una volta completato il compito. Gli agenti possono interrogare i log con LogQL e le metriche con PromQL. Con questo contesto disponibile, prompt come “assicurati che l'avvio del servizio si completi in meno di 800 ms“ o “nessuno span in questi quattro percorsi utente critici supera i due secondi“ diventano gestibili.
Vediamo regolarmente singole esecuzioni di Codex lavorare su un'unica attività per più di sei ore (spesso mentre le persone dormono).
Gestire il contesto è una delle difficoltà principali quando si vuole rendere gli agenti realmente efficaci in compiti ampi e complessi. Uno dei primi insegnamenti che abbiamo appreso è stato semplice: dare a Codex una mappa, non un manuale di istruzioni di 1.000 pagine.
Abbiamo provato l'approccio “one big AGENTS.md(si apre in una nuova finestra)” che ha fallito in modi prevedibili:
- Il contesto è una risorsa limitata. Un file di istruzioni enorme sovrasta l'attività, il codice e la documentazione pertinente, quindi l'agente o perde i vincoli chiave o inizia a ottimizzare quelli sbagliati.
- Un eccesso di indicazioni finisce per diventare assenza di guida. Quando tutto è “importante”, nulla lo è. Gli agenti finiscono per fare pattern matching a livello locale invece di navigare con uno scopo preciso.
- Si deteriora subito. Un manuale monolitico si trasforma in un cimitero di regole stantie. Gli agenti non sanno cosa sia ancora corretto, le persone smettono di aggiornarlo, e il file finisce per diventare un'inutile tentazione.
- È difficile da verificare. Un singolo blob non si presta a controlli meccanici (copertura, aggiornamento, proprietà, collegamenti incrociati), quindi la deriva è inevitabile.
Quindi, invece di trattare AGENTS.md come l'enciclopedia, lo trattiamo come l'indice.
La knowledge base del repository si trova in una directory strutturata docs/, considerata come sistema di riferimento. Un breve AGENTS.md (circa 100 righe) viene inserito nel contesto e funge principalmente da mappa, con riferimenti a fonti di verità più approfondite altrove.
La documentazione di progettazione è catalogata e indicizzata, incluso lo stato di verifica e un insieme di convinzioni fondamentali che definiscono i principi operativi agent-first. La documentazione dell'architettura(si apre in una nuova finestra) fornisce una mappa di primo livello dei domini e della stratificazione dei pacchetti. Un documento di qualità valuta ogni dominio di prodotto e livello architettonico, monitorando le lacune nel tempo.
I piani sono considerati artefatti di primaria importanza. I piani effimeri e leggeri vengono utilizzati per piccole modifiche, mentre il lavoro complesso viene documentato in piani di esecuzione(si apre in una nuova finestra) con registri di avanzamento e decisioni che vengono archiviati nel repository. I piani attivi, i piani completati e il debito tecnico noto sono tutti versionati e co-localizzati, permettendo agli agenti di operare senza fare affidamento sul contesto esterno.
Grazie alla divulgazione progressiva, gli agenti iniziano con un punto di accesso ridotto e stabile e imparano gradualmente dove focalizzarsi, evitando di essere subito travolti da troppe informazioni.
Lo applichiamo meccanicamente. I linter dedicati e i processi di CI verificano che la knowledge base sia aggiornata, collegata in modo incrociato e strutturata correttamente. Un agente ricorrente di “doc-gardening“ esegue una scansione per individuare documentazione obsoleta o non aggiornata che non riflette il comportamento reale del codice e apre pull request di correzione.
Con la progressiva evoluzione del codebase, anche il framework di Codex per le scelte di progettazione ha dovuto evolversi.
Poiché il repository è interamente generato da un agente, è ottimizzato innanzitutto per la leggibilità di Codex. Allo stesso modo in cui i team puntano a migliorare la navigabilità del loro codice per i nuovi ingegneri assunti, l'obiettivo dei nostri ingegneri umani era rendere possibile per un agente ragionare sull'intero dominio aziendale direttamente dal repository stesso.
Dal punto di vista dell'agente, qualsiasi cosa a cui non può accedere nel contesto mentre è in esecuzione, di fatto non esiste. Le conoscenze che si trovano in Google Docs, nelle conversazioni o nella mente delle persone non sono accessibili al sistema. Gli artefatti locali al repository e versionati (ad esempio codice, Markdown, schemi, piani eseguibili) sono tutto ciò che può vedere.

Abbiamo imparato che nel tempo dovevamo inserire sempre più contesto nel repository. Quella discussione su Slack che ha messo d'accordo il team su un pattern architetturale? Se l'agente non riesce a individuarla, è illeggibile, proprio come lo sarebbe per un nuovo assunto che entra nel team tre mesi dopo la discussione.
Fornire a Codex più contesto significa organizzare e rendere disponibili le informazioni corrette affinché l'agente possa ragionarci sopra, piuttosto che sovraccaricarlo con istruzioni ad hoc. Allo stesso modo in cui introdurresti un nuovo membro del team ai principi di prodotto, alle norme ingegneristiche e alla cultura del team (incluse le preferenze sulle emoji), fornire queste informazioni all'agente genera un output più coerente.
Questa struttura ha chiarito molti compromessi. Abbiamo privilegiato dipendenze e astrazioni che potessero essere completamente internalizzate e ragionate all'interno del repository. Le tecnologie spesso descritte come “noiose“ risultano più facili da modellare per gli agenti, grazie alla loro componibilità, alla stabilità delle API e alla presenza nei dati di addestramento. In alcuni casi, era più conveniente che l'agente reimplementasse sottoinsiemi di funzionalità piuttosto che aggirare il comportamento opaco a monte delle librerie pubbliche. Ad esempio, invece di utilizzare un pacchetto generico in stile p-limit, abbiamo sviluppato un nostro helper per la mappatura con concorrenza: è strettamente integrato con la nostra strumentazione OpenTelemetry, ha una copertura dei test del 100% e si comporta esattamente come si aspetta il nostro runtime.
Portare una porzione maggiore del sistema in una forma che l'agente possa ispezionare, convalidare e modificare direttamente aumenta la leva, non solo per Codex, ma anche per altri agenti (ad esempio Aardvark) che lavorano sullo stesso codebase.
La sola documentazione non basta a mantenere coerente un codebase generato interamente da agenti. Facendo rispettare gli invarianti, senza microgestire le implementazioni, permettiamo agli agenti di rilasciare velocemente senza compromettere le basi. Ad esempio, richiediamo a Codex di interpretare le strutture dei dati al confine(si apre in una nuova finestra), ma non siamo prescrittivi su come ciò debba avvenire (il modello sembra preferire Zod, ma non abbiamo specificato quella libreria in particolare).
Gli agenti sono più efficaci in ambienti con confini rigorosi e una struttura prevedibile(si apre in una nuova finestra), quindi abbiamo sviluppato l'applicazione attorno a un modello architettonico rigido. Ogni dominio aziendale è suddiviso in un insieme fisso di livelli, con direzioni di dipendenza rigorosamente convalidate e un insieme limitato di connessioni consentite. Questi vincoli sono applicati meccanicamente tramite linter personalizzati (generati da Codex, ovviamente!) e test strutturali.
Il diagramma sottostante mostra la regola: all'interno di ciascun dominio aziendale (ad es. Impostazioni app), il codice può dipendere solo “in avanti“ attraverso un insieme fisso di livelli (Types → Config → Repo → Service → Runtime → UI). Gli aspetti trasversali (autenticazione, connettori, telemetria, feature flag) passano attraverso un'unica interfaccia esplicita: i Provider. Qualsiasi altra cosa è vietata e viene applicata meccanicamente.

In genere, questo tipo di architettura viene implementato solo quando il team raggiunge centinaia di ingegneri. Con gli agenti di programmazione, è un prerequisito iniziale: i vincoli sono ciò che permette la velocità senza decadimento o deriva architettonica.
In pratica, applichiamo queste regole tramite linter personalizzati e test strutturali, affiancati da un piccolo insieme di “invarianti di stile“. Ad esempio, applichiamo in modo statico la registrazione strutturata, le convenzioni di denominazione per schemi e tipi, i limiti delle dimensioni dei file e i requisiti di affidabilità specifici della piattaforma con linter personalizzati. Poiché i linter sono personalizzati, scriviamo i messaggi di errore in modo da fornire all'agente istruzioni di correzione contestualizzate.
In un flusso di lavoro incentrato sulle persone, queste regole potrebbero sembrare pedanti o restrittive. Con gli agenti, diventano moltiplicatori: una volta codificate, si applicano ovunque contemporaneamente.
Allo stesso tempo, specifichiamo chiaramente dove i vincoli contano e dove invece non sono rilevanti. È simile a guidare una grande piattaforma ingegneristica: imporre regole e limiti a livello centrale, lasciando però autonomia a livello locale. In questi casi si presta grande attenzione a confini, correttezza e riproducibilità. Entro questi limiti, permetti ai team o agli agenti una notevole libertà nel modo in cui le soluzioni vengono espresse.
Il codice risultante non sempre corrisponde alle preferenze stilistiche umane, e va bene così. Finché l'output è corretto, manutenibile e leggibile per le future esecuzioni dell'agente, soddisfa il livello richiesto.
Il gusto umano viene costantemente restituito al sistema come feedback. I commenti di revisione, le pull request di refactoring e i bug visibili agli utenti vengono acquisiti come aggiornamenti della documentazione o codificati direttamente negli strumenti. Quando la documentazione è insufficiente, trasformiamo la regola in codice.
Con l'aumento della capacità di elaborazione di Codex, molte norme ingegneristiche convenzionali sono diventate controproducenti.
Il repository funziona con pochi meccanismi di blocco per le merge, così le integrazioni procedono rapidamente. Le pull request sono di breve durata. I test instabili vengono spesso affrontati con esecuzioni successive anziché bloccare i progressi a tempo indeterminato. In un sistema in cui la capacità di elaborazione dell'agente supera di gran lunga l'attenzione umana, le correzioni sono economiche e l'attesa è costosa.
Questo sarebbe irresponsabile in un ambiente a bassa capacità di elaborazione. Qui, spesso è il giusto compromesso.
Quando diciamo che la codebase è generata dagli agenti Codex, ci riferiamo a tutto ciò che è presente nella codebase.
Gli agenti producono:
- Codice prodotto e test
- Configurazione CI e strumenti di rilascio
- Strumenti interni per sviluppatori
- Documentazione e cronologia di progettazione
- Strumenti di valutazione
- Commenti e risposte alla revisione
- Script che gestiscono il repository stesso
- File di definizione della dashboard di produzione
Gli esseri umani fanno sempre parte del processo, ma operano a un livello di astrazione diverso rispetto a prima. Diamo priorità al lavoro, traduciamo il feedback degli utenti in criteri di accettazione e convalidiamo i risultati. Quando l'agente si trova in difficoltà, lo interpretiamo come un segnale e identifichiamo ciò che manca (strumenti, misure di sicurezza o documentazione) quindi lo reinseriamo nel repository, facendo sempre scrivere a Codex stesso la correzione.
Gli agenti usano direttamente i nostri strumenti di sviluppo standard. Recuperano il feedback di revisione, rispondono in linea, eseguono il push degli aggiornamenti e spesso eseguono squash e merge delle proprie pull request.
Man mano che una porzione sempre maggiore del ciclo di sviluppo (test, validazione, revisione, gestione dei feedback e recupero) è stata codificata direttamente nel sistema, il repository ha recentemente superato una soglia significativa: Codex ora è in grado di gestire l'intero processo di implementazione di una nuova funzionalità.
Dato un singolo prompt, l'agente ora può:
- Verificare lo stato attuale della codebase
- Riprodurre un bug segnalato
- Registrare un video che dimostri il malfunzionamento
- Implementare una soluzione
- Convalidare la correzione guidando l'applicazione
- Registrare un secondo video che dimostri la risoluzione
- Aprire una pull request
- Rispondere ai feedback dell'agente e a quelli umani
- Rilevare e correggere gli errori di compilazione
- Inoltrare a un essere umano solo quando è necessario il giudizio
- Unire la modifica
Questo comportamento dipende fortemente dalla struttura e dagli strumenti specifici di questo repository e non dovrebbe essere considerato generalizzabile senza un investimento simile, almeno per ora.
L'autonomia completa dell'agente introduce anche problemi nuovi. Codex replica modelli che esistono già nel repository, anche quelli irregolari o non ottimali. Nel tempo, questo porta inevitabilmente a una deriva.
Inizialmente, le persone si occupavano di questo manualmente. Il nostro team passava ogni venerdì (20% della settimana) a smaltire “i rifiuti dell'IA“. Quindi non sorprende che non fosse scalabile.
Abbiamo invece iniziato a codificare quelli che chiamiamo “principi d’oro” direttamente nel repository, creando anche un processo ricorrente di pulizia. Questi principi sono regole prescrittive e operative che mantengono il codebase leggibile e coerente per le future esecuzioni dell’agente. Ad esempio: (1) privilegiamo pacchetti di utilità condivisi rispetto ad helper scritti ad hoc, per mantenere gli invarianti centralizzati; e (2) evitiamo di interrogare i dati in stile “YOLO”: definiamo e convalidiamo esplicitamente i confini, oppure ci affidiamo a SDK tipizzati, così l'agente non può basarsi accidentalmente su strutture solo presunte. Con cadenza regolare, disponiamo di un insieme di attività Codex in background che analizzano le deviazioni, aggiornano i punteggi di qualità e aprono pull request di refactoring mirate. La maggior parte può essere revisionata in meno di un minuto e unita automaticamente.
Funziona come la raccolta dei rifiuti. Il debito tecnico è come un prestito ad alto interesse: è quasi sempre meglio ripagarlo poco alla volta, invece di lasciarlo accumulare e doverlo saldare in rate dolorose Il gusto umano viene acquisito una volta, poi applicato continuamente a ogni riga di codice. Questo ci permette anche di individuare e risolvere quotidianamente schemi problematici, invece di lasciare che si diffondano nella base di codice per giorni o settimane.
Finora questa strategia ha funzionato bene fino al lancio interno e all'adozione presso OpenAI. Costruire un prodotto reale per utenti reali ci ha aiutato ad ancorare i nostri investimenti alla realtà e a guidarci verso la sostenibilità a lungo termine.
Ciò che ancora non sappiamo è come la coerenza architettonica si evolva nel corso degli anni in un sistema completamente generato da agenti. Stiamo ancora imparando in quali ambiti il giudizio umano offre il massimo vantaggio e come codificarlo per amplificarne l'effetto. Inoltre, non sappiamo come questo sistema si evolverà man mano che i modelli acquisiranno capacità col passare del tempo.
È chiaro che sviluppare software richiede ancora disciplina, ma questa si manifesta più nell'impalcatura che nel codice. Gli strumenti, le astrazioni e i cicli di feedback che mantengono coerente il codice sono sempre più importanti.
Le nostre sfide più difficili ora si concentrano sulla progettazione di ambienti, cicli di feedback e sistemi di controllo che aiutano gli agenti a raggiungere il nostro obiettivo: creare e mantenere software complesso e affidabile su larga scala.
Man mano che agenti come Codex si fanno carico di porzioni sempre più ampie del ciclo di vita del software, queste questioni diventeranno ancora più importanti. Speriamo che la condivisione di alcune delle prime lezioni che abbiamo appreso possa aiutarti a capire meglio dove investire tempo ed energie, in modo da poter creare senza ostacoli.


