Che cos'è la progettazione di un loop AI?
La progettazione di un loop AI definisce attivazione, confini, verifica e budget del ciclo ripetuto da un agente, non un singolo prompt ben scritto.
Cosa significa progettare un loop
La progettazione di un loop consiste nel definire il ciclo ripetitivo eseguito da un agente AI: cosa lo attiva, quali risorse può modificare, come viene verificato il suo output e cosa ne interrompe l'esecuzione. La progettazione dei prompt modella un singolo messaggio inviato a un modello. La progettazione del loop modella il processo che invia migliaia di messaggi mentre dormi. L'unità di lavoro passa dal prompt al loop.
In breve: smetti di scrivere istruzioni e inizi a progettare un sistema di controllo. L'agente ha ancora bisogno di istruzioni valide, ma queste diventano un componente di un ciclo eseguito secondo una pianificazione, che opera su una copia isolata del codice, verifica il proprio risultato tramite un test e si interrompe quando esaurisce il budget.
Perché il termine è comparso nel 2026
Il nome si sta affermando pubblicamente proprio ora. Il repository GitHub cobusgreyling/loop-engineering ha superato 9,600 stelle entro due mesi dalla prima pubblicazione (a luglio 2026) e ne mostrava circa 11,600 il 2026-10-27, con la frase "Stop prompting. Design the loop. Get a score." Nel luglio 2026 il README raggruppava il cambiamento in sei elementi: pianificazione, worktree, skill, plugin e connettori, sub-agent e memoria persistente conservata al di fuori della conversazione. Il README attuale non contiene più quell'elenco (verificato il 2026-10-27), ma mantiene comunque lo stato del loop in un file esterno alla conversazione.
Il repository indica Boris Cherny, responsabile di Claude Code presso Anthropic, tra le fonti di ispirazione. La frase che gli viene ampiamente attribuita è:
I don't prompt Claude anymore. I have loops running that prompt Claude.
Un secondo repository, AI-Builder-Club/skills, è vicino a 1,300 stelle (al 2026-10-27) e definisce direttamente i due ruoli: un "codebase harness" che rende un repository sicuro per l'esecuzione di test e deploy da parte di un agent, e un "loop engineer" che crea workflow che si attivano in risposta a un trigger, eseguono il lavoro e scrivono ciò che hanno appreso in un file condiviso, in modo che il loop successivo possa leggerlo.
Nessuno dei due repository ha inventato questa pratica. Chiunque abbia eseguito una build notturna, un linter in continuous integration o un cron job che apre un ticket conosce già questo schema. La novità è che il worker all'interno del loop ora è non deterministico. Questo cambia le funzioni che deve svolgere l'infrastruttura circostante.
Le quattro parti di un loop
Ogni loop funzionante ha queste quattro parti. Se ne manca una, il loop può svegliarti alle 3 del mattino.
- Trigger. L’evento che avvia un’esecuzione: un timer, un webhook, una nuova pull request o un alert.
- Boundary. I file, le credenziali e la rete che l’agent può raggiungere durante quell’esecuzione.
- Verification. Un controllo con un codice di uscita che determina se l’output dell’esecuzione viene conservato o eliminato.
- Budget. Il limite di token, tempo e denaro che termina l’esecuzione, indipendentemente dal fatto che abbia avuto successo.
Rileggi questi quattro elementi sotto forma di domande: otterrai una revisione della progettazione per qualsiasi agent che stai per lasciare in esecuzione.
Trigger: cosa risveglia l'agente
Un timer è il trigger più semplice. Su un server Linux, un timer systemd è preferibile a cron perché registra gli eventi, ritenta secondo le impostazioni definite e non avvia una seconda istanza di un'unità ancora in esecuzione. Quest'ultima proprietà elimina il problema di sovrapposizione più comune nei cicli degli agenti: due esecuzioni che modificano lo stesso branch.
Assegna prima all'agente un utente dedicato. Questo utente fa parte del perimetro di isolamento, quindi è proprietario di /srv/agent e di nient'altro:
sudo useradd --system --home-dir /srv/agent --shell /usr/sbin/nologin agent
sudo chown -R agent:agent /srv/agentScrivi quindi l'unità in /etc/systemd/system/agent-loop.service:
[Unit]
Description=Agent loop: triage open issues
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
User=agent
WorkingDirectory=/srv/agent/repo
ExecStart=/srv/agent/bin/loop.sh
TimeoutStartSec=1800E il timer in /etc/systemd/system/agent-loop.timer:
[Unit]
Description=Run the triage loop every 30 minutes
[Timer]
OnBootSec=5min
OnUnitActiveSec=30min
Unit=agent-loop.service
[Install]
WantedBy=timers.targetsudo systemctl daemon-reload
sudo systemctl enable --now agent-loop.timer
systemctl list-timers agent-loop.timersystemctl list-timers dovrebbe mostrare una colonna NEXT con un orario futuro e una colonna LEFT con il conto alla rovescia. Un risultato vuoto indica che il timer non è abilitato, perché enable senza --now lo pianifica soltanto per il boot successivo. TimeoutStartSec=1800 è più importante di quanto sembri. Un servizio Type=oneshot risulta in avvio finché lo script non termina. Inoltre, per impostazione predefinita, systemd disabilita il timeout di avvio per le unità oneshot. Senza questa riga, un agente bloccato in attesa di input mantiene l'unità nello stato di attivazione per sempre. A ogni successivo tick del timer, l'unità risulta ancora in esecuzione e non viene avviato nulla. Con questa riga, systemd termina l'esecuzione dopo 30 minuti e la contrassegna come failed. Se modifichi l'unità usando il valore predefinito Type=simple, TimeoutStartSec non copre più l'esecuzione stessa. L'impostazione che la limita è RuntimeMaxSec=. Esamina un'esecuzione con journalctl -u agent-loop.service -n 50.
Se usi cron per pilotare il ciclo, aggiungi una protezione contro le sovrapposizioni, perché cron avvia senza problemi una seconda istanza:
*/30 * * * * /usr/bin/flock -n /tmp/agent-loop.lock /srv/agent/bin/loop.shflock -n termina immediatamente con lo stato 1 quando il lock è già acquisito. La seconda esecuzione termina quindi senza produrre output, invece di entrare in conflitto con la prima. La stessa configurazione del servizio e del timer systemd si applica a qualsiasi job di lunga durata sul server, che sia un agente oppure no.
Confini: ogni esecuzione usa una copia propria
Un agente che modifica il working tree può sovrascrivere il lavoro non ancora sottoposto a commit. I worktree di Git risolvono il problema con un costo ridotto: ogni esecuzione riceve una directory e un branch propri, condividendo un unico object store.
cd /srv/agent/repo
git worktree add -b loop/triage-01 /srv/agent/work/triage-01 origin/main
git worktree listgit worktree list stampa una riga per ogni tree con relativo percorso, commit e branch. Al termine dell'esecuzione, git worktree remove /srv/agent/work/triage-01 rimuove il worktree, ma solo se è pulito. Se il tree contiene file non tracciati, file tracciati modificati oppure submodule, Git rifiuta l'operazione finché non si aggiunge --force. Per questo lo script di controllo seguente forza la rimozione soltanto sul percorso che elimina l'esecuzione. git worktree prune rimuove le voci la cui directory non esiste più. A questo punto i cicli paralleli diventano sicuri, perché due agenti che lavorano su due branch in due directory diverse non possono sovrascriversi a vicenda.
Il confine riguarda anche le credenziali. Un ciclo eseguito senza supervisione conserva token di lunga durata, e ogni esecuzione può esporne uno in un log, in un commit o nel contesto del modello. Limita il token al solo repository utilizzato dal ciclo. Quando possibile, impedisci che sia presente nell'ambiente visibile alla shell dell'agente. Prima di assegnare a un ciclo l'accesso alla produzione, leggi come impedire agli agenti AI di accedere ai secret. Per un isolamento più rigido, esegui l'intero ciclo su una VM temporanea che puoi eliminare dopo ogni esecuzione. Anche lo strumento scelto definisce parte del confine prima che tu scriva il ciclo. Prima di decidere quanto isolamento configurare autonomamente, conviene quindi leggere come il sandbox gestito di Cowork si confronta con Claude Code sul tuo computer.
Verifica: il controllo che rende sicuro il ciclo
Questa è la parte che distingue un ciclo da un cron job che esegue comandi. L’output dell’agente è una proposta. Il controllo decide.
#!/usr/bin/env bash
set -euo pipefail
repo=/srv/agent/repo
branch="loop/$(date -u +%Y%m%dT%H%M%SZ)"
tree="/srv/agent/work/$(basename "$branch")"
cd "$repo"
git fetch --quiet origin
git worktree add -b "$branch" "$tree" origin/main
cd "$tree"
# the agent's own command runs here, in non-interactive mode
if ! npm test; then
echo "gate failed: discarding $branch" >&2
cd "$repo"
git worktree remove --force "$tree"
exit 1
fi
git push origin "$branch"
cd "$repo"
git worktree remove "$tree"set -euo pipefail svolge un lavoro effettivo in quello script. Senza -e, un git fetch non riuscito viene ignorato e l’esecuzione continua usando un origin/main obsoleto. Senza -u, un errore di battitura nel nome di una variabile viene sostituito da una stringa vuota e la pulizia viene quindi eseguita sul percorso sbagliato, invece di terminare segnalando chiaramente l’errore. L’ultima riga non contiene volutamente --force: se l’esecuzione ha lasciato file non tracciati o non sottoposti a commit nell’albero di lavoro, git rifiuta di rimuoverli e -e termina l’esecuzione con un errore dopo il push, invece di eliminare silenziosamente lavoro che nessuno ha sottoposto a commit.
Il blocco if ! npm test esprime l’idea centrale. Il codice di uscita di un controllo già considerato affidabile, come la suite di test o il type checker, decide se il branch viene sottoposto a push o eliminato. Un ciclo senza controllo produce lavoro che nessuno ha il tempo di esaminare, e questo è peggio che non produrre lavoro. Un ciclo con un controllo produce un branch che ha già superato lo stesso livello richiesto al branch di un contributore umano. Un controllo superato non dice nulla sulla quantità di codice modificata dall’agente per arrivare a quel risultato. Per questo conviene associare il controllo a un’istruzione permanente come la regola che impone all’agente di applicare la modifica minima funzionante, così il diff resta abbastanza ridotto da poter essere esaminato rapidamente.
Scegli un controllo che segnali correttamente gli errori. Una suite di test che passa con un diff vuoto insegna al ciclo che non fare nulla è un risultato positivo. I repository con test deboli producono cicli deboli. Per questo i repository più seguiti indicano di «rendere il codebase pronto per gli agenti» prima di «scrivere il ciclo». Se vuoi sapere se la suite rileverebbe davvero una regressione, invece di limitarsi a eseguire le righe di codice, il mutation testing è il controllo che fornisce la risposta. Inoltre, un agente che restituisce un report di evidenze rieseguibile invece di chiederti di leggere il diff trasforma quella risposta in qualcosa che puoi verificare direttamente.
Budget: cosa interrompe un'esecuzione
Un agente che ritenta senza fine genera costi senza limite. Imposta per ogni ciclo un limite basato sul tempo reale, applicato tramite TimeoutStartSec, un numero massimo di tentativi nello script e un limite di spesa imposto dall'account del provider. Registra poi il costo di ogni esecuzione, così puoi rilevare una deriva del ciclo prima che compaia in fattura. Controllo dei costi per un VPS con agente sempre attivo illustra la gestione contabile, mentre gestione del contesto che un agente mantiene tra i turni tratta il principale fattore che incide sul costo di ogni esecuzione: un ciclo che rilegge lo stesso repository ogni 30 minuti lo paga ogni 30 minuti.
Il costo è il motivo per cui i cicli sono generalmente preferibili a una sessione unica e prolungata. Un'esecuzione che parte da zero, svolge un'attività circoscritta e termina mantiene ridotto il contesto. Una sessione lasciata aperta per otto ore conserva nella cronologia tutti gli errori precedenti e addebita l'intera trascrizione a ogni turno.
I pattern codificati dai repository più in voga
Il repository dedicato al loop engineering elenca otto pattern per la produzione (al 2026-10-27). È utile leggerli come un catalogo, non come un manifesto. Triage giornaliero. Un loop minimale eseguito come GitHub Action, senza file di stato. Un babysitter per le pull request che monitora i commenti delle review e risponde. Un sweeper per la continuous integration che recupera le build non riuscite. Un dependency sweeper. Un generatore di bozze per il changelog. Pulizia post-merge. Triage degli issue.
Tutti hanno in comune un compito circoscritto e un controllo evidente. "Fix the failing build" ha una condizione di superamento che la macchina può leggere. "Improve the codebase" non ce l'ha, quindi non diventa mai un loop. Diventa un insieme disordinato di attività con una pianificazione.
Hanno in comune anche un record scritto. Entrambi i repository spostano lo stato al di fuori della conversazione, memorizzandolo in file nel repository: cosa è stato eseguito, cosa è stato rilevato e cosa è stato deciso. Quel file è la memoria del loop e consente a un secondo loop di basarsi sul lavoro del primo invece di riscoprirlo. È anche il modo per verificare a posteriori l'operato di un agent, perché il contesto del modello scompare nel momento in cui l'esecuzione termina. Il coordinamento in tempo reale avviene su un canale separato e una sessione di Claude Code può affidare il lavoro a un'altra sullo stesso host mentre entrambe sono ancora in esecuzione, ma nulla di quello scambio sopravvive alla chiusura di una delle due sessioni. Per questo il file resta l'elemento da consultare in seguito.
Dove i loop falliscono
I problemi sono banali e si ripetono in team diversi.
- Nessun controllo. L’output si accumula, nessuno lo revisiona, la fiducia viene meno e il loop viene disattivato.
- Sovrapposizione. Due esecuzioni sullo stesso branch o due agent nello stesso working tree generano conflitti che l’agent tenta poi di risolvere.
- Deriva silenziosa. Il loop continua a superare i controlli perché la verifica è troppo debole per rilevare il problema.
- Ambito illimitato. Un trigger che si attiva a ogni commit in un repository molto utilizzato si trasforma in un problema di costi nel giro di un giorno.
La correzione è la stessa in tutti i casi: ridurre il lavoro, rendere il controllo più preciso e registrare l’esecuzione. Se non puoi descrivere in una frase la condizione di superamento, il lavoro non è pronto per essere automatizzato.
Per iniziare senza il gergo
Non serve un framework. Un piccolo server Linux sempre acceso, un repository Git la cui suite di test fallisce quando deve fallire, un timer systemd e uno script shell che contiene un if completano il ciclo. È il punto di partenza consigliato nella maggior parte dei casi, perché le scelte progettuali trovano risposta eseguendo il sistema, non scegliendo uno strumento. Quando un ciclo è stabile, eseguirne un secondo richiede soprattutto un altro timer e un altro worktree. Vedere come eseguire un agente AI per la programmazione su un VPS per la configurazione di base e le opzioni attuali per agenti AI self-hosted se si vuole eseguire l’agente stesso su hardware sotto il proprio controllo.
FAQ
La progettazione del ciclo è diversa dalla progettazione del prompt?
La progettazione del prompt ottimizza un singolo messaggio: formulazione, esempi e formato dell'output. La progettazione del ciclo ottimizza il processo che circonda il messaggio: il trigger che avvia un'esecuzione, la sandbox in cui viene eseguita, il controllo che accetta o rifiuta l'output e il budget che la interrompe. Nel ciclo serve comunque un buon prompt. Tuttavia, il prompt non è più l'elemento da ottimizzare quotidianamente, perché il gate e il trigger hanno un effetto maggiore sul risultato.
Serve un framework per creare un ciclo di agente?
No. Un timer systemd, un git worktree per ogni esecuzione, uno script shell che termina con un comando di test e un limite di spesa sull'account del provider coprono ogni parte della definizione. I framework aggiungono interfacce di pianificazione, formati per la memoria condivisa e instradamento tra più agenti. Sono utili quando esegui diversi cicli, ma non sono necessari per iniziare.
Che cos'è un harness per una codebase?
È l'insieme degli strumenti che consente a un agente di lavorare in un repository senza la presenza di una persona: una configurazione eseguibile con un solo comando, test eseguibili senza interazione e con errori espliciti, un linter e un metodo per distribuire o visualizzare in anteprima una modifica. Il termine appartiene alla stessa ondata di repository del 2026 da cui proviene la progettazione dei cicli. Il test pratico è semplice: se un nuovo collaboratore umano non riesce a passare dal clone ai test superati con un solo comando, non ci riuscirà neppure un agente.
Come impedisco a un ciclo di agente di generare una fattura elevata?
Imposta un limite in tre punti. Configura TimeoutStartSec su un'unità systemd Type=oneshot come quella precedente, in modo che un'esecuzione bloccata venga terminata. Su un servizio Type=simple, l'equivalente è RuntimeMaxSec. Limita i tentativi nello script, invece di ripetere l'operazione fino al successo. Imposta un limite di spesa rigido sull'account API, perché è l'unico limite che l'agente non può superare con le proprie risposte. Registra quindi il costo di ogni esecuzione: quando il costo di un ciclo raddoppia, di solito significa che il suo ambito si è ampliato senza controllo.
Quali job conviene trasformare per primi in un ciclo?
Scegli un job con una condizione di superamento verificabile automaticamente e un raggio d'azione ridotto. La correzione di una build fallita, l'aggiornamento di una dipendenza e la rigenerazione di un changelog sono esempi adatti, perché una suite di test o un diff può dimostrare il risultato. Le attività aperte, come il refactoring o la progettazione, non sono ancora adatte: non c'è nulla che il gate possa verificare. Un ciclo senza gate è un modo costoso per accumulare debito di revisione.