Menu

Design agent-first: perché esiste Zero e cosa sacrifica

Zero nasce attorno a una sola domanda: come dovrebbe essere un linguaggio di programmazione se gli agenti AI sono utenti di prima classe fin dal primo giorno? Ecco i principi e i compromessi.

La domanda che si pone Zero

La premessa di Zero è semplice: quando a leggere, scrivere e correggere il codice è un agente AI, e non solo una persona, che forma dovrebbe avere il linguaggio in sé?

I linguaggi esistenti sono stati progettati molto prima che gli agenti potessero scrivere codice. Le loro priorità, cioè sintassi concisa, idiomi espressivi e librerie ingegnose, hanno senso per persone che scrivono in un editor. Tollerano ambiguità e conversioni implicite perché le persone sono brave a colmare le lacune. Gli agenti no. Generano testo esatto a partire da distribuzioni di probabilità, e pagano ogni zona grigia del linguaggio con un token sbagliato da qualche parte più avanti.

Zero riparte da zero con il vincolo capovolto: progettare prima per gli agenti, accettare che le persone continueranno a leggere il codice e vedere cosa ne viene fuori.

Principio 1: una superficie piccola e regolare

La maggior parte dei linguaggi di programmazione cresce nel tempo. Ogni nuova versione aggiunge una piccola comodità: un nuovo operatore, una nuova forma sintattica, un nuovo modo di esprimere qualcosa che il linguaggio copriva già. Ogni aggiunta si ripaga in ergonomia per le persone. Ogni aggiunta ha un costo per un agente: un'altra variante da imparare, un altro modo per sbagliare.

Zero mantiene di proposito una superficie minuscola:

  • Una forma di binding (let).
  • Una forma di funzione (fun, facoltativamente pub).
  • Un ciclo, per ora (while).
  • Un modo per modellare i tipi prodotto (shape).
  • Un modo per modellare i tipi somma con payload (choice).
  • Un modo per modellare le somme etichettate (enum).
  • Un costrutto di pattern matching (match).

Niente overloading degli operatori, niente decoratori, niente macro, niente conversioni implicite, niente coercizione truthy, niente operatore ternario. Ogni assenza è una caratteristica: elimina un punto in cui un agente potrebbe scegliere la variante sbagliata.

Il costo è quello ovvio: meno funzionalità di comodo. Il vantaggio è che un agente che impara Zero durante una sessione può arrivare alla sintassi giusta senza dover soppesare sette alternative quasi equivalenti.

Principio 2: effetti espliciti

La maggior parte dei linguaggi permette a qualsiasi funzione, ovunque, di fare I/O. console.log in JavaScript, printf in C, print in Python. La firma della funzione non dice nulla sul fatto che possa scrivere su un file o accedere alla rete. L'unico modo per saperlo è leggerne il corpo, ricorsivamente.

Zero prende la posizione opposta: ogni effetto di una funzione compare nella sua firma.

  • L'I/O passa dalla capability World. Una funzione che non riceve World non può fare I/O. Lo garantisce il sistema dei tipi.
  • Gli errori passano da raises e check. Una funzione che può fallire lo dichiara nella firma. Ogni chiamante ne prende atto con check o con un altro costrutto esplicito.

Dalla sola firma di una funzione puoi rispondere a due domande che stanno molto a cuore a un agente (o a un analizzatore statico, o a una persona che fa revisione):

  • "Potrebbe toccare il mondo esterno?": sì se e solo se compare World.
  • "Potrebbe fallire?": sì se e solo se compare raises.

Questa proprietà non esiste nei linguaggi mainstream, e non è cosa da poco averla.

Il costo è il passaggio dei parametri. Il valore World va passato ovunque serva l'I/O; la clausola raises si ripete ovunque passino gli errori. Zero lo accetta come prezzo di questa proprietà.

Principio 3: strumenti deterministici

Il terzo principio è quello rivolto più direttamente agli agenti: ogni output prodotto dal compilatore è un dato strutturato.

La diagnostica JSON è l'esempio principale:

{
    "code": "NAM003",
    "message": "unknown identifier",
    "line": 3,
    "repair": { "id": "declare-missing-symbol" }
}

Tre proprietà la distinguono da un normale errore del compilatore:

  1. Codici stabili. NAM003 significa la stessa cosa oggi e domani, indipendentemente da come è formulato il messaggio per le persone.
  2. Piani di correzione strutturati. Quando il compilatore pensa di sapere come risolvere una diagnostica, emette un piano sotto forma di dati: un elenco di modifiche, non un suggerimento in inglese.
  3. Più canali strutturati. Diagnostica, grafi delle dipendenze, report sulle dimensioni e spiegazioni sono tutti disponibili tramite le modalità --json.

Il punto è che uno strumento, agente o meno, non debba mai interpretare testo in inglese per agire sull'output del compilatore. Cercare un codice stabile è un'operazione esatta; interpretare la prosa è approssimativo. Zero tratta la prima come il contratto e la seconda come una comodità per le persone.

Principio 4: una libreria che vive nel linguaggio

Gli agenti sono bravi a scrivere codice che segue schemi esistenti. Lo sono meno nello scegliere la dipendenza esterna giusta in un mare di opzioni, nell'integrarla correttamente e nel seguire i cambiamenti della sua API. Ogni dipendenza esterna è attrito.

Il design di Zero sposta le funzionalità nella libreria standard: documentate in modo esplicito, coerenti e stabili man mano che il linguaggio si stabilizza. L'obiettivo è che un programma Zero raramente debba uscire dalla distribuzione standard per il lavoro di routine. Così la superficie su cui un agente deve ragionare resta limitata.

Oggi è più un'aspirazione che una realtà compiuta. La libreria standard pre-1.0 esiste davvero, ma sta ancora crescendo. Il principio indica la direzione, non la meta.

Cosa sacrifica Zero

Ogni scelta di design ha un costo. Ecco i compromessi onesti che fa Zero:

  • Verbosità invece di concisione. Le funzioni pure non hanno bisogno di World. Quelle che fanno I/O sì. Gli errori compaiono nelle firme. Il risultato sono più annotazioni rispetto all'equivalente in JavaScript o Python.
  • Esplicito invece che magico. Niente metaprogrammazione riflessiva, niente decoratori che avvolgono il comportamento in silenzio, niente variabili globali implicite. Cose che nei linguaggi dinamici sembrano funzionare "da sole" vanno collegate a mano.
  • Statico invece che dinamico. I tipi sono obbligatori su parametri, valori di ritorno e campi delle shape. Il compilatore fa molto lavoro; il costo è che ogni firma è qualcosa che chi scrive (o genera) il codice deve scrivere.
  • Stabilità invece di velocità di cambiamento. Il linguaggio è pre-1.0 e cambia in fretta, ma l'intenzione di design è bloccare la superficie una volta assestata. Il costo è che aggiungere più avanti una nuova funzionalità ingegnosa diventa più difficile, perché l'asticella per le aggiunte è "aiuta un agente più di quanto gli costi?".

Se i compromessi valgano la pena dipende da cosa vuoi ottimizzare. Se sei una persona che scrive uno script usa e getta, l'attrito è reale e i vantaggi per gli agenti sono astratti. Se gestisci un agente che produce migliaia di piccoli programmi al giorno, l'attrito si ripaga molte volte.

Cosa Zero non cerca di essere

Alcune affermazioni in negativo che vale la pena esplicitare:

  • Non è "il futuro di tutta la programmazione". Zero è un'ipotesi, non un manifesto. L'ipotesi è che i vincoli agent-first producano un linguaggio utile. Se i linguaggi mainstream debbano adottare quei vincoli è un discorso diverso e più lungo.
  • Non è una funzionalità della piattaforma di deploy di Vercel. Anche se nasce in Vercel Labs, Zero non è legato a Next.js né all'hosting di Vercel. È un linguaggio di sistema indipendente.
  • Non sostituisce Rust, Go o Zig in produzione. È pre-1.0 e sperimentale. Usalo per imparare e dare feedback; non rilasciarci ancora software per i clienti.
  • Non è finito. Parti della libreria standard, la sintassi per la mutabilità, le forme di gestione degli errori e i vincoli sui generics potrebbero cambiare tutti prima della 1.0.

Cosa c'è di interessante anche se non lo usi

Anche se non scriverai mai una riga di Zero, l'esperimento è istruttivo:

  • È l'esempio più chiaro di un sistema di effetti basato su capability, reale e funzionante, in un piccolo linguaggio di sistema. Il modello mentale, cioè passare il permesso e vedere l'effetto nella firma, è trasferibile ovunque.
  • La gestione della diagnostica è ciò che ogni compilatore avrebbe dovuto fare nell'ultimo decennio. L'output strutturato batte la prosa ogni volta, e l'impegno di Zero sui codici stabili è qualcosa che altri strumenti potrebbero adottare senza cambiare linguaggio.
  • Il principio "un solo modo per fare ogni cosa, superficie volutamente piccola" va controcorrente rispetto a come si progettano di solito i linguaggi. Osservare dove questo principio aiuta e dove stringe è utile, qualunque sia il linguaggio in cui scriverai domani.

Cosa leggere dopo

Se hai finito il resto di questa documentazione, le letture più utili sono esterne:

  • Il repository di Zero su github.com/vercel-labs/zero: esempi, sorgenti e AGENTS.md con la dichiarazione di intenti dei maintainer stessi.
  • Il sito ufficiale zerolang.ai: istruzioni per iniziare e l'introduzione di riferimento.

Entrambi sono in evoluzione. Quello che trovi lì sarà più aggiornato di qualsiasi tutorial di terze parti. I principi di questa pagina sono la parte che si muove lentamente; la sintassi attorno a loro cambierà mentre il linguaggio si assesta.

Domande frequenti

Cosa significa 'linguaggio di programmazione agent-first'?

Significa trattare gli agenti AI, non solo le persone, come utenti principali del linguaggio fin dall'inizio. Le loro esigenze (analizzare la sintassi in modo meccanico, generare programmi validi, leggere l'output degli errori come dati, applicare correzioni in modo deterministico) guidano le scelte di design, insieme alle solite attenzioni per la leggibilità e l'ergonomia per le persone.

Perché un linguaggio esistente non va bene per gli agenti?

I linguaggi esistenti sono stati progettati per le persone. Le loro grammatiche includono scorciatoie, conversioni implicite e costrutti ambigui che le persone tollerano ma che mettono in difficoltà chi genera codice. I loro compilatori stampano prosa, non dati. I loro sistemi di effetti sono impliciti. Niente di tutto questo è fatale, gli agenti possono aggirarlo, ma un linguaggio progettato per gli agenti fin dall'inizio elimina l'attrito invece di nasconderlo.

Quali sono i principi fondamentali del design di Zero?

Una grammatica piccola e regolare (un solo modo per fare ogni cosa), effetti espliciti tramite la capability World (nessun I/O implicito), errori espliciti tramite raises/check (nessun flusso di controllo nascosto) e strumenti deterministici (l'output del compilatore come dati strutturati con codici stabili e piani di correzione). I principi si rafforzano a vicenda: ognuno rende gli altri più utili per un agente.

A cosa rinuncia Zero per essere agent-first?

Alla concisione e alla comodità implicita. Non esiste truthiness implicita, non c'è un print globale, non c'è un try/catch che risale silenziosamente lo stack di chiamate. Le funzioni hanno più parametri e le firme portano più annotazioni. In cambio, ciò che una funzione fa, compreso il modo in cui può fallire, si legge dalla sola firma.

Zero sostituirà i linguaggi di programmazione scritti dalle persone?

No, e non è questo l'obiettivo. Zero è un esperimento su come appare un design agent-first, non un'affermazione che gli altri linguaggi debbano adottare tutte le sue scelte. Il risultato interessante è ciò che l'esperimento insegna: quali vincoli aiutano di più gli agenti, quali compromessi le persone tollerano e quali idee potrebbero migrare col tempo nei linguaggi mainstream.

Illustrazione dei linguaggi di programmazione di Coddy

Impara a programmare con Coddy

INIZIA