
Come creare agenti AI nel 2026 (Corso completo)
AI features
- Views
- 696K
- Likes
- 368
- Reposts
- 68
- Comments
- 22
- Bookmarks
- 1.2K
TL;DR
Un approfondimento tecnico sul runtime agentic-harness, che spiega come utilizzare un'architettura a tre livelli, sandbox remote e la compattazione del contesto per creare agenti AI resilienti e pronti per la produzione.
Reading the ITALIANO translation
ecco la verità che nessuno dice ai costruttori di AI.
la maggior parte di loro sta costruendo demo
tutto ciò che ti serve per costruire è
un agente AI di livello produttivo
TL;DR; se non vuoi leggerlo, dai questo link al tuo agente e fagli domande: ➡️https://github.com/codejunkie99/agentic-harness
ecco il tweet che ha dato il via a tutto
il problema è che la maggior parte degli ingegneri AI non ha una chiara idea di cosa costruire quando decide di prendere sul serio gli agenti.
alcuni si rivolgono a LangChain perché le demo multi-agente su YouTube sembrano pulite, e passano le due settimane successive a combattere con l'interoperabilità Python e i mismatch del runtime asincrono, per poi buttare tutto all'aria.
alcuni provano a costruire un layer di orchestrazione personalizzato da zero: un loop, un archivio di sessioni, un assemblatore di contesto, e non finiscono mai l'agente vero perché l'infrastruttura ha divorato la timeline.
altri copiano l'esempio del webhook hello-world, ottengono una risposta JSON, pensano di aver capito il sistema, e rilasciano qualcosa che si rompe la prima volta che una sessione supera i dieci minuti, un sandbox remoto va giù a metà compito, o la finestra di contesto si riempie senza compaction configurata.
il risultato è di solito lo stesso: tanta infrastruttura, nessun agente in produzione, e nessun modello mentale di come sia realmente un runtime per agenti in produzione.
se il tuo obiettivo è costruire e rilasciare agenti reali nel 2026, non hai bisogno di imparare sei framework.
devi capire un runtime abbastanza a fondo da possedere un agente di produzione dal gestore al deployment.
questo significa imparare a:
- cablare l'architettura a tre layer in modo che la logica del gestore sopravviva a cambi di provider e di target senza toccare il codice dell'agente
- usare sessioni e task correttamente in modo che i lavori lunghi non contaminino il proprio contesto
- scrivere ruoli e skill che modellano il comportamento del modello senza ricompilare nulla
- configurare la compaction in modo che sessioni di due ore non inizino ad allucinare dopo un'ora
- puntare HttpSessionEnv a sandbox remoti in modo che il binario giri in locale mentre l'esecuzione gira su Linux
- scegliere il target di build giusto: native, node o Cloudflare, senza riscrivere alcuna logica dell'agente tra di essi
- generare connettori invece di scrivere adattatori a mano, e capire perché questa distinzione conta sotto carico reale
questa guida è un walkthrough tecnico completo costruito dal codice base di agentic-harness, sei settimane di costruzione e rottura di agenti reali con esso, e le modalità di fallimento che hanno richiesto più tempo per il debug.
il pezzo è di oltre 4.000 PAROLE e attinge direttamente dal repository e dalla documentazione, non da riassunti di seconda mano o esempi a livello demo.
ma il suo vero valore è che ogni sezione ha un frammento di codice funzionante, una spiegazione chiara del perché è stata presa quella decisione, e l'esatta modalità di fallimento che incontrerai se la salti.
in questo modo, quando avrai finito di leggere, potrai possedere un agente di produzione dall'inizio alla fine, dal primo gestore al sandbox al job CI che lo esegue senza supervisione.
costruire questa comprensione ha richiesto più di 6 SETTIMANE di lavoro quotidiano con il codice base, per lo più a fare debug di cose che sembravano corrette prima di rompersi in condizioni reali.
ora entriamo nel vivo. ⬇️
La forma del progetto
due crate. un binario. ogni target di esecuzione è una scelta di configurazione, non una riscrittura.
- l'SDK è una libreria che importi in qualsiasi progetto Rust. il CLI la avvolge. il tuo agente è un binario Rust che inizia con
use agentic_harness::prelude::*. cargo buildè l'intera pipeline. nessun bundler. nessun passo di transpilazione. nessun runtime linguistico sulla macchina di destinazione. un eseguibile autonomo più unmanifest.json.
il vincolo di design che ha guidato tutto: lo stesso binario dell'agente deve poter girare sul tuo laptop in modalità interattiva, in un job di GitHub Actions che clona un repository fresco, contro un sandbox remoto E2B via HTTP, e su un boundary Cloudflare Worker senza cambiare una singola riga di logica dell'agente tra di essi.
ogni decisione in questo codice base esiste per onorare quel vincolo.
I 3 layer e perché ciascuno esiste
il modello mentale è tre anelli concentrici. sapere dove si trova ogni confine ti farà risparmiare più tempo di debug di qualsiasi altra cosa in questa guida.
il tuo codice Rust è l'anello esterno.
- scrivi gestori. i gestori ricevono un
AgentContext. chiamano sessioni. le sessioni chiamano il modello, leggono file, scrivono file, eseguono comandi shell, lanciano task, si connettono a server MCP. - non tocchi mai un client HTTP direttamente. non analizzi mai una risposta del modello direttamente. l'SDK gestisce entrambi.
l'harness è l'anello intermedio.
- gestisce il registro degli agenti, instrada l'identità per percorso URL, gestisce la persistenza delle sessioni tra le chiamate, la compaction del contesto quando le sessioni crescono, la scoperta di ruoli e skill, la precedenza nella selezione del modello, e il trait
ModelClientneutrale rispetto al provider. - questo ti permette di scambiare Anthropic con OpenAI con un'istanza locale di Ollama senza toccare il codice del gestore.
- l'harness è ciò che rende la logica del tuo agente riutilizzabile tra provider e target.
- è anche dove vengono gestite tutte le cose che si rompono in produzione: stato della sessione, overflow del contesto, fallimenti del provider, ordinamento delle richieste concorrenti.
i target di esecuzione sono l'anello interno.
- filesystem locale. checkout CI.
HttpSessionEnvpuntato a Daytona o E2B. boundary Cloudflare Worker. - all'harness non importa quale stai usando. ai tuoi gestori neanche. chiamano
session.shell()esession.write()e l'harness traduce quelle operazioni in ciò di cui il target sottostante ha bisogno. - questa separazione è il punto centrale. quando E2B rilascia una nuova versione dell'API, aggiorni il connettore, non la logica del tuo agente.
- quando Anthropic rilascia
claude-opus-4-7, aggiorniruntime.json, non i tuoi gestori. l'anello esterno rimane pulito perché l'anello intermedio assorbe tutto il cambiamento.
Configurazione runtime: il file che controlla il layer del modello
prima di scrivere un singolo gestore, hai bisogno di runtime.json nel tuo workspace.
mettilo in .agentic-harness/config.json o nella radice del workspace come agentic-harness.json. load_workspace_context() lo raccoglie automaticamente.
la selezione del modello a runtime segue questa precedenza:
PromptOptions::model(...): override per chiamata- i metadati del modello del ruolo selezionato: default per ruolo
defaultModeldalla configurazione runtime: default del workspace
la cosa da capire: l'ID del modello deve essere registrato prima di poterlo usare. openaiCompatibleModels è l'elenco che l'harness usa per cablare il client built-in di chat-completions. se il tuo modello non è in quell'elenco, ottieni un errore pulito all'avvio invece di un fallimento confuso a metà sessione.
per i gateway compatibili con OpenAI, la configurazione è la stessa. punta baseUrl al tuo gateway:
- non scrivere mai una chiave API letterale in
runtime.json. usaapiKeyEnve tieni la chiave reale nel tuo ambiente. - l'harness legge la variabile d'ambiente al momento della richiesta, non all'avvio — il che significa che puoi ruotare le chiavi senza riavviare il server.
L'identità dell'agente è un percorso URL, mai una ricerca nel registro
questa è stata la prima decisione di design che mi ha sorpreso. ora penso sia quella giusta.
non esiste un sistema di ID agente. nessuna chiave di registro. nessun UUID che generi da solo. l'identità del tuo agente è POST /agents/<nome>/<id>.
- l'harness gestisce tutta la contabilità dello stato della sessione dietro quell'URL.
- il motivo per cui funziona: ogni chiamante in ogni sistema sa già come costruire un ID significativo dal contesto. un numero di PR. un ID di esecuzione. un timestamp combinato con un nome di task. un handle utente.
- non hai bisogno di un endpoint di creazione sessione. non hai bisogno di memorizzare gli ID sessione separatamente. l'URL è la sessione.
il gestore dell'agente sul lato Rust chiama ctx.id() per ottenere l'ID fornito dal chiamante:
Sessioni: il contesto di esecuzione con stato
una sessione è più di un thread di conversazione. è il contesto di esecuzione completo per un'invocazione dell'agente.
contiene:
- cronologia dei messaggi con il modello
- accesso ai file del workspace (lettura, scrittura, modifica, grep, glob, stat, readdir)
- esecuzione shell con controllo di cwd e env
- registrazioni di strumenti (server MCP, strumenti personalizzati)
- il ruolo assegnato e la sua sovrapposizione di system prompt
- il budget di compaction e il watermark della cronologia
ottieni una sessione chiamando ctx.session_with_id() con qualsiasi ID abbia senso:
- le sessioni persistono tra le chiamate HTTP quando usi lo stesso ID. chiama lo stesso endpoint dell'agente tre volte con lo stesso ID di sessione, il modello vede tutti e tre gli scambi come una conversazione continua.
- la cronologia si accumula automaticamente. non la gestisci tu.
- questo è ciò che rende possibili flussi di lavoro multi-step senza gestire lo stato da solo. continui a chiamare
session.prompt()e l'harness gestisce tutto il resto.
quando hai bisogno di passare grandi quantità di contesto insieme a un prompt, leggi il file e formattalo inline:
la sessione gestisce il conteggio dei token in modo da non far traboccare accidentalmente la finestra di contesto a metà conversazione. quando sei vicino al budget, scatta la compaction. ne parleremo più avanti in una sezione successiva.
Task: sessioni figlie focalizzate che mantengono pulito il genitore
- questa è la primitiva che avrei voluto capire dal primo giorno. è la differenza tra agenti che rimangono coerenti per lavori lunghi e agenti che iniziano ad allucinare a metà.
- un task è una sessione figlia monouso. cronologia fresca. workspace condiviso. restituisce un risultato al genitore. la cronologia del genitore non vede mai alcun ragionamento intermedio del task.
- il task di ricerca viene eseguito in isolamento. l'intera catena di ragionamento.
- ogni osservazione intermedia che il modello ha fatto sul codice, ogni "aspetta, fammi controllare anche questo file", rimane dentro il task.
- la sessione genitore riceve un riepilogo pulito. è tutto ciò che vede mai.
perché questo è importante in pratica: quando esegui un'analisi esplorativa direttamente all'interno di una sessione di lunga durata, la cronologia si riempie di chiamate a strumenti intermedie, risposte parziali e ragionamenti del modello su cose che non sono più rilevanti.
- il modello si ancora a quel rumore quando non dovrebbe. la compaction alla fine scatta e perde contesto di cui avevi effettivamente bisogno. i task sono la soluzione chirurgica.
la regola: se il sottoproblema ha un risultato chiaro e non ha bisogno della cronologia della conversazione del genitore per essere completato, trasformalo in un task. la soglia per "trasformalo in un task" è più bassa di quanto pensi.
per l'analisi parallela su un codice base: il pattern del cartografo, distribuisci i task e raccogli i risultati:
ogni task è pulito. ogni task è focalizzato esattamente su una directory. la sessione genitore raccoglie i risultati e scrive il documento finale.
se hai 12 moduli, esegui 12 task focalizzati, ognuno che inizia con zero bagaglio dagli altri.
Ruoli e skill: modellare il comportamento senza ricompilare
- i ruoli vivono in
.agentic-harness/roles/. le skill vivono in.agents/skills/. entrambi vengono scoperti automaticamente quando l'harness si avvia. - i ruoli sono sovrapposizioni di system prompt limitate a una chiamata. applicati al momento della chiamata e scartati dopo. non persistono nella cronologia dei messaggi. non si accumulano tra le chiamate.
la catena di precedenza: ruolo di chiamata > ruolo di sessione > ruolo di agente > nessun ruolo.
- il frontmatter del modello è opzionale ma utile. ti permette di instradare ruoli specifici a modelli specifici.
- il tuo ruolo di spiegatore gira su
claude-sonnet-4-6per velocità e costo. il tuo revisore di sicurezza gira suclaude-opus-4-7per profondità. configuri questo una volta nel file del ruolo e non ci pensi mai più. - le skill sono file descrittivi del comportamento che il modello legge all'inizio di una sessione.
- sono file markdown in
.agents/skills/. l'harness li trova automaticamente. non li registri da nessuna parte.
l'uso pratico: una libreria di skill accanto al tuo codice base descrive come lavori. formato dei commit, librerie preferite, convenzioni di denominazione per le migrazioni, pattern di progettazione API, requisiti di test.
il modello legge questo prima di ogni sessione. modifichi il markdown. il comportamento si aggiorna alla prossima esecuzione. nessuna ricompilazione.
il modello legge questo. scrive commit che corrispondono alla tua convenzione. non glielo ricordi ogni sessione. mantieni un file.
Il loop dell'agente di codifica in dettaglio
il loop dell'agente di codifica è il caso d'uso principale per cui è stato costruito il CLI. è anche dove più cose possono andare storte se lo configuri male.
il comando completo con tutte le opzioni che contano:
cosa fa ogni flag e perché è importante:
--workspace .imposta la radice. tutte le operazioni sui file sono sandboxate qui. l'agente non può leggere o scrivere al di fuori di questo percorso, applicato a livello di harness — non fidandosi che il modello si autolimiti.--llm autoseleziona il modello dadefaultModelnella tua configurazione runtime. usa--llm anthropic/claude-opus-4-7per compiti complessi che necessitano di ragionamento profondo, o--llm anthropic/claude-sonnet-4-6per iterazioni più veloci.--deny-pathè un blocco duro. corrisponde in stile prefisso, quindi--deny-path config/copre tutto sottoconfig/. controlla il tuo workspace prima della prima esecuzione ed elenca ogni percorso che contiene segreti o configurazioni di produzione — non solo.env.--approve-dependenciespermette modifiche aCargo.tomlsenza un passo di approvazione umana. lascialo fuori se vuoi rivedere ogni nuova crate prima che venga aggiunta.--commitmette in stage automaticamente tutte le modifiche e le committa alla fine di un'esecuzione riuscita con il messaggio che fornisci. senza questo flag, le modifiche arrivano come modifiche non in stage per la tua revisione.--prapre una pull request dal commit. richiede uno stato git pulito prima dell'esecuzione e un branch reale, non un HEAD distaccato.
il loop stesso: Ispeziona → Brief → LLM + Strumenti → Modifica + Test → Commit · PR.
- inspect: legge la struttura del workspace, carica skill e ruoli, identifica i file più probabilmente rilevanti per il prompt.
- scrive la sua comprensione in
coding-brief.mdprima di toccare qualsiasi codice. - brief: il modello si impegna in un piano. puoi leggere
.agentic-harness/runs/<id>/coding-brief.mda metà esecuzione per vedere cosa ha deciso. - se il brief sembra sbagliato, uccidi l'esecuzione. è più economico riavviare con un prompt più chiaro che lasciare che l'agente esegua un piano sbagliato.
- LLM + strumenti: il loop modifica-test. il modello apporta modifiche, esegue la suite di test, legge l'output, apporta altre modifiche. itera fino a quando i test passano, il limite di iterazione viene raggiunto, o decide che il compito è completo.
commit · PR: mette in stage, committa, spinge, apre la PR con il diff allegato.
ogni esecuzione scrive sei artefatti in .agentic-harness/runs/<id>/:
coding-brief.md: il piano a cui l'agente si è impegnato prima di scrivere qualsiasi codicesummary.md: resoconto leggibile di ciò che è stato fatto, cosa è stato provato e perchérun.json: metadati strutturati: modello usato, durata totale, conteggi di token in input/output, numero di iterazioni, stato di uscita finaleevents.jsonl: ogni singola chiamata a strumento in ordine con input e output completi, per il debug di ciò che è andato stortodiff.patch: il diff completo di tutte le modifiche ai filechecks.json: risultati finali di test e lint che hanno determinato successo o fallimento
Consigli da ricordare
- trattali come log strutturati, non output effimeri. committo gli artefatti delle esecuzioni nel repository per qualsiasi compito che devo essere in grado di riprodurre.
- il solo
run.json— 2KB — ti dice il modello, i costi dei token e se ha avuto successo.events.jsonlti dice esattamente cosa ha fatto l'agente e in quale ordine quando devi fare debug di un'esecuzione sbagliata.
per CI, il pattern è:
HttpSessionEnv: eseguire il binario in locale, eseguire in remoto
- questa è la capacità che ho impiegato più tempo a capire appieno. ora la uso in quasi tutti i compiti che toccano l'infrastruttura.
- il binario dell'agente gira sulla tua macchina o in CI. le operazioni sul filesystem e sulla shell vengono eseguite all'interno di un sandbox remoto.
- l'agente non sa né gli importa in quale ambiente si trova.
usa agentic_harness::HttpSessionEnv;
il protocollo wire è JSON su HTTP. ogni operazione:
- exec
- read
- write
- edit
- grep
- glob
- stat
- readdir
- mkdir
- rm ha una forma richiesta/risposta definita.
qualsiasi sandbox che implementa questo protocollo funziona come target HttpSessionEnv.
per cablare un sandbox nominato:
i connettori built-in gestiscono il boilerplate di autenticazione e ciclo di vita per Vercel Sandbox, Daytona e E2B:
- il caso d'uso concreto per cui lo uso di più: riprodurre fallimenti CI in un ambiente Linux pulito.
- l'agente clona il repository all'esatto hash di commit fallito, esegue l'esatto comando di test fallito, legge l'output completo, diagnostica il fallimento e scrive un report.
- leggo il report. non ho mai toccato la mia macchina locale. il sandbox viene scartato quando la sessione termina.
la cosa sulle prestazioni di cui nessuno ti avverte: ogni chiamata shell tramite HttpSessionEnv è un round trip di rete. loop stretti: modifica, test, controlla output, modifica — accumulano latenza rapidamente.
un loop di 40 iterazioni che richiede 5 secondi in locale richiede diversi minuti contro un sandbox remoto se ogni iterazione fa tre chiamate shell separate.
la soluzione: raggruppa il lavoro shell in script.
una chiamata per iterazione invece di tre. scrivi lo script una volta, eseguilo ripetutamente. la differenza di latenza su un loop di 40 iterazioni è reale.
Target di build: stesso codice base, tre forme di deployment
native è il default. un binario. un manifest. nient'altro sulla macchina di destinazione. gira ovunque possa eseguire un binario Linux nativo.
node è per piattaforme di hosting che richiedono un entrypoint Node. la build genera server.mjs che avvia il binario Rust nativo come processo figlio e proxy HTTP ad esso. la logica dell'agente gira ancora come Rust. il layer Node è uno shim HTTP di 30 righe.
Cloudflare è per il deployment edge.
- la build genera un file boundary Worker e collega un adattatore app compatibile con Worker.
- i gestori compilano in WASM tramite il WASM JSON ABI.
- i binding Durable Object gestiscono la persistenza delle sessioni tramite Cloudflare KV.
il vincolo importante su Cloudflare: i Worker non supportano comandi shell di lunga durata. non hanno un filesystem reale.
non supportano cargo né alcun tool di build. --target cloudflare è per la gestione di webhook, metadati di route, piccoli endpoint di controllo e routing Durable Object — non per lavoro di codifica.
per qualsiasi cosa che necessiti di eseguire cargo test, delega a un processo nativo o a un sandbox remoto.
la matrice decisionale pratica:
- rilasciare un agente come API che altri servizi chiamano → native dietro nginx o una piattaforma gestita
- ospitare su Railway, Render o una piattaforma che si aspetta Node → node
- ingestione di webhook, routing leggero, gestione dello stato Durable Object → cloudflare
- tutto il resto → native
Output guidato da schema: struct Rust tipizzate dalle risposte del modello
chiedere al modello di restituire JSON e sperare che lo faccia è metà della soluzione.
avere l'harness che estrae, valida e deserializza nella tua struct Rust è la soluzione completa.
il modello può restituire prosa di ragionamento insieme al payload tipizzato nella stessa risposta. l'harness estrae il blocco di risultato tra
- i marcatori
---RESULT_START---e---RESULT_END---. ottieni una struct Rust. sicurezza dei tipi a tempo di compilazione dall'output del modello alla logica del gestore. - lo schema fa due cose: dice al modello quale forma produrre, e dà all'harness qualcosa su cui validare prima della deserializzazione.
- se il modello restituisce qualcosa che non corrisponde allo schema, ottieni
PromptError::SchemaValidationFailedinvece di un panic tre siti di chiamata dopo quando accedi a un campo mancante.
Strumenti MCP: raggiungere oltre il sandbox
quando l'agente ha bisogno di capacità oltre file e shell, connect_mcp è la via di fuga.
l'agente ottiene l'intero set di strumenti del server MCP. nessuna definizione di strumento da scrivere. le descrizioni provengono dal server. il modello decide quando chiamare quale strumento in base a quelle descrizioni.
puoi cablare più server MCP a una sessione:
- il modello chiama gli strumenti in base alle loro descrizioni. una descrizione vaga come "cerca su sentry" viene chiamata in modo incoerente.
- una descrizione che dice "chiama questo prima di rispondere a qualsiasi domanda su errori, incidenti o problemi di produzione" viene chiamata in modo affidabile.
- se controlli il server MCP, scrivi descrizioni prescrittive: dì al modello quando chiamare, non solo cosa restituisce.
Connettori: generare adattatori invece di scriverli
invece di scrivere codice adattatore a mano contro un'API sconosciuta, passa una ricetta di connettore al tuo agente di codifica:
- la ricetta del connettore è una descrizione strutturata dell'API del sandbox e del contratto
SessionEnvche deve soddisfare. - l'agente di codifica la legge, scrive il modulo adattatore Rust, gestisce l'autenticazione, avvolge il ciclo di vita del provider e lo espone come
HttpSessionEnv. - rivedi il diff. lo unisci. l'adattatore vive nel tuo progetto. ora è codice tuo.
ho cablato Daytona usando questo in circa 20 minuti, incluso l'intero ciclo di revisione. l'agente ha ottenuto il formato dell'intestazione di autenticazione corretto al primo tentativo.
scrivere l'adattatore da zero contro la documentazione di Daytona avrebbe richiesto gran parte di un pomeriggio e almeno due ipotesi sbagliate sul flusso del token di refresh.
una volta generato il connettore:
Compaction automatica: gestire sessioni lunghe senza perdere contesto
le sessioni di lunga durata accumulano cronologia.
alla fine superano la finestra di contesto del modello.
l'harness gestisce questo automaticamente, ma devi configurarlo correttamente o perderai contesto esattamente nel momento sbagliato.
context_window_tokens è il budget totale per la sessione.
reserve_tokensè ciò che tieni da parte per la risposta del modello. il limite effettivo per la cronologia ècontext_window_tokens - reserve_tokens.keep_recent_messagesè il numero di messaggi in coda che vengono sempre preservati integralmente indipendentemente dalla compaction.
quando la cronologia supera il budget, l'harness chiede al modello di riassumere tutto tra il system prompt e la coda mantenuta.
quel riepilogo sostituisce la sezione centrale. i messaggi in coda rimangono intatti. la sessione compattata è più piccola e la chiamata successiva rientra nel budget.
il compromesso è reale: i riepiloghi perdono precisione. una decisione specifica presa 50 messaggi fa — "abbiamo scelto authlib perché è l'unica libreria con supporto PKCE che funziona con il modello middleware di axum" — potrebbe sopravvivere come "abbiamo scelto authlib per l'autenticazione" nel riepilogo.
se quella precisione è portante per le decisioni successive nella sessione, memorizzala esplicitamente:
- scrivi le decisioni su file. i file sopravvivono alla compaction. il modello può rileggerli su richiesta. la cronologia non deve portare tutto se lo fa il workspace.
- esegui
agentic-harness doctorper vedere l'effettiva finestra di contesto riportata dal tuo modello. impostacontext_window_tokensall'80-90% di quel valore. - il contatore di token non è perfettamente accurato dal lato del modello, e una singola lettura di un file grande può spingerti oltre se sei al 99%.
A cosa prestare attenzione
- Contaminazione della cronologia della sessione
- problema: l'analisi esplorativa all'interno di una sessione lunga avvelena i prompt successivi con rumore dalla fase di esplorazione
- soluzione: usa i task. la cronologia del task non tocca mai il genitore. la soglia per "trasformalo in un task" è più bassa di quanto pensi
- Sorprese nella precedenza dei ruoli
- problema: un ruolo a livello di chiamata oscura il ruolo di sessione. il modello si comporta diversamente dal previsto e non sai perché
- soluzione: il ruolo di sessione imposta l'identità. il ruolo di chiamata restringe il focus. si sovrappongono — il ruolo di chiamata aggiunge, non dovrebbe cancellare
- Lacune in
--deny-path
- problema: neghi
.env. i tuoi segreti vivono anche in.env.localeconfig/staging.yaml. l'agente ne legge uno - soluzione: nega prefissi, non nomi di file.
--deny-path config/copre tutto ciò che sta sotto
- HEAD distaccato in CI
- problema: l'agente modifica, i test passano, il commit fallisce — perché non c'è un branch su cui fare commit
- soluzione:
git checkout -b agent-run-$RUN_IDprima di invocare l'harness
- Latenza di HttpSessionEnv in loop stretti
- problema: 40 iterazioni con tre chiamate shell ciascuna sono minuti di pura latenza di rete
- soluzione: scrivi
agent-check.shche fa tutto in una invocazione. una chiamata per iterazione
- Sottostima del budget di contesto
- problema: la compaction scatta a metà task. il modello perde il suo piano e inizia a improvvisare dal riepilogo
- soluzione: esegui
agentic-harness doctorper ottenere la finestra effettiva. imposta il budget all'80-90% di quella
- Configurazione runtime caricata dopo la registrazione del gestore
- problema: un handler viene eseguito prima di
load_workspace_context(). Nessun modello registrato. L'errore non assomiglia per niente a un problema di configurazione. - soluzione: chiama sempre
load_workspace_context()inapp()prima di collegare qualsiasi agente.
--llmche cambia automaticamente tra esecuzioni
- problema:
defaultModelviene aggiornato. Due esecuzioni a sei mesi di distanza non sono confrontabili. Non puoi riprodurre la prima. - soluzione: fissa il modello in
runtime.jsonper tutto ciò che richiede riproducibilità.
- Eliminazione degli artefatti di esecuzione
- problema: pulisci la directory
runs/con una regola in.gitignore. Tre settimane dopo devi riprodurre una regressione e tutto è sparito. - soluzione: committa gli artefatti di esecuzione per qualsiasi attività che devi riprodurre.
run.jsonpesa 2KB. Tienilo.
cose che farei diversamente
- Leggere la guida di
agentic-harnessprima di toccare qualsiasi altra cosa. - Scrivere test a livello di sessione prima di scrivere la logica degli handler.
- Usare
tasksper tutto ciò che ha un sotto-obiettivo. - Fissare il modello fin dalla prima esecuzione seria.
- Memorizzare le decisioni in file, non nella cronologia della sessione.
- Raggruppare le operazioni shell fin dall'inizio quando si usano sandbox remoti.
il punto fondamentale
La maggior parte dei framework per agenti sono wrapper attorno a una chiamata API. Questo è un runtime.
Un wrapper risolve a "fai rispondere il modello". Un runtime risolve a "porta un agente in produzione e mantienilo funzionante dopo che il modello cambia, dopo che la sandbox cambia, dopo che il codebase cambia, dopo che la sessione va avanti per due ore e fa overflow del contesto."
L'architettura a 3 livelli
- il tuo codice
- l'harness
- il target di esecuzione
è ciò che rende tutto questo possibile. Tu scrivi handler. L'harness assorbe tutta la complessità operativa. Il target di esecuzione è una scelta di configurazione.
Le cose che non cambiano: la logica degli handler, la struttura della sessione, i pattern delle attività, le definizioni dei ruoli, i file delle skill. Le cose che cambiano: modelli, provider, vendor di sandbox, target di deploy.
L'architettura è progettata in modo che le cose che cambiano non tocchino mai quelle che non cambiano.
Questa è la scommessa. Ed è la scommessa giusta.
Spero ti sia piaciuto leggere questo articolo ed esplorare come costruisco per gli agenti e in generale ❣️
Dichiarazioni
Questo articolo è stato ricercato e scritto dall'autore, revisionato da Minimax-M2.7. La miniatura è stata presa da Pinterest.
Harrison Chase "la memoria dovrebbe essere aperta!" —
[https://x.com/hwchase17/status/2046308913939919232Harrison](https://x.com/hwchase17/status/2046308913939919232Harrison)
Chase: "La tua Harness, la tua Memoria" —
[https://www.langchain.com/blog/your-harness-your-memory](https://www.langchain.com/blog/your-harness-your-memory)
Vivek Trivedi: "L'Anatomia di un'Agent Harness" —
[https://www.langchain.com/blog/the-anatomy-of-an-agent-harness](https://www.langchain.com/blog/the-anatomy-of-an-agent-harness)


