0. TL;DR
Dopo aver scritto "The Claude Code You Don't Know: Architecture, Governance, and Engineering Practices", mi sono reso conto che la mia comprensione degli strati sottostanti degli Agenti non era abbastanza approfondita. Combinata con la significativa esperienza del nostro team nel realizzare soluzioni aziendali basate su Agenti, ho sentito la necessità di una revisione sistematica. Così, ho esaminato materiali, implementazioni open-source e il mio stesso codice per organizzare questo articolo.
Questo articolo si concentra sulle parti dell'architettura degli Agenti che hanno il maggiore impatto sui risultati ingegneristici, inclusi il flusso di controllo, l'ingegneria del contesto, la progettazione degli strumenti, la memoria, l'organizzazione multi-agente, la valutazione, il tracciamento e la sicurezza. Infine, utilizzeremo l'implementazione di OpenClaw per collegare insieme questi principi di progettazione.
Nell'organizzare questo, diverse conclusioni si sono discostate dalle mie ipotesi iniziali: i miglioramenti apportati da modelli più costosi sono spesso inferiori al previsto; invece, la qualità dell'Harness e dei test di verifica ha un impatto maggiore sui tassi di successo. Quando si esegue il debug del comportamento di un Agente, dare priorità al controllo delle definizioni degli strumenti, poiché la maggior parte degli errori di selezione degli strumenti deriva da descrizioni imprecise. Inoltre, i problemi all'interno del sistema di valutazione stesso sono spesso più difficili da rilevare dei bug dell'Agente. Se continui a modificare il codice dell'Agente senza successo, la risposta potrebbe risiedere in queste aree.
1. Funzionamento di Base del Ciclo dell'Agente
La logica di implementazione principale di un Ciclo Agente, quando astratta, è meno di 20 righe di codice:
1const messages: MessageParam[] = [{ role: "user", content: userInput }];23while (true) {4 const response = await client.messages.create({5 model: "claude-opus-4-6",6 max_tokens: 8096,7 tools: toolDefinitions,8 messages,9 });1011 if (response.stop_reason === "tool_use") {12 const toolResults = await Promise.all(13 response.content14 .filter((b) => b.type === "tool_use")15 .map(async (b) => ({16 type: "tool_result" as const,17 tool_use_id: b.id,18 content: await executeTool(b.name, b.input),19 }))20 );21 messages.push({ role: "assistant", content: response.content });22 messages.push({ role: "user", content: toolResults });23 } else {24 return response.content.find((b) => b.type === "text")?.text ?? "";25 }26}
Il flusso di controllo corrispondente è il seguente: un ciclo continuo di Percezione -> Decisione -> Azione -> Feedback fino a quando il modello restituisce testo semplice:

Avendo visto molte implementazioni di Agenti e SDK ufficiali, le strutture sono simili. Il ciclo stesso è abbastanza stabile. Da un'implementazione minima al supporto di sub-agenti, compressione del contesto e caricamento delle competenze, il ciclo principale cambia raramente. Le nuove capacità vengono solitamente aggiunte all'esterno del ciclo piuttosto che modificarne l'interno.
Le nuove capacità vengono integrate principalmente in tre modi: estendendo i set di strumenti e i gestori, regolando le strutture del prompt di sistema ed esternalizzando lo stato su file o database. Il corpo del ciclo non dovrebbe diventare una macchina a stati massiccia. Il modello gestisce il ragionamento, mentre i sistemi esterni gestiscono lo stato e i confini. Una volta stabilita questa divisione del lavoro, la logica del ciclo principale raramente necessita di frequenti aggiustamenti.
Qual è la differenza tra Workflow e Agente?
Anthropic fa una distinzione diretta: un sistema in cui il percorso di esecuzione è pre-scritto nel codice è un Workflow; un sistema in cui l'LLM decide dinamicamente il passo successivo è un Agente. La differenza fondamentale è chi detiene il controllo. In realtà, molti prodotti etichettati come Agenti sono più vicini a Workflow, ma nessuno dei due è intrinsecamente superiore. Ciò che conta è trovare la soluzione giusta per il compito.

Guardandolo in un diagramma diventa più intuitivo:

Cinque Modelli di Controllo Comuni
La maggior parte dei sistemi AI, quando scomposti, sono combinazioni di questi cinque modelli. Molti scenari non necessitano della piena autonomia di un Agente; combinare alcuni di questi modelli è sufficiente. La chiave è quale design si adatta al compito.
- Concatenazione di Prompt (Prompt Chaining): I compiti vengono suddivisi in passaggi sequenziali in cui ogni passo LLM elabora l'output precedente. È possibile aggiungere checkpoint di codice. Adatto per processi lineari come la traduzione dopo la generazione o la scrittura del corpo del testo dopo una bozza.
- Instradamento (Routing): Classifica l'input e lo indirizza a un processo specializzato. Le domande semplici vanno a modelli leggeri, quelle complesse a modelli forti; le richieste di supporto tecnico e di fatturazione seguono logiche diverse.
- Parallelizzazione (Parallelization): Due varianti: Sezionamento (suddivisione dei compiti in sotto-compiti indipendenti) e Votazione (esecuzione dello stesso compito più volte per raggiungere un consenso). Adatto per decisioni ad alto rischio o esigenze multi-prospettiva.
- Orchestratore-Lavoratori (Orchestrator-Workers): Un LLM centrale scompone dinamicamente i compiti e li delega a LLM lavoratori, quindi sintetizza i risultati. Questo è il prototipo per lo strumento spawn di nanobot e la modalità sub-agente di learn-claude-code.
- Valutatore-Ottimizzatore (Evaluator-Optimizer): Un generatore produce output e un valutatore fornisce feedback in un ciclo fino al raggiungimento degli standard. Adatto per compiti come la traduzione o la scrittura creativa in cui gli standard di qualità sono difficili da definire con precisione nel codice.

Questi modelli risolvono come costruire il flusso di controllo. Ora esaminiamo una domanda più incentrata sull'ingegneria: perché un sistema funziona in modo stabile?
2. Perché l'Harness è Più Critico del Modello
Un Harness si riferisce all'infrastruttura di test, verifica e vincoli costruita attorno a un Agente. Un Harness include almeno quattro parti: baseline di accettazione, confini di esecuzione, segnali di feedback e metodi di fallback.
Sebbene il modello sia importante, queste condizioni ingegneristiche periferiche spesso determinano se un sistema funziona in modo stabile. Questo giudizio è più vero per compiti altamente verificabili come la programmazione, ma in compiti a verifica debole come la ricerca aperta o la negoziazione multi-round, il limite superiore del modello rimane più critico.
La Pratica di Sviluppo Agent-First di OpenAI
Tre ingegneri hanno scritto un milione di righe di codice in cinque mesi con quasi 1.500 PR, una velocità 10 volte superiore allo sviluppo tradizionale. Questa velocità non era dovuta solo alla potenza del modello, ma a decisioni ingegneristiche corrette:
- Ciò che l'Agente non può vedere non esiste: La conoscenza deve esistere nel codebase stesso. I documenti esterni sono invisibili a un Agente in esecuzione. AGENTS.md è mantenuto a circa 100 righe come indice, con i dettagli suddivisi in directory docs per riferimento on-demand.
- Vincola con il codice, non documentarli: Le norme nei documenti vengono facilmente ignorate. I vincoli codificati in Linter, sistemi di tipi o regole CI sono eseguibili. La stratificazione architetturale è imposta meccanicamente da Linter personalizzati, non da revisione manuale.
- Completamento autonomo end-to-end dei compiti: Dalla verifica dello stato e riproduzione dei bug all'implementazione delle correzioni e guida della verifica dell'app, apertura di PR, gestione delle revisioni e merge, l'intera catena non richiede intervento umano. Gli Agenti controllano attivamente log, metriche e trace.
- Minimizzare l'attrito del merge: Gestire i fallimenti intermittenti dei test con tentativi piuttosto che bloccare i progressi. In ambienti ad alto throughput, il costo dell'attesa di una revisione manuale è spesso superiore alla correzione di piccoli errori. La disciplina di codifica non è scomparsa; si è spostata dalla revisione manuale ai vincoli eseguiti dalla macchina.

L'app distribuisce log, metriche e trace tramite Vector al layer di storage Victoria, corrispondente alle interfacce LogQL, PromQL e TraceQL. Codex interroga, correla e ragiona attraverso queste interfacce. Dopo le modifiche, riavvia l'app, riesegue i carichi di lavoro e restituisce i risultati a Codex. Anche i UI Journeys sono input. Questo stack di osservabilità viene creato per ogni compito e distrutto al completamento. L'Agente non aspetta che gli vengano comunicati gli errori; interroga lo stato del sistema per verificare le correzioni.
Qual è la Conclusione Chiave per l'Harness?

Il diagramma utilizza la chiarezza del compito e l'automazione della verifica per dividere i compiti in quattro stati. L'angolo in alto a destra (obiettivi chiari, verifica automatizzata) è la zona ideale per gli Agenti. L'angolo in alto a sinistra (compito chiaro ma revisione manuale) è limitato dalla velocità di revisione umana. L'angolo in basso a destra (feedback automatizzato ma obiettivi vaghi) porta a un movimento efficiente nella direzione sbagliata. L'angolo in basso a sinistra (mancano entrambi) rende gli Agenti inutili.
Il compito dell'Harness è spingere i compiti nell'angolo in alto a destra, assicurando che giusto e sbagliato siano giudicati da standard eseguibili dalla macchina, non da occhi umani.
3. Perché l'Ingegneria del Contesto Determina la Stabilità
La complessità dell'attenzione del Transformer è O(n²). Più lungo è il contesto, più è facile che i segnali chiave vengano diluiti dal rumore. Una modalità di fallimento comune è il "Context Rot", in cui il contenuto irrilevante domina il contesto, causando un calo della qualità decisionale dell'Agente. Molti problemi che appaiono come incapacità del modello sono in realtà dovuti a una scarsa organizzazione del contesto.
Perché Stratificare il Contesto?
Il problema di solito non è che la finestra non sia abbastanza lunga, ma che la densità di informazioni sia sbagliata. Caricare elementi usati raramente ogni volta o mescolare regole stabili con stati dinamici rende più difficile per il modello notare ciò che è utile.

La soluzione è stratificare le informazioni per frequenza e stabilità:
- Strato Permanente: Identità, convenzioni di progetto, divieti assoluti. Contenuto che deve valere per ogni sessione. Mantienilo breve, solido ed eseguibile.
- Caricamento su Richiesta: Competenze e conoscenze di dominio. Mantieni i descrittori permanenti, ma inietta il contenuto completo solo quando attivato.
- Iniezione a Runtime: Informazioni dinamiche come ora corrente, ID canale, preferenze utente. Iniettate per round secondo necessità.
- Strato di Memoria: Esperienze tra sessioni scritte in MEMORY.md. Non direttamente nel prompt di sistema; lette solo quando necessario.
- Strato di Sistema: Hook o regole di codice per logica deterministica. Rimane completamente fuori dal contesto.
Non mettere logica deterministica nel contesto. Qualsiasi cosa esprimibile tramite Hook, regole di codice o vincoli degli strumenti dovrebbe essere gestita da sistemi esterni.
Tre Strategie di Compressione Comuni
- Finestra Scorrevole (Sliding Window): Scarta i messaggi vecchi. Costo basso, ma perde il contesto iniziale. Buono per chat brevi.
- Riepilogo LLM: Il modello genera un riepilogo. Costo medio, perde dettagli ma mantiene le decisioni. Buono per compiti lunghi.
- Sostituzione del Risultato dello Strumento: Sostituisce l'output grezzo con segnaposto. Costo basso, buono per compiti con molti strumenti.
Le finestre scorrevoli sono le più facili ma perdono il contesto iniziale. I riepiloghi LLM avanzati utilizzano la "riassunzione per rami", preservando esplicitamente le decisioni architetturali, i compiti incompiuti e i vincoli chiave. Nella sostituzione degli strumenti, micro_compact sostituisce i vecchi output degli strumenti ogni round, mentre auto_compact si attiva quando il contesto supera una soglia.
Prompt Caching per Ridurre il Sovraccarico Ridondante
L'inferenza LLM calcola coppie Chiave-Valore per ogni token. Se un prefisso corrisponde esattamente a una richiesta precedente, viene letto dalla cache. La memorizzazione nella cache richiede una corrispondenza esatta del prefisso. Un design favorevole alla cache si basa sulla stabilità: i prompt di sistema, le definizioni degli strumenti e i documenti lunghi sono stabili e adatti alla cache. Le informazioni dinamiche (ora, input, risultati degli strumenti) dovrebbero essere posizionate alla fine.
Questo è correlato alla stratificazione del contesto. Più stabile è lo strato permanente, maggiore è il tasso di hit della cache e minore è il costo marginale. "Breve e stabile" non serve solo a risparmiare token; protegge la cache. Il caricamento ritardato delle competenze aiuta anche aggiungendo contenuto dopo il prefisso stabile. Un punto controintuitivo: un prompt di sistema grande e stabile può essere più economico di uno piccolo che cambia frequentemente perché lo sconto del 90% sulle letture successive supera il costo iniziale di scrittura.
Perché Caricare le Competenze su Richiesta?
Le competenze sono un modello efficace: mantieni solo l'indice nel prompt di sistema, carica la conoscenza completa quando necessario.
1const systemPrompt = `2Competenze Disponibili:3- deploy: Processo completo di distribuzione in produzione4- code-review: Checklist per la revisione del codice5- git-workflow: Strategia dei branch e norme PR6`;78async function executeLoadSkill(name: string): Promise<string> {9 return fs.readFile(`./skills/${name}.md`, "utf-8");10}
Le descrizioni delle competenze devono essere brevi per evitare il gonfiaggio dei token e dovrebbero fungere da condizioni di instradamento. Spiega quando usarla, quando NON usarla e qual è l'output. Usa "Usa quando / Non usare quando" con esempi negativi. Molti fallimenti di instradamento sono dovuti a confini poco chiari, non alla capacità del modello. Il prompt di sistema dovrebbe chiarire le regole: scansiona available_skills prima di ogni risposta, carica lo specifico SKILL.md in caso di corrispondenza e carica solo uno alla volta.

I dati sono chiari: senza esempi negativi, la precisione scende dal 73% al 53%; aggiungendoli sale all'85% e riduce il tempo di risposta del 18,1%. Gli esempi negativi sono fondamentali.
I descrittori delle competenze hanno due trappole. Primo, il conteggio delle parole: descrizioni lunghe per ogni competenza si accumulano. Secondo, la precisione: "aiuta con il backend" è troppo vago. I descrittori efficaci sono condizioni di instradamento, non introduzioni di funzionalità. "Quando usarmi" è più importante di "Cosa posso fare".
Controlla la quantità: mantieni solo le competenze ad alta frequenza nel prompt permanente. Quelle a bassa frequenza possono essere introdotte manualmente o mantenute come documenti. Gli anti-pattern tipici includono infilare centinaia di righe di manuali in una competenza o avere una competenza che copre troppi compiti distinti (revisione, distribuzione, debug).
Cosa Perde Più Facilmente la Compressione?
Il problema più comune non è che il riepilogo sia troppo lungo, ma che la priorità di conservazione sia sbagliata. Gli LLM spesso eliminano informazioni che sembrano riottenibili. Gli output degli strumenti vanno per primi, ma le relative decisioni architetturali e i percorsi di fallimento spesso scompaiono insieme. Definisci esplicitamente le priorità di conservazione in CLAUDE.md:
1### Istruzioni di Compattazione: Come conservare le info chiave2Priorità:31. Decisioni architetturali (non riassumere)42. File modificati e modifiche chiave53. Stato di verifica (pass/fail)64. TODO non risolti e note di rollback75. Output degli strumenti (può essere cancellato, mantenere solo la conclusione pass/fail)
Un'altra trappola: non cambiare gli identificatori. UUID, hash, IP e nomi di file devono essere preservati esattamente. Un carattere sbagliato in un hash di commit rompe le successive chiamate agli strumenti.
Perché i File System sono Ottime Interfacce di Contesto
Cursor chiama questo "Dynamic Context Discovery": dai meno per impostazione predefinita, leggi quando necessario. I file system sono interfacce naturali. Le chiamate agli strumenti spesso restituiscono JSON massicci; invece di infilarli nel contesto, scrivili in un file. L'Agente può usare grep o rg per leggere secondo necessità. Questo mantiene il contesto pulito ed è leggibile dagli sviluppatori.
Cursor lo ha verificato con gli strumenti MCP: sincronizzano le descrizioni degli strumenti nelle cartelle. Gli Agenti vedono solo i nomi degli strumenti per impostazione predefinita e interrogano le definizioni quando necessario. Nei test A/B, questo ha ridotto il consumo totale di token del 46,9%.
Questo funziona anche per la compressione di compiti lunghi. Invece di scartare la cronologia, salva il log completo della chat in un file e fai riferimento al percorso nel riepilogo. Se l'Agente ha bisogno di dettagli, può recuperarli dal file, rendendo la compressione un'operazione lossy ma tracciabile.
4. La Progettazione degli Strumenti Determina Cosa Può Fare un Agente
Il contesto determina cosa vede il modello; gli strumenti determinano cosa può fare. La qualità batte la quantità. Solo 5 server MCP possono costare circa 55.000 token nelle definizioni, quasi il 30% di un contesto di 200K prima ancora che la chat inizi. Troppi strumenti diluiscono l'attenzione del modello.
La maggior parte dei problemi con gli strumenti non riguarda averne troppo pochi, ma scegliere quello sbagliato, descrizioni incomprensibili o restituire dati inutili.

Come si Evolve la Progettazione degli Strumenti
La progettazione degli strumenti ha attraversato tre fasi. All'inizio, le API esistenti venivano semplicemente wrappate come strumenti. Successivamente, si è scoperto che gli errori di selezione erano spesso dovuti al fatto che gli strumenti erano progettati per ingegneri, non per Agenti.
1a Gen: Wrapping API: Ogni endpoint è uno strumento. Troppo granulare; gli Agenti devono coordinare più strumenti per un unico obiettivo.
2a Gen: ACI (Interfaccia Agente-Calcolatore): Gli strumenti corrispondono agli obiettivi dell'Agente, non alle API di basso livello. Invece di create_file e set_permissions, fornisci create_script(path, content, executable).
3a Gen: Uso Avanzato degli Strumenti: Ottimizzazione della scoperta e della chiamata:
- Ricerca Strumenti: Non infilare tutte le definizioni in una volta. Gli Agenti trovano le definizioni tramite
search_tools. La ritenzione del contesto raggiunge il 95%. - Chiamata Programmata degli Strumenti: Lascia che il modello usi il codice per orchestrare più chiamate. I risultati intermedi rimangono nell'ambiente di esecuzione, non nel contesto LLM. I token possono scendere da 150.000 a 2.000.
- Esempi di Utilizzo degli Strumenti: Ogni strumento ottiene 1-5 esempi reali. JSON Schema descrive i tipi, ma gli esempi mostrano l'utilizzo. La precisione può salire dal 72% al 90%.
Principi di Progettazione degli Strumenti ACI
La progettazione degli strumenti influisce direttamente sugli Agenti. Non si tratta solo di "può essere chiamato", ma di "può autocorreggersi se chiamato in modo errato?"
I progetti scadenti hanno parametri vaghi ed errori non correggibili. I buoni progetti usano betaZodTool per legare definizione e implementazione, usando Zod per vincoli di formato e suggerimenti di errore strutturati:
1const updateTool = betaZodTool({2 name: "update_yuque_post",3 description: "Aggiorna il contenuto di un post Yuque; non per creare nuovi post",4 inputSchema: z.object({5 post_id: z.string().describe("ID del post Yuque, stringa numerica come '12345678'"),6 title: z.string().optional().describe("Titolo del post, omettere se invariato"),7 content_markdown: z.string().describe("Corpo in Markdown"),8 }),9 run: async (input) => {10 const post = await getPost(input.post_id);11 if (!post) throw new ToolError("L'ID del post non esiste", {12 error_code: "POST_NOT_FOUND",13 suggestion: "Chiama prima list_yuque_posts per ottenere un post_id valido",14 });15 return await updatePost(input.post_id, input.title, input.content_markdown);16 },17});

Un cattivo design dice solo cosa fa, non quando usarlo. Un buon design ACI ha confini chiari ed errori strutturati, aiutando gli Agenti a scegliere correttamente e a risolvere rapidamente i fallimenti. Esegui il debug degli strumenti per primo; la maggior parte degli errori è nelle descrizioni, non nella capacità del modello.
Perché Isolare i Messaggi degli Strumenti?
I framework generano eventi interni (compressione, notifiche). Questi dovrebbero essere nella cronologia della sessione ma non inviati all'LLM, poiché sprecano token e confondono il modello. La soluzione sono due tipi di messaggi: AgentMessage per il layer dell'app (con campi personalizzati) e Message standard (user, assistant, tool_result) per l'LLM.
5. Progettare il Sistema di Memoria
Gli Agenti mancano di continuità temporale nativa. Il contesto viene cancellato dopo una sessione. Per ottenere coerenza tra sessioni, un layer di memoria deve essere progettato come infrastruttura, non come un ripensamento.
Dove Vivono i Quattro Tipi di Memoria?
Categorizzati dal problema che risolvono:
- Finestra di Contesto (Memoria di Lavoro): Informazioni minime per il compito corrente. Token limitati; deve essere gestita.
- Competenze (Memoria Procedurale): Come fare le cose (flussi di lavoro, norme). Caricate su richiesta.
- Cronologia Sessione JSONL (Memoria Episodica): Cosa è successo. Persistita su disco; ricercabile.
- MEMORY.md (Memoria Semantica): Fatti stabili scritti dall'Agente. Iniettati nei prompt di sistema.

Come Collaborano MEMORY.md e le Competenze
Il nucleo è mantenere i fatti importanti controllando il volume dei contenuti.
Memoria a 4 Strati di ChatGPT: Struttura semplice. Metadati di Sessione (non persistiti), Memoria Utente (~33 fatti, persistiti/iniettati), Riepilogo Conversazione (~15 riepiloghi recenti, persistiti), Sessione Corrente (finestra scorrevole).
Recupero Ibrido di OpenClaw: Log giornalieri (memory/YYYY-MM-DD.md), MEMORY.md per fatti curati e memory_search che utilizza recupero ibrido (70% similarità vettoriale + 30% parole chiave). Per la maggior parte degli Agenti, Markdown strutturato + ricerca per parole chiave è sufficiente per la debuggabilità e il costo.
Attivazione e Rollback del Consolidamento della Memoria

Quando tokenUsage / maxTokens >= 0.5, attiva il consolidamento. Riepiloga i messaggi, aggiungi a MEMORY.md e aggiorna l'indice. Se fallisce, scrivi i messaggi grezzi in un archivio. Il processo deve essere reversibile; sposta i puntatori, non eliminare i dati grezzi.
6. Aumentare Gradualmente l'Autonomia dell'Agente
L'autonomia richiede tre infrastrutture: ripresa tra sessioni, vincoli di progresso all'interno della sessione e I/O in background per compiti lenti.
Come Continuare Compiti Lunghi Tra Sessioni
I compiti lunghi falliscono quando le sessioni terminano prima del completamento. Un approccio stabile utilizza un Agente Inizializzatore e un Agente di Codifica. L'Inizializzatore viene eseguito una volta per creare feature-list.json, init.sh e claude-progress.txt. L'Agente di Codifica viene quindi eseguito in più sessioni, riprendendo da questi file, implementando una funzionalità, eseguendo test e aggiornando il file di progresso. Questo rende il compito uno stato esterno.

Mantieni i progressi nei file, non nel contesto. Usa JSON per la struttura. Il compito è completato solo quando tutte le funzionalità in feature-list.json hanno passes: true.
Perché Scrivere Esplicitamente lo Stato del Compito?
Senza ancore esterne, gli Agenti deviano o terminano prematuramente. Registra lo stato come oggetto di controllo esterno:
1{2 "tasks": [3 {"id": "1", "desc": "Leggi configurazione", "status": "completed"},4 {"id": "2", "desc": "Modifica schema", "status": "in_progress"}5 ]6}
Vincolo: solo un in_progress alla volta. Aggiorna lo stato dopo ogni passo.
Integrazione di I/O in Background
L'I/O lento (operazioni su file, rete) non dovrebbe bloccare il ciclo principale. Metti i sottoprocessi lenti in thread in background e inietta i risultati tramite una coda di notifica prima della successiva chiamata LLM. Questo è più manutenibile di un runtime asincrono complesso.
7. Organizzare Sistemi Multi-Agente
L'ingegneria dei sistemi multi-agente riguarda l'isolamento e la collaborazione.
Modalità Direttore: Sincrona. L'umano interagisce strettamente con un Agente. Il contesto viene perso quando la sessione termina.
Modalità Coordinatore: Delega asincrona. L'umano stabilisce gli obiettivi, gli Agenti lavorano in parallelo, l'umano rivede l'output. L'output diventa artefatti persistenti (PR, branch).

Un Orchestratore gestisce sub-agenti che lavorano in parallelo, comunicando tramite protocolli di posta in arrivo JSONL e utilizzando Worktrees per l'isolamento.

A Cosa Servono i Sub-Agenti?
La ricerca e il tentativo ed errore non dovrebbero inquinare il contesto dell'Agente principale. L'Agente principale ha bisogno solo della conclusione.
1const result = await runAgentLoop(task, { messages: [] });2return summarize(result); // Il contesto principale vede solo questa riga
Perché Scrivere la Collaborazione come Protocollo?
La collaborazione in linguaggio naturale fallisce quando gli Agenti dimenticano le promesse. Usa un protocollo strutturato:
1{ request_id, from_agent, to_agent, content, status: 'pending', timestamp }
Usa una posta in arrivo JSONL append-only per il ripristino da crash. Prima isolamento, poi collaborazione.

Le Allucinazioni si Amplificano nei Sistemi Multi-Agente
Gli errori si propagano a cascata tra gli Agenti. La convalida incrociata interrompe questa catena facendo giudicare la conclusione da un Agente indipendente o da feedback esterni (test, compilatori).

8. Come Valutare gli Agenti
La valutazione richiede casi di test, standard di punteggio e verifica automatizzata.

La valutazione tradizionale a turno singolo (Prompt -> Risposta) è insufficiente. La valutazione degli Agenti richiede strumenti e ambienti. Il punteggio si basa su ciò che è successo nell'ambiente, non solo su ciò che l'Agente ha detto.

Concetti chiave: Task, Trial, Grader. Transcript (log di esecuzione) vs Outcome (stato finale). Servono entrambi. Un Agente potrebbe dire "biglietto prenotato" (transcript) ma non riuscire a creare il record nel database (outcome).
Stato e metriche di valutazione
Molti team si affidano ancora alla revisione manuale o a giudici LLM. Metriche comuni: Pass@k (può teoricamente farlo?) e Pass^k (è stabile per la produzione?). Non mescolarle.

Tre tipi di valutatori
- Valutatori di codice: corrispondenza di stringhe, test unitari. Massima certezza.
- Valutatori modello: giudici LLM basati su criteri. Buoni per la qualità semantica.
- Valutatori umani: revisione di esperti. Lento ma stabilisce la baseline.
Costruire un sistema di valutazione da zero
Inizia con 20-50 casi di fallimento reali. Assicura l'isolamento dell'ambiente in modo che i test non si contaminino a vicenda. Includi sia casi positivi che negativi. Se due esperti non sono d'accordo su un caso, i criteri non sono ancora chiari.
Ripara la valutazione prima di riparare l'agente
Se i punteggi calano, controlla prima il sistema di valutazione. I problemi ambientali (limiti di memoria, bug nei valutatori) sembrano degradazione del modello.

9. Tracciare il processo di esecuzione
Senza tracce, i fallimenti non possono essere riprodotti. Le metriche APM (latenza, tasso di errore) non bastano; serve la catena di ragionamento.
Cosa registrare in una traccia?
Prompt completo, messaggi multi-round, chiamate/argomenti/ritorni degli strumenti, catena di pensiero, output finale, token e latenza.
Osservabilità a due livelli
- Campionamento manuale: campionamento basato su regole di errori o feedback negativi per trovare pattern di fallimento.
- Auto-valutazione LLM: copertura completa delle tracce usando il livello manuale come baseline di calibrazione.

Flussi di eventi come fondamento
Emette eventi a tool_start, tool_end e turn_end. I sistemi a valle (log, UI, valutazione) consumano questi eventi senza modificare il codice del loop principale.

10. Implementare agenti con OpenClaw
OpenClaw utilizza cinque livelli disaccoppiati: Gateway, Adattatori di canale, Agente Pi (loop principale), Set di strumenti (design ACI) e Contesto/Memoria.

Disaccoppiamento del bus di messaggi
Un bus di messaggi separa i canali dall'agente. I canali gestiscono solo I/O; l'agente gestisce solo l'elaborazione.
Prompt di sistema a livelli
SOUL.md definisce identità e standard di completamento. I prompt sono stratificati: info di runtime -> Identità -> Memoria -> Competenze -> Iniezione dinamica.

Prima i confini di sicurezza
Prima di aggiungere funzionalità, stabilisci: Whitelist utente, Isolamento dell'area di lavoro (controlli dei percorsi) e Log di audit.
Protezione dall'iniezione di prompt: tratta il contenuto esterno come non affidabile. Usa la separazione sorgente-pozzetto. Non dare agli agenti strumenti di cui non hanno bisogno. Richiedi conferma umana esplicita per azioni sensibili.
Fallback del provider: passa automaticamente da un provider all'altro (Anthropic -> OpenAI) se uno fallisce.
11. Anti-pattern comuni
- Prompt di sistema come base di conoscenza (troppo lungo).
- Proliferazione di strumenti (l'agente sceglie strumenti sbagliati).
- Mancanza di cicli di verifica.
- Sistemi multi-agente senza confini.
- Nessun consolidamento della memoria (la qualità cala dopo 20 round).
- Nessun sistema di valutazione.
- Complessità multi-agente prematura.
- Affidarsi alle aspettative invece che ai vincoli meccanici.
12. Conclusione
- Il nucleo dell'agente è un loop stabile; le nuove funzionalità dovrebbero essere esternalizzate.
- L'Harness determina la convergenza più del modello.
- L'ingegneria del contesto previene il 'Context Rot'.
- Il design degli strumenti ACI si concentra sugli obiettivi e sulla correzione degli errori.
- La memoria è stratificata (di lavoro, procedurale, episodica, semantica).
- I compiti lunghi si basano su stato e file esternalizzati.
- I sistemi multi-agente necessitano di protocolli e isolamento.
- Valutazione Pass@k per la capacità, Pass^k per la qualità.
- Il tracciamento è il prerequisito per il debug.
- Gli agenti stabili si basano su dettagli ingegneristici come disaccoppiamento e confini di sicurezza.





