Costruiamo l'harness di Claude Code (passo dopo passo)

@akshay_pachaar
INGLESE6 giorni fa · 15 lug 2026
202K
841
122
29
1.9K

TL;DR

Un tutorial completo sulla creazione di un harness per agenti di programmazione tramite CrewAI. Copre il ciclo di esecuzione principale, la delega gerarchica, l'esecuzione in sandbox e la memoria persistente per ottenere un'affidabilità pari a quella di Claude Code.

Traduzione in italiano:

Tratteremo tutto ciò che serve per costruire un harness di codifica: il ciclo dell'agente, la pianificazione, i sottoagenti, il sandboxing, la memoria e il checkpointing, costruiti passo dopo passo.

Se hai mai provato a costruire il tuo agente di codifica, sai come va. Colleghi un modello a strumenti per file e a una shell, lo punti a un codice reale, e si rompe dopo una dozzina di chiamate agli strumenti.

Legge i file sbagliati, perde l'obiettivo a metà strada e riempie il suo contesto con output che non gli servono più.

Poi lo stesso compito passa attraverso Claude Code e viene completato senza problemi. La conclusione facile è che Anthropic ha semplicemente un modello migliore, e questa conclusione ignora dove avviene realmente il lavoro.

La differenza è l'harness. Un harness è il codice ordinario che avvolge il modello: gestisce pianificazione, esecuzione degli strumenti, memoria e sicurezza, mentre il modello decide solo il passo successivo.

Ecco come appare un agente completamente harnessato quando lo si schematizza:

Akshay 🚀 - inline image

GIF

L'immagine sembra complessa, ma si divide in quattro gruppi:

  • Memoria fornisce al modello il suo contesto di lavoro più i fatti appresi tra sessioni diverse.
  • Competenze codificano come l'agente deve operare, ovvero le procedure, i vincoli e le euristiche che segue.
  • Protocolli collegano l'agente a utenti, strumenti e altri agenti.
  • Il nucleo dell'harness tiene tutto insieme con orchestrazione dei sottoagenti, sandbox, valutatore, ciclo di approvazione, osservabilità e compressione del contesto.

Anthropic descrive questa suddivisione come cervello e mani. Il modello è il cervello che sceglie ogni azione, e l'harness sono le mani che la eseguono e mantengono il run in carreggiata.

Quindi il divario tra il tuo agente e Claude Code non è il modello, ma la macchina attorno al modello.

Claude Code è uno degli harness più capaci in produzione oggi, ed è costruito da un numero sorprendentemente piccolo di strati di quell'illustrazione. Per vedere quanta di quella macchina dovresti costruire da solo, l'ho ricostruita in CrewAI, un framework open-source per orchestrare agenti.

Più di quanto mi aspettassi si mappa su funzionalità integrate, e la parte che non lo fa è dove vive la vera ingegneria.

Costruiamolo strato per strato, partendo dal ciclo centrale e aggiungendo pianificazione, sottoagenti, sandboxing e memoria. A ogni passo segneremo dove finisce il framework e dove inizia il tuo lavoro.

Come funziona l'harness di Claude Code

Al centro di Claude Code c'è un semplice ciclo dell'agente. Invi un messaggio, il modello decide cosa fare dopo, e o risponde direttamente o richiede uno strumento. Se lo richiede, lo strumento viene eseguito, il risultato torna nella conversazione e il modello decide di nuovo.

Questo si ripete finché il modello non restituisce una risposta finale senza ulteriori chiamate a strumenti.

All'interno di quel ciclo, il modello legge file, modifica codice, esegue comandi shell e lancia test. Non sono modalità separate. Sono solo diverse chiamate a strumenti all'interno dello stesso ciclo.

Il ciclo da solo non è sufficiente per un agente di codifica affidabile, però. Claude Code aggiunge pianificazione, strumenti per file, sottoagenti, memoria e un sistema di permessi e sandbox attorno. Questi strati non sostituiscono il ciclo, lo rendono sicuro e affidabile per il lavoro reale.

Akshay 🚀 - inline image

Questa è l'architettura che ricostruiremo: prima il ciclo centrale, poi ogni strato sopra, mappando ogni strato alla funzionalità di CrewAI che lo gestisce.

Il ciclo centrale dell'agente

Il ciclo esegue la stessa sequenza finché il compito non è completato:

  1. Chiedi al modello di eseguire il compito.
  2. Il modello risponde direttamente o richiede uno o più strumenti.
  3. Se vengono richiesti strumenti, eseguili e restituisci i risultati al modello.
  4. Ripeti con la conversazione aggiornata.
  5. Quando il modello risponde senza richiedere alcuno strumento, il compito è completato.
Akshay 🚀 - inline image
python
1while True:
2 reply = model(messages, tools)
3 calls = [b for b in reply if b.type == "tool_use"]
4 if not calls: # plain text, no tool call: the job is done
5 return reply.text
6 messages += [reply, run_all(calls)]

Ogni chiamata a uno strumento completa un passo, fornisce al modello nuove informazioni e alimenta la decisione successiva. Una domanda semplice potrebbe richiedere una sola iterazione, mentre correggere un bug complesso o rifattorizzare un grande codice può richiedere dozzine di iterazioni prima che il modello abbia abbastanza per produrre una risposta finale.

CrewAI fornisce automaticamente questo ciclo di esecuzione non appena crei un agente. Non implementi tu il ciclo while, definisci l'agente e gli assegni un compito.

Costruire il primo agente

Creiamo un semplice agente Bug Fixer.

python
1from crewai import LLM, Agent, Crew, Task
2
3bug_fixer = Agent(
4 role="Bug Fixer",
5 goal="Find and describe the fix for the reported bug in the codebase.",
6 backstory="You read directories and files to build an accurate picture of the code.",
7 llm="claude-sonnet-4-6",
8)
9
10task = Task(
11 description="Find the fix for {objective}.",
12 expected_output="A short description of the fix and which file it belongs in.",
13)
14
15result = Crew(agents=[bug_fixer], tasks=[task]).kickoff(
16 inputs={"objective": "the overdraft bug in account.py"}
17)

Tre concetti da capire qui:

  • Un Agent definisce chi fa il lavoro, attraverso il suo ruolo, obiettivo, LLM e strumenti.
  • Un Task descrive l'incarico.
  • Un Crew mette insieme agenti e compiti. Chiamare kickoff() esegue lo stesso ciclo di esecuzione descritto sopra, indipendentemente dal fatto che il modello sottostante sia Anthropic, OpenAI, Google o altro.

Dare strumenti all'agente

Gli strumenti sono ciò che permette a un modello che genera solo testo di lavorare effettivamente su un codice. Leggono file, li scrivono, eseguono comandi shell e chiamano API esterne.

CrewAI fornisce strumenti per il file system pronti all'uso:

  • FileReadTool legge file.
  • DirectoryReadTool elenca directory.
  • FileWriterTool scrive file.
python
1from crewai_tools import DirectoryReadTool, FileReadTool, FileWriterTool
2
3read_file = FileReadTool()
4write_file = FileWriterTool()
5list_dir = DirectoryReadTool()
6
7filesystem_tools = [read_file, write_file, list_dir]

Questi fungono anche da memoria esterna. Invece di tenere un grande risultato di ricerca nella finestra di contesto del modello, l'agente può scriverlo in un file, conservare solo il nome del file e rileggerlo quando necessario.

Questo mantiene la finestra di contesto più piccola e il modello più concentrato, ciò che Anthropic chiama ingegneria del contesto.

Akshay 🚀 - inline image

Gli strumenti integrati coprono solo i flussi di lavoro comuni. Per qualsiasi cosa più specifica, esponi una funzione Python come strumento con il decoratore @tool.

La docstring funge da manuale di istruzioni, dicendo al modello cosa fa lo strumento, quando usarlo e cosa si aspetta come input.

python
1from crewai.tools import tool
2import subprocess
3
4@tool("run_tests")
5def run_tests(path: str = "tests/") -> str:
6 """Run the pytest suite at the given path and return the result."""
7 result = subprocess.run(
8 ["pytest", path, "-q"], capture_output=True, text=True, timeout=120
9 )
10 output = result.stdout + result.stderr
11 return output[-4000:] if len(output) > 4000 else output

Pianificare compiti di lunga durata

Man mano che i compiti diventano più complessi, un semplice ciclo di esecuzione inizia a perdere traccia dell'obiettivo originale. Dopo abbastanza chiamate a strumenti, letture di file e risultati intermedi, il contesto si riempie e l'obiettivo viene messo in ombra da tutto ciò che è venuto dopo.

Questo lento degrado è ciò che le persone chiamano marciume del contesto.

La pianificazione lo affronta direttamente. L'agente costruisce un piano passo dopo passo prima di fare qualsiasi lavoro e mantiene quel piano nel contesto durante l'esecuzione.

Il piano non fa il lavoro. È una tabella di marcia che tiene il modello connesso all'obiettivo originale, lo stesso lavoro che fa la lista delle cose da fare di Claude Code.

Akshay 🚀 - inline image

CrewAI aggiunge questo a livello di crew con planning=True. Genera un piano prima dell'esecuzione e lo mantiene disponibile mentre il compito procede.

python
1from crewai import Crew, LLM
2
3crew = Crew(
4 agents=self.agents,
5 tasks=self.tasks,
6 planning=True,
7 planning_llm=LLM(model="gpt-4o-mini"),
8)

Nota: Di default, CrewAI usa gpt-4o-mini per la pianificazione, e puoi sostituirlo con qualsiasi LLM preferisci per quel passaggio.

I singoli agenti possono anche ragionare sul proprio lavoro con reasoning=True:

python
1from crewai import Agent
2
3bug_fixer = Agent(
4 role="Bug Fixer",
5 goal="Find and describe the fix for the reported bug in the codebase.",
6 backstory="You read directories and files to build an accurate picture of the code.",
7 tools=[FileReadTool()],
8 reasoning=True,
9 max_reasoning_attempts=3 # Optional: Set a maximum number of reasoning attempts
10)

Pianificazione e ragionamento risolvono problemi diversi. La pianificazione costruisce una tabella di marcia di alto livello per l'intero compito, mentre il ragionamento dà a un agente il tempo di pensare al proprio approccio prima di agire.

Quando il ragionamento è abilitato, l'agente:

  1. Riflette sul compito e abbozza un piano di esecuzione.
  2. Valuta se il piano è pronto.
  3. Raffina il piano se necessario, finché non è soddisfatto o raggiunge max_reasoning_attempts.
  4. Inietta il piano di ragionamento finalizzato nel compito prima dell'esecuzione.
Akshay 🚀 - inline image

Insieme, mantengono l'agente ancorato su compiti di lunga durata e riducono la deriva dall'obiettivo originale.

Delegare con sottoagenti

La pianificazione mantiene l'agente concentrato, ma non riduce la quantità di informazioni che il modello deve tenere. Su un grande codice, anche un compito ben pianificato può superare una singola finestra di contesto.

Trovare un bug può richiedere la lettura di dozzine di file, e l'agente principale non ha bisogno di tenerli tutti in memoria.

I sottoagenti risolvono questo attraverso la delega. L'agente principale affida un compito specifico a un agente aiutante, che lavora nel proprio contesto e restituisce un breve riepilogo. L'agente principale vede la conclusione, non i passaggi intermedi.

Akshay 🚀 - inline image

CrewAI supporta questo attraverso workflow gerarchici, dove un agente manager delega ad agenti specializzati e combina i loro risultati.

Nella nostra configurazione precedente, un singolo agente Bug Fixer faceva tutto il lavoro pesante. Dividiamo il lavoro tra un manager e tre specialisti:

  • Codebase Explorer esplora il codice e mappa il repository.
  • Software Engineer implementa la modifica richiesta.
  • Test Runner esegue i test nel sandbox e riporta successo o fallimento.
  • Engineering Lead supervisiona i tre specialisti.
Akshay 🚀 - inline image
python
1from crewai import Crew, Agent, Task, Process
2
3explorer = Agent(
4 role="Codebase Explorer",
5 goal="Map the repository and surface the files relevant to the task.",
6 backstory="You read directories and files to build a picture of the code.",
7 tools=[read_file, list_dir],
8 llm=llm,
9) # Same for other two specialist agents
10
11manager = Agent(
12 role="Engineering Lead",
13 goal="Break the request into steps and delegate each to the right specialist.",
14 backstory="You decide who does what, review tests, finish once change is done.",
15 llm=llm,
16 allow_delegation=True,
17)
18
19crew = Crew(
20 agents=[explorer, coder, tester],
21 tasks=[task],
22 manager_agent=manager,
23 process=Process.hierarchical,
24)

Una cosa da notare è che allow_delegation è disabilitato per impostazione predefinita, quindi deve essere esplicitamente abilitato sul manager.

Sandboxing: proteggere l'esecuzione dell'agente

Un agente con accesso alla shell può eseguire un comando distruttivo, e dire al modello di non fare qualcosa non è una salvaguardia.

La protezione reale viene da due strati:

  1. Un sistema di permessi che richiede approvazione per azioni sensibili.
  2. Un sandbox che isola l'esecuzione, in modo che anche i comandi approvati non possano toccare la macchina host.

Anthropic usa lo stesso approccio. Spostare l'esecuzione del codice in un sandbox riduce la frequenza con cui un utente deve approvare azioni, pur proteggendo il sistema host.

Akshay 🚀 - inline image

Sandboxing in CrewAI

Eseguire il codice all'interno di un sandbox anziché sulla macchina host applica quel secondo strato. In questa configurazione, il codice viene eseguito all'interno di E2B, che avvia una VM fresca per sessione e la distrugge dopo.

I comandi shell e Python vengono eseguiti interamente in quell'ambiente isolato.

Akshay 🚀 - inline image
python
1from crewai_tools import E2BExecTool, E2BPythonTool
2sandbox_tools = [E2BExecTool(), E2BPythonTool()] # run tests / run code

Approvazione umana nel ciclo

Impostare human_input=True su un Task mette in pausa la crew dopo che ha generato una risposta. Esamini l'output, poi lo approvi o lo rimandi indietro per un'altra iterazione.

Quando l'esecuzione raggiunge quel compito, CrewAI aspetta il tuo feedback attraverso l'input standard.

python
1from crewai import Task
2
3task = Task(
4 description=(
5 "In the working directory ./workspace, {objective}. "
6 "Explore the code first, make the change, then run the tests and report."
7 ),
8 expected_output="A summary of the files changed and the final test output.",
9 human_input=True,
10)

Se la tua crew viene eseguita dietro un'app web o un'interfaccia chat invece di un terminale, il sistema di intervento umano basato su webhook di CrewAI gestisce lo stesso passaggio di revisione.

Memoria e checkpointing

Per impostazione predefinita, un agente dimentica tutto una volta che un run termina. Torna domani per correggere un altro bug nello stesso progetto, e ricomincia da zero.

Due meccanismi permettono a un agente di portare informazioni tra run diversi, e ciascuno serve a uno scopo diverso:

  • Checkpointing salva lo stato dell'agente durante un run, in modo che possa riprendere dopo un'interruzione o continuare dallo stesso punto lungo un percorso diverso.
  • Memoria persistente memorizza fatti tra conversazioni separate, incluse preferenze di progetto come "formatta sempre il codice finale prima di finire."
Akshay 🚀 - inline image

Memoria in CrewAI

CrewAI fornisce un'interfaccia Memory unificata piuttosto che tipi separati di memoria a breve termine, a lungo termine, entità ed esterna. Quando salva, usa un LLM per identificare dettagli importanti, organizzarli e renderli recuperabili in seguito.

Impostare memory=True sulla crew le dà memoria tra run diversi. Dopo ogni compito, CrewAI estrae fatti utili dall'output e li memorizza, e nei run futuri recupera memorie rilevanti e le aggiunge al prompt del compito.

Akshay 🚀 - inline image
python
1from crewai import Crew
2
3crew = Crew(
4 agents=[explorer, coder, tester],
5 tasks=[task],
6 memory=True,
7)

Tutti gli agenti in una crew condividono la sua memoria a meno che un agente non ne riceva una propria.

Checkpointing in CrewAI

Un checkpoint è un'istantanea dello stato di avanzamento di un agente, inclusi la sua configurazione, lo stato del compito, la memoria, i risultati intermedi, gli input e la cronologia di esecuzione.

Per impostazione predefinita, CrewAI crea un checkpoint ogni volta che un compito termina, consentendo al flusso di lavoro di riprendere da quel punto se viene interrotto.

I checkpoint possono risiedere in uno di due archivi integrati:

  • JsonProvider salva ogni checkpoint come un file JSON separato, facile da leggere e ispezionare manualmente.
  • SqliteProvider memorizza tutti i checkpoint in un unico database SQLite, che regge meglio sotto checkpoint frequenti e carichi di lavoro più grandi.
Akshay 🚀 - inline image
python
1from crewai import Crew
2
3crew = Crew(
4 agents=[explorer, coder, tester],
5 tasks=[task],
6 checkpoint=True,
7)

Crew, Flow e Agent accettano tutti un argomento checkpoint, e i figli ereditano dal genitore a meno che non impostino un proprio valore.

Mettere tutto insieme

Ecco l'harness completo su un compito, con il ciclo di esecuzione, strumenti, pianificazione, sottoagenti, sandboxing e memoria che lavorano insieme:

python
1from crewai import Agent, Crew, LLM, Process, Task
2from crewai.tools import tool
3from crewai_tools import (DirectoryReadTool, FileReadTool, FileWriterTool,
4E2BExecTool, E2BPythonTool)
5
6llm = LLM(model="anthropic/claude-sonnet-4.6")
7
8list_dir = DirectoryReadTool(directory="./workspace")
9filesystem_tools = [FileReadTool(), FileWriterTool(), list_dir]
10sandbox_tools = [exec_tool, E2BPythonTool()]
11
12@tool("run_tests")
13def run_tests(path: str = "tests/") -> str:
14 """Sync ./workspace into the sandbox, then run pytest there."""
15 return E2BExecTool().run(command=sync_and_test_command(path))
16
17explorer = Agent(role="Codebase Explorer", goal="Map repo, surface relevant files.",
18 tools=[read_file, list_dir], llm=llm)
19coder = Agent(role="Software Engineer", goal="Implement requested change.",
20 tools=filesystem_tools, reasoning=True, llm=llm)
21tester = Agent(role="Test Runner", goal="Run tests in sandbox, report pass/fail.",
22 tools=sandbox_tools + [read_file] + [run_tests], llm=llm)
23manager = Agent(role="Engineering Lead", goal="Delegate steps, finish once tests pass.",
24 allow_delegation=True, llm=llm)
25
26task = Task(
27 description="In ./workspace, {objective}. Explore, edit, test, report.",
28 expected_output="Summary of changes and test output.", human_input=True,
29)
30crew = Crew(
31 agents=[explorer, coder, tester], tasks=[task],
32 manager_agent=manager, process=Process.hierarchical,
33 planning=True, memory=True, checkpoint=True,
34)
35result = crew.kickoff(inputs={"objective": "fix failing tests in account.py"})

Gli harness per agenti sono più facili da valutare quando il successo può essere verificato automaticamente. Una suite di test dà all'agente un obiettivo concreto, così può pianificare, modificare, testare e ripetere finché tutto non passa.

Quindi questo è stato testato su un piccolo codice, una classe BankAccount con due bug reali e cinque test, di cui tre fallivano. La regola era correggere solo l'implementazione, non i test.

Questo rispecchia come Anthropic valuta internamente gli agenti di codifica. Un esempio pubblicato mostra Claude che ricostruisce un clone dell'interfaccia claude.ai contro una grande suite di test falliti.

Qui, l'harness ha portato il progetto da 3 falliti e 2 superati a tutti e 5 superati, con la regola di solo implementazione che chiudeva la scorciatoia di modificare o rimuovere i test falliti.

Akshay 🚀 - inline image

Cosa resta compito tuo

Alcune parti del sistema non sono cose che il framework costruisce per te:

  • I prompt. Il comportamento di ogni agente deriva dal suo ruolo, obiettivo e backstory. Ottenerli corretti richiede test e iterazione, e nessun flag di configurazione lo sostituisce.
  • L'ambiente di esecuzione. Il sandbox, che sia E2B o una VM autogestita, deve essere configurato e collegato.
  • La selezione degli strumenti. Quali strumenti riceve ogni agente, e quale agente dovrebbe avere accesso a cosa, è una decisione progettuale che il framework non prende.

C'è anche un costo per l'harness stesso. Pianificazione, sottoagenti e cicli aggiungono chiamate API, quindi una configurazione complessa di agenti può finire per essere più costosa di un compito che una singola chiamata al modello avrebbe risolto direttamente.

E c'è una limitazione a lungo termine che vale la pena tenere a mente. Man mano che i modelli migliorano, parte dell'impalcatura cessa di essere necessaria, perché parte di ciò che viene costruito in un harness oggi è una soluzione alternativa per i limiti dei modelli attuali, piuttosto che un requisito permanente.

Anthropic originariamente usava reset di contesto per impedire a Claude Sonnet 4.5 di terminare i compiti troppo presto, e non erano più necessari con il più capace Claude Opus 4.5.

Akshay 🚀 - inline image

Concludendo

Questa è l'intera scoperta. La capacità di un agente di codifica risiede principalmente nell'harness, e un framework di orchestrazione ti offre più di quell'harness di quanto penseresti.

Il ciclo, la pianificazione, la delega, il sandboxing e la memoria arrivano tutti come configurazione, mentre i prompt, l'ambiente di esecuzione e le scelte degli strumenti rimangono tuoi.

Se vuoi eseguirlo sul tuo codice, la documentazione di CrewAI copre ogni funzionalità usata qui, e il framework è completamente open source.

Vedi la documentazione di CrewAI →

Trova tutto il codice qui →

Grazie per aver letto!

Saluti! :)

Salva con un clic

Leggi in profondità gli articoli virali con l’AI di YouMind

Salva la fonte, fai domande mirate, riassumi l’argomentazione e trasforma un articolo virale in note riutilizzabili in un unico spazio di lavoro AI.

Scopri YouMind
Per i creator

Trasforma il tuo Markdown in un articolo 𝕏 pulito

Quando pubblichi i tuoi testi lunghi, formattare immagini, tabelle e blocchi di codice per 𝕏 è una seccatura. YouMind trasforma un'intera bozza Markdown in un articolo 𝕏 pulito e pronto da pubblicare.

Prova Markdown verso 𝕏

Altri pattern da decodificare

Articoli virali recenti

Esplora altri articoli virali