Il 90% del codice in Anthropic è scritto dagli agenti Claude. Non da ingegneri che scrivono in una finestra di chat. Da agenti autonomi che eseguono cicli, chiamano strumenti e spediscono codice mentre il team dorme.
Segui il mio Substack per ricevere alpha fresche sull'AI:
Questa è la configurazione esatta. Passo dopo passo. Dalla prima chiamata API a un agente funzionante che puoi puntare a qualsiasi attività.
Questo articolo coprirà:
1 – perché la maggior parte degli "agenti" che le persone costruiscono non sono agenti
2 – le 5 parti di cui ogni agente funzionante ha bisogno
3 – come costruire ogni parte con Claude, con codice
4 – gli errori che uccidono gli agenti prima che vengano spediti
Metti questo articolo tra i preferiti. Ogni blocco di codice qui sotto funziona.
01. La maggior parte degli "agenti AI" non sono agenti
Ho costruito e rotto più agenti di quanti ne possa contare. Li ho visti bruciare token tutta la notte e non produrre nulla. Li ho visti riscrivere lo stesso file 30 volte. Li ho visti superare il proprio test cancellando il test.

Ogni fallimento mi ha insegnato la stessa lezione: il modello non è il problema. L'architettura intorno ad esso lo è. Questa guida è tutto ciò che ho imparato, compresso nel percorso più breve che posso darti.
Ecco cosa costruisce la maggior parte delle persone quando dice "agente AI":
1while True:2 user_input = input("> ")3 response = call_claude(user_input)4 print(response)
Questo è un chatbot. Aspetta te. Fa quello che dici tu. Dimentica tutto tra una sessione e l'altra. Quando chiudi la scheda, si ferma.
Un agente è un sistema che lavora verso un obiettivo senza che tu sia seduto di fronte ad esso. Scopre cosa deve essere fatto, fa un piano, esegue, controlla il risultato e, se non è ancora finito, riprova. Tu imposti la direzione. L'agente fa il lavoro.
"Claude Code è passato da zero a 400 milioni di dollari di entrate in pochi mesi. È iniziato come un progetto di hackathon. Usa ancora solo l'API pubblica." -
Boris Cherny, Head of Claude Code
La stessa API a cui hai accesso ora. Stessi modelli. La differenza è l'architettura intorno al modello.

02. Le 5 parti di un vero agente
Ogni agente funzionante – Claude Code, Devin, Codex, o qualsiasi cosa tu costruisca da solo – è assemblato da cinque parti. Ne manca una e si rompe.

03. Il livello API
Tutto inizia qui. Chiami Claude, Claude risponde. Ma il modo in cui lo chiami determina se ottieni un chatbot o un agente.

Tre cose contano: il prompt di sistema, l'output strutturato e la temperatura.
Il prompt di sistema non è un saluto. È il manuale operativo del tuo agente. Ogni regola, vincolo e comportamento va qui. Senza di esso, Claude indovina cosa vuoi. Con esso, Claude segue la tua specifica.
1import anthropic23client = anthropic.Anthropic()45response = client.messages.create(6 model="claude-sonnet-4-6",7 max_tokens=4096,8 system="""Sei un agente di revisione del codice.910Regole:11- Leggi l'intero diff prima di commentare12- Segnala solo bug reali, non preferenze di stile13- Se non c'è niente di sbagliato, scrivi "LGTM" e fermati14- Non suggerire mai modifiche che non hai testato mentalmente15- Formato output: array JSON di {file, line, issue, fix}""",16 messages=[{"role": "user", "content": diff_content}]17)
L'output strutturato rende la risposta del tuo agente leggibile dalla macchina. Se Claude restituisce testo libero, il tuo codice deve analizzarlo. Se Claude restituisce JSON, il tuo codice può usarlo direttamente.
1# Forza l'output JSON dicendo a Claude la forma esatta2system = """Restituisci SOLO JSON valido. Nessun markdown. Nessuna spiegazione.3Schema:4{5 "status": "pass" | "fail",6 "issues": [{"file": str, "line": int, "issue": str}],7 "summary": str8}"""
Temperatura. Impostala a 0 per agenti deterministici. Impostala a 0.3-0.5 per lavoro creativo. Il valore predefinito (1.0) aggiunge casualità che quasi mai vuoi in un agente.
04. Strumenti
Un modello senza strumenti può ragionare ma non può agire. Può dirti quale file modificare ma non può modificarlo. Può descrivere una query ma non può eseguirla.

L'uso degli strumenti di Claude ti permette di definire funzioni che il modello può chiamare. Descrivi la funzione. Claude decide quando chiamarla. Tu la esegui e restituisci il risultato. Claude usa il risultato per continuare a ragionare.
1tools = [{2 "name": "run_sql",3 "description": "Esegui una query SQL di sola lettura sul database",4 "input_schema": {5 "type": "object",6 "properties": {7 "query": {8 "type": "string",9 "description": "Query SQL SELECT da eseguire"10 }11 },12 "required": ["query"]13 }14},15{16 "name": "write_file",17 "description": "Scrivi contenuto in un file su disco",18 "input_schema": {19 "type": "object",20 "properties": {21 "path": {"type": "string"},22 "content": {"type": "string"}23 },24 "required": ["path", "content"]25 }26}]
La descrizione dello strumento conta più di quanto pensi. Claude la legge per decidere quando e come usare lo strumento. Una descrizione vaga significa chiamate errate. Una descrizione precisa significa chiamate accurate.
Inizia con 3-5 strumenti. Leggi file, scrivi file, esegui comando, cerca, e uno strumento specifico del dominio per il tuo caso d'uso. Questo copre il 90% dei compiti degli agenti.

05. Il ciclo
Questa è la parte che trasforma uno script in un agente. Senza un ciclo, il tuo codice chiama Claude una volta e si ferma. Con un ciclo, il tuo codice chiama Claude, controlla il risultato e chiama di nuovo fino a quando il lavoro è finito.

Tre componenti:
- Verificatore. Qualcosa che controlla se l'output è buono. Una suite di test, un type checker, un linter, una seconda chiamata a Claude con criteri rigorosi. Senza questo, l'agente concorda con se stesso in loop.
- Stato. Una registrazione di ciò che è successo. Cosa ha funzionato, cosa ha fallito, cosa provare dopo. Senza stato, l'agente fa lo stesso errore ad ogni passaggio.
- Condizione di arresto. L'obiettivo è raggiunto, o un limite massimo dice "dopo N tentativi, fermati e riporta." Senza questo, il ciclo gira all'infinito e prosciuga il tuo account.
1import json2from pathlib import Path34def run_agent(task: str, max_attempts: int = 5):5 state = {"task": task, "attempts": [], "done": False}67 for i in range(max_attempts):8 # Costruisci contesto dallo stato9 context = build_prompt(state)1011 # Chiama Claude con gli strumenti12 result = call_claude(context, tools)1314 # Esegui eventuali chiamate agli strumenti15 output = execute_tools(result)1617 # Verifica il risultato18 check = verify(output)1920 # Aggiorna stato21 state["attempts"].append({22 "attempt": i + 1,23 "action": result.summary,24 "passed": check.passed,25 "reason": check.reason26 })2728 if check.passed:29 state["done"] = True30 break3132 # Salva stato per la prossima esecuzione33 Path("state.json").write_text(json.dumps(state, indent=2))34 return state
Questo è lo scheletro completo. Ogni agente in produzione è una variazione di questo schema. I dettagli cambiano. La forma no.
06. Memoria
Senza memoria, ogni sessione parte da zero. L'agente riscopre la struttura del tuo progetto. Reimpara le tue convenzioni. Rifà gli errori che ha fatto ieri.

Gli agenti Claude usano tre livelli di memoria:
CLAUDE.md è un file markdown nella radice del tuo progetto. Claude Code lo legge automaticamente all'inizio di ogni sessione. Le tue regole, il tuo stack, le tue convenzioni. Scrivilo una volta, leggilo per sempre.
1# CLAUDE.md23## Progetto4API di gestione delle attività. Python 3.12, FastAPI, PostgreSQL.56## Regole7- Tutte le risposte: schema {data, error, meta}8- Test richiesti per ogni nuovo endpoint9- Messaggi di commit: tipo(ambito): descrizione10- Mai usare print() per logging. Usa structlog.1112## Problemi noti13- Il middleware di autenticazione prevede x-auth-token, non Authorization14- La suite di test impiega 45s completa. Usa --filter per iterazione.
Le skills catturano interi flussi di lavoro. Non solo prompt – la forma completa: formato di input, passaggi, formato di output, regole di validazione. La prima esecuzione richiede 20 minuti. La riproduzione richiede 30 secondi.
Il file delle lezioni è un registro continuo degli errori. L'agente scrive in esso dopo ogni sessione. La sessione successiva lo legge. Gli errori si ripetono finché non vengono scritti. Poi si fermano.
1# learnings.md23- L'API di pagamento si aspetta la chiave di idempotenza nell'header, non nel body4- PostgreSQL NOTIFY necessita di LISTEN esplicito nel connection pool5- Il rate limiter conta per chiave, non per IP. I test necessitano di chiavi uniche.
07. Il gate di verifica
Il gate è la parte più difficile da costruire e la più facile da saltare. La maggior parte delle persone lo salta. Questo è il motivo per cui la maggior parte degli agenti si rompe in produzione.

Un gate di verifica è qualcosa che controlla il lavoro dell'agente senza che l'agente si valuti da solo. Il modello che ha scritto il codice è troppo generoso nel valutare i propri compiti. Hai bisogno di un secondo controllo.
Tre schemi che funzionano:
1. Test automatizzati. L'agente scrive codice. La suite di test viene eseguita. Se i test falliscono, l'agente riceve l'output dell'errore e riprova. Questo è come funziona internamente Claude Code.
1def verify(output):2 # Esegui la suite di test3 result = subprocess.run(4 ["pytest", "tests/", "-x", "--tb=short"],5 capture_output=True, text=True6 )7 return {8 "passed": result.returncode == 0,9 "reason": result.stdout if result.returncode != 0 else "tutti i test passano"10 }
2. Type checker / linter. Esegui mypy, ruff, o tsc --noEmit dopo ogni modifica. Cattura intere categorie di bug senza scrivere un singolo test.
3. Secondo modello come revisore. Usa una chiamata Claude separata con un prompt di sistema rigoroso che cerca solo problemi. Lo scrittore è veloce ed economico. Il revisore è lento e rigoroso. Questa separazione è la maggior parte della qualità.
1# Prompt del revisore - separato dal costruttore2reviewer_system = """Sei un revisore di codice rigoroso.3Il tuo UNICO compito è trovare problemi.45Controlla:6- Il codice corrisponde alle specifiche?7- Ci sono casi limite non gestiti?8- Tutti i test testano effettivamente la cosa giusta?910Se tutto è corretto, rispondi: {"passed": true}11Se qualcosa è sbagliato, rispondi: {"passed": false, "issues": [...]}1213Non suggerire miglioramenti. Segnala solo bug reali."""
Lo scrittore è veloce ed economico. Il revisore è lento e rigoroso. Questa separazione è la maggior parte della qualità.
08. Mettere tutto insieme
Ecco un agente completo che prende l'URL di un'issue GitHub, legge l'issue, scrive il codice, esegue i test e apre una PR. Cinque parti che lavorano insieme.
1import anthropic, subprocess, json2from pathlib import Path34client = anthropic.Anthropic()5CLAUDE_MD = Path("CLAUDE.md").read_text()6LEARNINGS = Path("learnings.md").read_text()78SYSTEM = f"""Sei un agente di programmazione.9Leggi l'issue. Scrivi la correzione. Esegui i test.1011Contesto del progetto:12{CLAUDE_MD}1314Problemi noti:15{LEARNINGS}1617Regole:18- Leggi l'intero codebase prima di modificare qualsiasi cosa19- Scrivi test per ogni modifica20- Se i test falliscono, correggi il codice, non i test21- Fermati quando tutti i test passano"""2223TOOLS = [24 read_file_tool,25 write_file_tool,26 run_command_tool,27 search_codebase_tool,28]2930def run(issue_text, max_attempts=5):31 messages = [{"role": "user", "content": issue_text}]3233 for attempt in range(max_attempts):34 # Chiama Claude35 response = client.messages.create(36 model="claude-sonnet-4-6",37 max_tokens=8192,38 system=SYSTEM,39 tools=TOOLS,40 messages=messages41 )4243 # Esegui le chiamate agli strumenti44 messages = handle_tool_use(response, messages)4546 # Verifica: esegui i test47 test_result = subprocess.run(48 ["pytest", "-x", "--tb=short"],49 capture_output=True, text=True50 )5152 if test_result.returncode == 0:53 print(f"Fatto in {attempt + 1} tentativi")54 return True5556 # Reinserisci il fallimento nel ciclo57 messages.append({58 "role": "user",59 "content": f"Test falliti:\n{test_result.stdout}\nCorreggi e riprova."60 })6162 return False
Questo è un agente funzionante. Livello API con prompt di sistema e CLAUDE.md. Strumenti per operazioni sui file. Un ciclo con riprova. Memoria da learnings.md. Un gate di verifica tramite pytest.
Meno di 50 righe. La stessa architettura che Claude Code usa internamente.
**
09. I 5 errori che rompono ogni agente
- Nessun gate di verifica. L'agente valuta i propri compiti. Scrive codice, dice "sembra buono" e va avanti. L'output sembra giusto e si rompe in produzione.
- Nessuna condizione di arresto. Il ciclo gira finché la tua bolletta API non è di $200. Senza un limite massimo, l'agente riprova all'infinito, riscrivendo lo stesso file 40 volte. Imposta sempre max_attempts. Sempre.
- Nessun file di stato. Stesso errore al tentativo #1 e al tentativo #50. L'agente non sa cosa ha già provato. Propone la stessa correzione rotta tre volte di fila perché nulla registra il fallimento.
- Troppi strumenti. Dai a Claude 20 strumenti e sceglie quello sbagliato. Un modello con 5 strumenti chiari fa scelte migliori di un modello con 20 sovrapposti. Inizia in piccolo. Aggiungi strumenti solo quando l'agente incontra un muro.
- Prompt di sistema vago. "Sii un buon assistente di programmazione" ti dà output generico. "Tutte le risposte devono essere JSON valido, test richiesti per ogni modifica, non modificare mai file al di fuori di /src" ti dà un agente che si comporta.
Conclusione:
Un agente funzionante non è un prompt migliore. È un sistema: API + strumenti + ciclo + memoria + gate di verifica. Cinque parti. Ne manca una e si rompe.
La maggior parte delle persone leggerà questo, lo metterà tra i preferiti e continuerà a usare Claude come chatbot. Incolleranno una domanda alla volta e copieranno la risposta nel loro codebase a mano.
Quelli che costruiranno il ciclo spediranno lavoro mentre dormono. Stesso modello. Stessa API. Stesso prezzo. Architettura diversa.
I blocchi di codice sopra funzionano tutti. Copiali. Esegui. Modificali per il tuo caso d'uso.
Costruisci un agente questa settimana. Puntalo a un compito che fai ogni giorno. Lascialo eseguire.





