Un sistema software costruito senza API: il metodo di lavoro con un'AI in chat

Il feedback loop: un umano al terminale, un'AI al fianco, e il copia-incolla che li tiene insieme

Ho passato una giornata intera a costruire un piccolo sistema software sul server di casa, in coppia con un'AI — senza API. Niente agente, niente accesso al server: solo chat, terminale, screenshot e molto copia-incolla. Il sistema funziona, verificato end-to-end (62 download completati di prova).

Questo post non parla del software: parla del metodo. La tesi: la struttura rende l'errore economico. Un errore verificato costa un turno; un errore non verificato costa una giornata.

Il vincolo: l'AI non tocca niente

L'AI — nel mio caso Lumo, il modello di chat di Proton — non ha accesso al server. Non esegue comandi, non vede i file. Io sono le mani, lei è il copilota.

Sembra uno svantaggio pesante, e in parte lo è. Ma ha un effetto collaterale interessante: ogni comando proposto deve essere autonomo e verificabile, perché non esiste retry silenzioso. L'assenza di automazione obbliga alla disciplina. E nella giornata ho attraversato tutte le fasi del ciclo di vita — specifica, mockup, deploy, debug, hardening, backup, documentazione — con un sistema che alla fine girava.

Il feedback loop con copia e incolla

Il loop della giornata, sempre lo stesso:

AI propone comando → io incollo nel terminale → incollo l'output in chat → l'AI corregge

Tre regole, imparate sbagliando.

L'output si incolla parola per parola, anche quando fallisce. Il bug più ostico della giornata — un download che moriva con un laconico exit code 1 — si è sbloccato solo incollando i log completi: la causa era nel traceback, da dieci turni. Dieci turni passati a indovinare attorno a un errore già scritto, nero su bianco.

Comandi che dicano se hanno funzionato. Per le modifiche al codice, l'AI ha scritto piccoli script che si rifiutano di toccare un file se non trovano la porzione di testo esatta da sostituire: o il file è quello atteso, o lo script si ferma con un errore chiaro. Niente modifiche che quando sbagliano sbagliano in silenzio. Se un comando di controllo non dice niente, il lavoro non è finito.

Uno step per turno. Mai cinque comandi insieme, altrimenti non sai quale output corrisponde a quale azione. Una volta ho incollato testo e comandi insieme e bash ha risposto syntax error near unexpected token — innocuo, ma istruttivo. Il terminale non è una chat.

Gli screenshot: il canale bidirezionale

Quando il problema è nell'interfaccia, il terminale finisce: servono screenshot. E il canale è davvero bidiazionale — io mandavo screenshot della UI e l'AI notava dettagli che non vedevo: righe sbiadite, elementi disabilitati, un badge “12 issues” nella console.

Ma nemmeno lo screenshot è infallibile. Sospettavamo un HTML incompleto perché nell'inspector del browser i nodi del DOM apparivano collassati (il classico ▶ che nasconde i figli). Il cat del file ha chiarito tutto: c'era tutto. Serve il tipo di evidenza giusto per il tipo di domanda.

Il Markdown come lingua franca

Tutta la documentazione — specifica, README, script di bootstrap — è in Markdown perché ha lavorato in tre ruoli contemporaneamente: documento leggibile per l'umano, input strutturato per l'AI, artefatto persistente nel repository. Un formato, zero traduzioni.

Da qui la regola d'oro: quando uno scambio in chat produce una decisione, la decisione va consolidata in un file. La chat è volatile, il file è la memoria. Una nuova sessione con i file giusti batte una vecchia sessione semi-compattata. Sempre. E scrivere la specifica prima del codice ti obbliga a decidere prima di costruire.

La specifica come contratto

Per la specifica abbiamo usato OpenSpec: flusso propose → review → apply → verify → archive, requisiti come scenari WHEN/THEN, un tasks.md come checklist viva.

Devo raccontare un episodio. L'AI, interrogata su OpenSpec, all'inizio se l'è inventato: un framework plausibile ma di fantasia. Me ne sono accorto, ho cercato la documentazione ufficiale e le ho dato i link. Lei ha riletto le fonti e riscritto tutto il pacchetto documentale secondo il framework vero. La morale non è “le AI allucinano” — è operativa: verifica le fonti anche quando parli con un'AI, soprattutto quando parla con sicurezza.

Il punto importante sono i checkpoint umani: l'AI non passa mai alla fase successiva senza un ok esplicito mio. Le decisioni all'umano, l'esecuzione all'AI. E la specifica funziona da cornice anti-feature-creep: a ogni domanda di scope (“e i video?”), la risposta era “fuori scope, sarà un altro change”. È così che un progetto piccolo finisce.

Il bug fixing come conversazione

Il ciclo di vita di ogni bug: sintomo riportato per intero (log completo, non interpretazione), ipotesi dichiarata come tale (“sospetto X, verifichiamo con Y” ≠ “è X, risolto”), diagnosi con evidenza, modifica chirurgica e riprova. Degli errori dell'AI, uno merita nota: un bug in un modulo l'aveva generato lei stessa; rileggendo il proprio codice se n'è accorta, l'ha ricreato pulito e me l'ha detto apertamente.

L'episodio che definisce la giornata è un altro, e il protagonista sono io.

Tre patch di fila, tre fallimenti. Il download restava rotto, e l'AI continuava a proporre correzioni. A un certo punto mi sono fermato: sta patchando un codice che non corrisponde a quello reale. La compattazione — le chat lunghe vengono riassunte, e i dettagli fini si perdono — le aveva mangiato la visione d'insieme della codebase. Stava patchando un codice immaginario.

Ho scritto una cosa tipo: “forse conviene rileggere il codice, la compattazione potrebbe averti fatto perdere contesto”. Era esattamente quello. Rilettura del codice vero, e la soluzione è arrivata.

Questo problema è una conseguenza diretta dell'assenza di API: un agente con accesso leggerebbe il file a ogni modifica. Senza API, la freschezza del contesto è responsabilità condivisa — l'AI non può accorgersi che la sua mappa ha smesso di corrispondere al territorio. Glielo deve dire qualcuno. Dopo tre patch fallite: fermarsi e chiedere di rileggere il codice vero, non la quarta patch cieca.

La compattazione: strategie di sopravvivenza

La compattazione è il comportamento normale delle chat lunghe: i messaggi vecchi vengono riassunti, i dettagli fini si perdono. Ne abbiamo attraversate più di tre. I segnali del degrado li ho imparati a riconoscere: l'AI tira a indovinare pattern di codice, propone fix per codice che non esiste, ripete suggerimenti già provati.

A sinistra il contesto degradato e sfumato; a destra lo stesso ricostruito nitido dal dump completo

Quattro strategie hanno funzionato.

  1. Documentare mentre si lavora. Il design del sistema, scritto in Markdown a inizio sessione, è sopravvissuto a tre compattazioni. I dettagli no, la struttura sì.
  2. Il dump completo. Quando il patching a distanza non funzionava più, ho creato un file unico con TUTTO il codice del progetto — uno script bash con un loop di docker exec ... cat, più stato del DB e archivio — e l'ho caricato in chat. Costo: due minuti. Beneficio: l'AI smette di indovinare. Il reset del contesto più economico che esista.
  3. Verificare la memoria. Chiedere “cosa ricordi di X?” e confrontare col reale. Se diverge, si ridà il file — non si corregge a parole.
  4. Ripartire dal file, non dalla chat.

Tutto il resto — il backup prima del tocco rischioso (cp file file.bak), l'output incollato per intero — è la stessa idea alla scala del singolo turno: ridare all'AI dati freschi invece di farci sopra ragionamenti.

L'umano come mani

Il modello operativo completo: io faccio da occhi, giudizio e terminal-paste; l'AI fornisce memoria tecnica e generazione. Ma non sono un esecutore passivo: ho verificato, rifiutato, corretto, deciso scope e tagli.

E il collo di bottiglia non è mai stata la velocità dell'AI: è la qualità del feedback che io le riportavo. Un log incollato subito e completo vale dieci turni di descrizioni.

Il canvas: quando la chat smette di essere l'unica superficie

Qui è successa una cosa nel bel mezzo della sessione: di colpo, l'AI ha iniziato a pubblicare i contenuti lunghi in un pannello laterale — un canvas. La funzione era appena stata attivata dalla piattaforma, e ci siamo finiti dentro senza accorgercene.

Ed è stata una svolta. Prima, ogni documento lungo andava fatto stampare in chat e copiato a mano riga per riga: funzionava, era laborioso, ed era il punto dove il metodo si sfilacciava. Col canvas, il contenuto lungo diventa un oggetto di prima classe: si guarda intero, si revisiona, si esporta.

Senza canvas, tutto il contenuto lungo vive nella chat e muore con la compattazione. Con il canvas, si conserva. Trasforma il brainstorm in processo: la differenza tra parlare di un'idea e averne una versione.

Perché funziona

La tesi: la struttura rende l'errore economico. L'output incollato per intero rende l'errore visibile subito; gli script con i controlli interni fanno fallire la modifica sbagliata rumorosamente; il checkpoint umano blocca l'errore di scope quando costa poco; il dump ripristina il contesto quando costa ancora due minuti.

E c'è l'effetto rubber-duck: spiegare il problema all'AI — o incollarle il log, che è spiegare con i fatti — è metà del lavoro di diagnosi. Più di una volta, componendo la descrizione del bug, ho capito da solo dov'era.

Con le API, un agente con accesso diretto renderebbe gran parte di questo metodo inutile. Si andrebbe più veloci e più comodi. Ma c'è una cosa che lavorare senza API ti lascia e l'automazione non dà: le dinamiche di lavoro con l'AI diventano visibili. Vedi dove il contesto degrada, vedi quando comincia a indovinare, vedi quali informazioni la fanno sbagliare e quali la rimettono in pista. Capirla è il prerequisito per usarla bene: esco da questa giornata non solo con un sistema che gira, ma sapendo esattamente cosa significa darle buone informazioni.

Perché l'avvertimento resta valido anche col massimo dell'automazione: le API ti tolgono la fatica del copia-incolla, non la responsabilità della qualità delle informazioni con cui l'AI lavora. Quella meglio non delegarla mai del tutto.


“La tecnologia libera non è solo codice, è la libertà di capire cosa c'è sotto il cofano.”

👤 Lorenzo | ItsMeLarry 🧪 Esperimenti AI & Open Source | 🕹️ Retro Gaming & Graphic Novel 🎸 Rock, Folk, Jazz, Punk | 🔒 Privacy First 📍 Toscana / Digitale

🔗 noblogo.org | 🐙 Codeberg