← Torna al Blog

Programmare con l'AI porta preoccupazioni che gli strumenti standard non risolvono

Illustrazione che contrappone modifiche caotiche del codice da parte dell'AI all'approccio strutturato di AITM

L'AI di oggi può scrivere una funzione, un componente o un intero endpoint in pochi secondi. Il problema non compare dove ci si aspetta — nella sintassi o nella velocità. Compare nel momento in cui l'AI deve toccare un sistema esistente: decine di file, una storia di decisioni, regole di business che non sono scritte da nessuna parte se non "nella testa" degli sviluppatori. Come prevenire in modo sistematico questo problema è il tema di tutta questa serie — e lo strumento a cui arriveremo gradualmente si chiama AITM.

Prima di arrivarci, vale la pena porsi una domanda a cui ogni team che lavora con Agent AI risponde prima o poi — nel modo facile o in quello costoso: come si fa a sapere davvero che il risultato che un Agent ha restituito come "fatto" sia realmente corretto, e non soltanto che sembri tale? Alla risposta arriveremo alla fine di questo articolo — ma prima vediamo perché non è affatto una domanda così ovvia.

Come appare nella pratica

Uno scenario tipico: si chiede a un Agent AI di modificare una funzione. L'Agent la corregge — ma dimentica che questa funzione viene chiamata da altri tre punti con aspettative diverse. Oppure "migliora" la struttura del codice perché gli sembrava logico, e così facendo rompe una logica a valle che non ha mai nemmeno visto.

Non sono bug isolati — sono un problema sistemico: l'Agent AI non ha il contesto dell'intero sistema, solo ciò che entra nel prompt e ciò che riesce a leggere tramite la ricerca full-text. Decide in base alle parole, non alla logica di business. Se è disponibile della documentazione, spesso ne carica l'intero contenuto — compresa la parte che non c'entra nulla con il prompt dato. E questo vale anche per i modelli più potenti disponibili (Opus, Fable, Astra e simili): non è che il modello non sia abbastanza intelligente, è che non ha un posto dove conservare in modo sistematico questa conoscenza tra un intervento e l'altro.

Man mano che cresce il numero di righe di codice sorgente, che la logica di business si fa più complessa e che moduli e classi diventano più interconnessi, questa ricerca peggiora. Finiscono nell'AI dati che non c'entrano nulla con la correzione — e il risultato è un codice tecnicamente scritto in modo corretto ma che segue la logica di business sbagliata. La funzionalità risultante è rotta, oppure viene "corretto" un pezzo di codice che nessuno voleva toccare fin dall'inizio.

Dove esattamente si inceppa

L'ostacolo fondamentale è l'allucinazione — ed è molto difficile da eliminare. Il secondo problema è la qualità del prompt, su cui noi utenti possiamo già influire in parte. Ma su entrambi incombe un vincolo più duro: il limite del contesto. Anche con i modelli più grandi disponibili si parla di circa un milione di token — per ambienti che hanno centinaia di migliaia di righe di codice.

Per esperienza, la soglia pratica oltre la quale le basi come una Skill o un hint in un file md non bastano più è all'incirca intorno alle 150.000 righe di codice. Intorno alle 300.000 righe l'ambiente diventa davvero complesso — lo stato quotidiano comincia a sfaldarsi e le cose si rompono da sole. Parliamo di software costruito su OOP, con condizioni logiche complicate e parti collegate tramite meccanismi di messaggi/eventi e tecniche simili. In un codice di questo tipo il riferimento tra una chiamata e la sua gestione non è sempre evidente, e l'AI fa molta fatica con questa parte — è piuttosto probabile che non riesca a scoprire tutto il codice legato a un dato metodo.

A ciò si aggiunge un altro livello: l'Agent AI stesso, in base al prompt, spesso genera propri subagent — e la creazione di quei subagent è a sua volta sotto il controllo dell'AI, il che introduce un'ulteriore fonte di errore. Se l'AI attribuisce un peso maggiore a una parola che era stata inserita in una frase solo per fluidità grammaticale (non come istruzione), può generare un subagent basato su quella parola che elabora qualcosa che non si voleva affatto. E un subagent può trasmettere i propri errori ad altri Agent lungo la catena — così le singole allucinazioni possono propagarsi e sommarsi.

Sembrerebbe che un Agent di controllo, il cui compito è verificare che tutto sia stato fatto secondo le specifiche, dovrebbe risolvere il problema. Ma che cosa significa davvero "verificare"? Se un'altra AI valuta il Task nello stesso modo in cui è stato elaborato, si ottiene solo la conferma dello stesso giudizio, non un controllo indipendente. Solo usando un LLM diverso e migliore per il controllo la probabilità di individuare l'errore aumenta davvero — ma è una scelta che qualcuno deve compiere deliberatamente, non un esito automatico del fatto che "un controllo c'è stato".

Rimane ancora una strada: eseguire l'applicazione o un test esistente, leggere l'errore dal log e correggerlo in modo che il test passi. Anche qui, però, resta la domanda su che cosa sia stato effettivamente corretto — è davvero un bug, o è un errore causato da una modifica della logica di business che un passo precedente ha introdotto involontariamente? La correzione in sé di solito è netta e l'errore scompare, ma spesso nel farlo rompe qualche altra parte del codice. Molto dipende da quanto è complesso il codice e da quali dipendenze ha.

Per cose più semplici — ad esempio un modulo web con modifica, validazione dopo la compilazione e salvataggio dei dati tramite logica di business — di solito non è impegnativo e la probabilità di successo è vicina al 99%. Per strutture più complesse si può davvero arrivare a uno stato in cui la struttura del codice comincia a sfaldarsi e un bug segue l'altro. Eseguire ripetutamente test e test e2e può gradualmente sistemare le cose, ma su un sistema davvero complesso possono servire molti tentativi — e ciascuno ha un costo.

La risposta promessa all'inizio

Tornando alla domanda iniziale: come si fa a sapere che un risultato è davvero corretto, e non solo che sembra concluso? Dal solo prompt e dal controllo successivo non lo si può dire con affidabilità. Abbiamo visto perché: contesto limitato, allucinazioni che si propagano tra subagent, un controllo che nel peggiore dei casi conferma soltanto lo stesso errore, e una correzione guidata dai log che non sa distinguere un vero bug da un effetto collaterale.

Questi sono i metodi che i programmatori usano comunemente oggi e, per modifiche più semplici, funzionano bene. Il livello successivo è l'orchestrazione tramite AI — si preparano determinati dati sul sistema e li si mantiene aggiornati, così da poter fornire all'AI informazioni migliori e ridurre così lo spazio che ha per fare qualcosa di diverso da ciò che è stato chiesto. È esattamente lo scopo per cui è stato creato AITM — AI Task Manager: prima che l'Agent che scrive il codice arrivi alla richiesta, il sistema recupera i contratti (comportamento documentato), una mappa del DOM e la logica di business per l'area in questione — e solo allora, con quella conoscenza, assembla il Task. Non si affida direttamente a un singolo Agent, ma a un'intera Pipeline e ad altri metodi che AITM usa per ottenere risultati migliori.

I prossimi giorni mostreranno esattamente come appare tutto questo in AITM, con prompt, Agent e passi della Pipeline concreti — e perché si tratta di un modo di lavorare con l'AI diverso da quello a cui i programmatori sono abituati con una semplice console.