Due persone danno a un Agent AI quella che sembra la stessa richiesta — e ottengono risultati di qualità completamente diversa. Che cosa differisce davvero tra queste richieste, e come lo si può riconoscere prima ancora che l'AI cominci a lavorare? La risposta è una regola semplice: quanto meglio e più specificamente si descrive una richiesta, tanto meglio l'AI la esegue. Sembra ovvio, ma nella pratica è la causa più comune di cattivi risultati — non la capacità insufficiente del modello, ma una richiesta descritta in modo insufficiente.
Prompt sbagliato: "Correggi il bug del login."
Prompt buono: "In AuthService.login() si verifica un errore quando un utente inserisce un'e-mail con lettere maiuscole — il confronto nel DB distingue maiuscole e minuscole. Correggi la normalizzazione dell'e-mail in modo che avvenga PRIMA del confronto; non toccare l'hashing delle password né il rate limiting in LoginThrottle.ts."
Il secondo prompt contiene quattro elementi chiave che al primo mancano:
- La posizione esatta (file/funzione), non una descrizione generica.
- La descrizione della causa radice, non solo del sintomo.
- Esattamente che cosa fare, non solo "correggilo".
- Che cosa non deve rompersi — un confine esplicito alla modifica.
Senza il punto 4, l'AI tende a "migliorare" cose che non si voleva toccare — ed è esattamente il momento in cui si rompe la logica a valle.
È simile a spiegare a un bambino di cinque anni che cosa fare. Gli si dice che cosa e come, ma altrettanto importante è dirgli che cosa non fare. Per un bambino quel confine è soprattutto educativo; per l'AI è una definizione precisa di ciò che non deve esplorare né modificare — e quel confine affina il risultato molto più di quanto potrebbe mai fare qualsiasi descrizione di cosa cercare.
La stessa logica vale all'interno di un singolo prompt: se vi si infilano contemporaneamente più requisiti non correlati, l'AI non sa quale abbia la priorità e spesso interpreta il compito in modo diverso da quello inteso. Da qui la regola semplice: un prompt = una cosa specifica.
Questo vale tanto per i prompt scritti a mano quanto per i Task generati automaticamente. E questa disciplina è proprio ciò che si può automatizzare — in modo che un prompt non nasca da ciò che una persona si trova a ricordare, ma dalla conoscenza reale e aggiornata del codice (contratti, mappa del DOM, logica di business) che AITM mantiene per conto dell'utente.
Prima di esaminare la struttura del prompt in sé, vale la pena sapere ancora una cosa: AITM non scrive ogni prompt di Task allo stesso modo. Quando un Task viene creato, si classifica prima da solo (oppure lo sceglie l'utente) in una di tre categorie — bug (correzione di un comportamento esistente), enhancement (miglioramento di qualcosa che già esiste) o feature (funzionalità del tutto nuova) — e ogni categoria produce un diverso insieme di requisiti e di criteri di verifica. Per ora concentriamoci su ciò che tutti e tre i tipi hanno in comune: una struttura fissa a 5 blocchi.
Come lo fa davvero AITM — la struttura reale del prompt
AITM non scrive i prompt dei Task a ruota libera. Ogni prompt di Task generato dalla Chat o dal Brainstorm è composto da 5 blocchi fissi, in quest'ordine — e ogni blocco risolve uno specifico problema che altrimenti porterebbe a un Task poco chiaro:
- Role — al massimo 3 frasi che descrivono quale ruolo e quanto prudente approccio l'Agent deve assumere. Senza questo blocco l'Agent non sa quanta "creatività" gli sia consentita — e la creatività senza paletti è proprio ciò che porta a modifiche indesiderate.
- Context — perché esiste il Task: la segnalazione dell'utente, la storia del problema, chi è responsabile dell'area. È separato dalla frase "Context (background only — implement nothing from this block)", perché senza quella frase l'Agent rischia di implementare per sbaglio qualcosa della storia di sfondo invece di concentrarsi esclusivamente sui requisiti.
- Requirements — un blocco numerato per ciascun requisito, ognuno con un criterio di accettazione preciso e verificabile. Suddividere i requisiti in blocchi numerati risolve direttamente il problema discusso sopra — un blocco, una cosa specifica, senza mescolare più requisiti in un'unica frase.
- Scope — tre righe: In scope (cosa può essere modificato), Out of scope (cosa non deve essere modificato e chi ne è responsabile), Must not break (quali contratti devono continuare a valere). È un'implementazione diretta della regola "di' all'AI anche che cosa non fare" — senza questo blocco l'Agent non sa dove siano i confini della sua modifica.
- Output and verification — ogni nuovo file che il Task crea, più comandi di verifica concreti limitati solo a ciò che questa specifica modifica potrebbe rompere. In questo modo il Task non si chiude su un "sembra fatto", ma su un misurabile "questo comando esatto è passato".
Si noti i riferimenti ai contratti come %AUTH-012 — è un riferimento a un contratto specifico, inserito con una sintassi esatta che AITM riconosce ed espande automaticamente nella descrizione completa del comportamento. È proprio questa la differenza tra "scrivi il tuo prompt" e un sistema che impone al posto dell'utente una struttura e citazioni precise.
Cosa contiene davvero un contratto. In AITM un contratto è un record nel database SQLite del progetto, non un commento nel codice. Ha un ID breve (un prefisso di modulo più un numero), un modulo (a quale parte del sistema appartiene il comportamento) e soprattutto un campo behavior — una descrizione precisa, in più frasi, del meccanismo, spesso con un riferimento a righe specifiche di un file e al numero del Task da cui il comportamento ha avuto origine. Porta con sé anche un elenco dei file che il contratto tocca, facoltativamente una danger zone e un elenco delle variabili a cui è collegato. Quando l'Agent vede nel prompt un riferimento "Must not break", AITM inserisce l'intera descrizione al posto del semplice codice — così l'Agent sa esattamente quale comportamento non deve violare.
E i test unitari? Hanno anch'essi un proprio codice — ogni blocco di test nei test di AITM porta all'inizio della sua descrizione un tag univoco. Ciò permette di indirizzare un test specifico con la stessa precisione di un contratto. Un contratto si abbina inoltre al percorso del file di test, così un riferimento a un contratto porta con sé non solo la descrizione del comportamento ma anche un collegamento diretto al test che lo protegge.