Context Engineering: perché il tuo agent diventa più stupido al turno 40
Spostare un dato tre righe più giù in un prompt che usa il 2,6% della context window fa crollare il retrieval dall’84% al 19%.
In questa pagina
Ecco un prompt inviato 288 volte allo stesso modello con greedy decoding. È lungo 853 token. Contiene un registro di venticinque ticket di supporto — città, coda, priorità, proprietario, interno — e una domanda: Marta Ferreira ha bisogno di essere richiamata per il suo ticket. Qual è l’interno telefonico diretto per quel ticket?
Il registro è identico ogni volta. Il modello è identico ogni volta. L’unica cosa che cambia è quale delle venticinque righe contiene la risposta.
| posizione della risposta | successi | tasso di retrieval | intervallo al 95 % |
|---|---|---|---|
| 1 di 25 | 27/32 | 84 % | 68–93 % |
| 4 di 25 | 6/32 | 19 % | 9–35 % |
| 7 di 25 | 6/32 | 19 % | 9–35 % |
| 10 di 25 | 9/32 | 28 % | 16–45 % |
| 13 di 25 | 8/32 | 25 % | 13–42 % |
| 16 di 25 | 6/32 | 19 % | 9–35 % |
| 19 di 25 | 6/32 | 19 % | 9–35 % |
| 22 di 25 | 3/32 | 9 % | 3–24 % |
| 25 di 25 | 7/32 | 22 % | 11–39 % |
Trentadue prove per riga, un ticket diverso a ogni prova, intervalli di Wilson dal Capitolo 4 perché diciassette su venti non distingue nulla da nulla.
Alla posizione uno si risponde correttamente l’84 % delle volte. Ogni altra posizione sta tra il 9 % e il 28 % e tutti e otto quegli intervalli si sovrappongono, quindi la lettura onesta è prima posizione, poi tutto il resto. Liu et al. hanno trovato una U — alto a entrambe le estremità, basso al centro — e qui il braccio della recency non è chiaramente presente: il 22 % nell’ultima posizione rientra nella dispersione delle posizioni centrali. Quello che non rientra in nulla è il calo dalla posizione 1 alla posizione 4. Tre righe.
La context window di questo modello è di 32.768 token. Il prompt ne usa 853, il 2,6 %. Nulla è andato in overflow, nulla è stato troncato, nessun limite è stato raggiunto, nessun avviso è comparso. Il modello ha smesso di trovare una riga che gli era stata consegnata, perché la riga si è spostata tre posizioni più in basso in una lista di venticinque.
Il Capitolo 16 ha dato un prezzo alla context window e si è chiuso avvertendo che avere un milione di token non significa usarli, rimandando qui. Questo è il qui.
Mostra dettagli
Che cosa serve a questo capitolo dai precedenti.
- Capitolo 9 ha derivato la self-attention e il suo costo . Ogni token fa attention a ogni altro, quindi il numero di relazioni a coppie cresce con il quadrato della lunghezza. Questo fatto viene usato sotto, non ri-derivato.
- Capitolo 16 ha contato i cinque bucket di token fatturabili e ha mostrato che il conto di una conversazione cresce quadraticamente. Questo capitolo spiega cosa farne senza rompere l’agent.
- Capitolo 18 ha costruito il catalogo degli strumenti e misurato che venti strumenti non peggioravano la selezione, ma moltiplicavano il prompt per sei. Qui c’è il loro conto.
- Capitolo 19 ha costruito il retrieval. Il retrieval just-in-time qui sotto è quel capitolo applicato alla cronologia stessa di un agent; il chunking non viene rispiegato.
- Capitolo 23 ha costruito il harness. Tutto in questo capitolo è una policy che gira dentro il suo loop, ed è per questo che è TypeScript: l’artefatto è un servizio longevo che mantiene stato, non un notebook che mantiene tensori.
Due lavori con nomi simili
Link alla sezione: Due lavori con nomi similiAnthropic ha tracciato la linea a settembre 2025 e le due frasi vanno lette una accanto all’altra. Il prompt engineering è «metodi per scrivere e organizzare istruzioni per LLM per risultati ottimali». Il context engineering è «l’insieme di strategie per curare e mantenere il set ottimale di token (informazioni) durante l’inferenza LLM, inclusa tutta l’altra informazione che può finire lì fuori dai prompt».1
La differenza operativa è quando, e da chi. Un prompt viene scritto una volta, da una persona, e revisionato. Un contesto viene assemblato a ogni chiamata, da codice che nessuno sta guardando, a partire da materiale che nessuno ha scritto a mano: quaranta turni di cronologia, sei risultati di strumenti, quattro passaggi recuperati, un profilo utente, dodici schemi JSON. Il Capitolo 15 ha misurato quanto comprano istruzioni migliori. Questo capitolo riguarda l’altro novanta per cento dei token, che arrivano da soli.
Lo stesso documento nomina la risorsa che tutti consumano: i modelli «hanno un budget di attention da cui attingono quando analizzano grandi volumi di contesto. Ogni nuovo token introdotto esaurisce questo budget di una certa quantità». E nomina il sintomo: «quando il numero di token nella context window aumenta, la capacità del modello di richiamare accuratamente informazioni da quel contesto diminuisce» — context rot.1
Quest’ultima frase è un’affermazione sul comportamento, quindi si può verificare, e la tabella in cima a questa pagina è la verifica.
Come è stata costruita quella tabella
Link alla sezione: Come è stata costruita quella tabellaQuaranta righe contro l’endpoint locale del Capitolo 22 — un piccolo server Python che tiene Qwen2.5-0.5B-Instruct sulla CPU e parla nel formato chat-completions, così il loop resta TypeScript e i tensori restano dall’altra parte della porta.
const DEPTHS = [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1];
for (const d of DEPTHS) {
const slot = Math.round(d * (N - 1));
let hits = 0, other = 0;
for (let t = 0; t < TRIALS; t++) {
const recs = buildRecords(N, 1000 + t); // 25 unique tickets
const gold = recs[Math.floor(rng(7 + t)() * N)]; // a different one each trial
const rest = recs.filter((x) => x.ticket !== gold.ticket).slice(0, N - 1);
const lines = [...rest.slice(0, slot).map((x) => x.line),
gold.line,
...rest.slice(slot).map((x) => x.line)];
const r = await complete(prompt(lines, ask(gold.owner)), { maxTokens: 12 });
const said = /\d{4}/.exec(r.text)?.[0];
if (said === String(gold.ext)) hits++;
else if (said && recs.some((x) => String(x.ext) === said)) other++;
}
}Il contatore other è ciò che trasforma un risultato deludente in uno utile: quando il modello sbaglia, è perso o è sicuro?
La risposta è: sicuro. Nelle otto posizioni non iniziali, 136 delle 205 risposte sbagliate erano l’interno di un altro ticket — un numero reale di quattro cifre, formattato correttamente, letto dalla riga sbagliata. Alla posizione 1 solo uno dei cinque errori lo era; alla posizione 7, ventuno su ventisei.
Questa distinzione è ciò che conta in produzione. Un modello che dice non riesco a trovarlo è un bug che noti; un modello che restituisce il numero della riga vicina è un bug che rilasci, perché sullo schermo i due sembrano identici. È il fallimento contro cui il Capitolo 19 aveva costruito citazioni verificabili, ma che arriva dall’interno del prompt invece che dall’indice.
Non è solo dove. È quanto.
Link alla sezione: Non è solo dove. È quanto.La posizione è un asse. La lunghezza è l’altro, ed è più facile da testare: tieni la risposta al centro e fai crescere la lista.
| record | token del prompt | successi | tasso | intervallo al 95 % | riga sbagliata | né l’uno né l’altro |
|---|---|---|---|---|---|---|
| 1 | 97 | 18/20 | 90 % | 70–97 % | 0 | 2 |
| 3 | 159 | 11/20 | 55 % | 34–74 % | 9 | 0 |
| 8 | 315 | 3/20 | 15 % | 5–36 % | 17 | 0 |
| 20 | 695 | 2/20 | 10 % | 3–30 % | 16 | 2 |
| 40 | 1.324 | 3/20 | 15 % | 5–36 % | 15 | 2 |
| 80 | 2.587 | 1/20 | 5 % | 1–24 % | 18 | 1 |
| 140 | 4.477 | 2/20 | 10 % | 3–30 % | 18 | 0 |
Un record e 97 token: 90 %. Tre record e 159 token: 55 %. Otto record e 315 token: 15 %, e da lì piatto e basso fino a 140 record e 4.477 token. L’intero crollo avviene tra la prima e l’ottava riga di una lista.
L’ultima colonna è tutto ciò che non è né l’interno corretto né quello di un altro record, che con un solo record sulla pagina è l’unico posto in cui può finire una risposta sbagliata. I due errori con un record meritano di essere riportati invece che arrotondati via, perché nessuno dei due era un rifiuto: uno ha risposto 5806 a un registro la cui unica riga dice 5805. A 97 token con un solo candidato, questo modello copia comunque male una cifra due volte su venti, e questo è il pavimento rispetto a cui si misura tutto il resto.
Ne seguono due cose. Una context più grande compra il diritto di inviare di più, non la certezza che venga letto: questo modello ha una context window da 32.768 token e un intervallo operativo, su questo compito, di poche centinaia di token. E non c’è soglia, non c’è precipizio, non c’è stato «context pieno» — il degrado è già in corso al terzo record ed è completo all’ottavo, all’uno per cento della window. Qualunque cosa sia un limite di contesto, non è ciò che governa questo fenomeno.
Di solito vengono proposti due meccanismi. Il primo è l’aritmetica del Capitolo 9, che Anthropic esprime negli stessi termini di questo corso: i modelli «sono basati sull’architettura transformer, che permette a ogni token di fare attention a ogni altro token nell’intero contesto. Questo produce n² relazioni a coppie per n token».1 L’attention su una sequenza più lunga non è la stessa operazione applicata a più materiale; è un budget fisso di massa di probabilità distribuito su più concorrenti. Il secondo è il training: i modelli vedono molte più sequenze brevi che lunghe, quindi i pattern posizionali a lungo raggio sono la parte meno esercitata della rete. Questo è un argomento, non una misurazione, e questo capitolo non può risolverlo.
Ciò che è risolto è la forma, e lo è dal 2023. Liu et al. hanno testato question answering multi-documento e retrieval key-value tra famiglie e dimensioni di modelli e hanno trovato che «le performance sono spesso più alte quando le informazioni rilevanti compaiono all’inizio o alla fine del contesto di input, e degradano significativamente quando i modelli devono accedere a informazioni rilevanti nel mezzo di contesti lunghi, anche per modelli esplicitamente long-context».2 Il Capitolo 15 ha preso da quel paper la sua regola di posizione; il Capitolo 19 ne ha preso il motivo per cui venti chunk recuperati possono ottenere un punteggio peggiore di quattro. La forma pratica del fatto è l’unica frase qui su cui dovresti agire: servono cinque minuti per misurarlo sul tuo modello con i tuoi dati, e nessuna curva pubblicata sostituisce la tua.
Nessuno sa cosa c’è nella propria window
Link alla sezione: Nessuno sa cosa c’è nella propria windowChiedi a un team che cosa riempia il contesto del suo agent e ottieni una stima, perché nessuna API restituisce la risposta: la risposta ti dà prompt_tokens, un numero unico per tutto.
Puoi ricostruire la scomposizione con quattro conteggi e tre sottrazioni — il prompt renderizzato completo, lo stesso senza definizioni degli strumenti, il solo messaggio di sistema con e senza di esse, e tutto con i risultati degli strumenti rimossi:
async function buckets(messages: Msg[]) {
const sys = messages.slice(0, 1);
const withoutResults = messages.filter((m) => m.role !== "tool");
const [total, sysWithTools, sysNoTools, noResults] = await Promise.all([
countPrompt(messages, CATALOGUE), // everything
countPrompt(sys, CATALOGUE), // system + scaffolding + schemas
countPrompt(sys), // system + scaffolding
countPrompt(withoutResults, CATALOGUE), // everything but tool output
]);
return {
system: sysNoTools,
tools: sysWithTools - sysNoTools,
toolResults: total - noResults,
conversation: total - sysWithTools - (total - noResults),
total,
};
}countPrompt applica il chat template del modello prima della tokenizzazione, cosa che conta più di quanto sembri: il tuo testo non è ciò che viene contato. Marcatori di ruolo, preambolo di tool-calling e rendering dello schema sono tutti token che paghi e che non hai mai digitato. Il Capitolo 7 ha costruito un tokenizer e il Capitolo 16 ha contato con js-tiktoken; qui il conteggio viene dallo stesso modello che leggerà il prompt, ed è l’unico conteggio esattamente corretto.
Ora fai passare un agent reale attraverso questo: quaranta turni di indagine su un incidente, dodici strumenti, un ambiente operativo fittizio che restituisce dump di log e serie di metriche realistici.
| turno | sistema | definizioni strumenti | conversazione | risultati strumenti | prompt totale | input fatturato in questo turno |
|---|---|---|---|---|---|---|
| 1 | 85 | 1.817 | 155 | 490 | 2.547 | 4.370 |
| 2 | 85 | 1.817 | 282 | 529 | 2.713 | 5.275 |
| 5 | 85 | 1.817 | 647 | 1.870 | 4.419 | 8.093 |
| 10 | 85 | 1.817 | 946 | 2.141 | 4.989 | 4.951 |
| 20 | 85 | 1.817 | 1.500 | 2.943 | 6.345 | 6.316 |
| 30 | 85 | 1.817 | 2.187 | 4.000 | 8.089 | 8.059 |
| 40 | 85 | 1.817 | 3.053 | 5.677 | 10.632 | 21.090 |
Leggi la prima riga contro l’ultima.
Al turno 1 il prompt è di 2.547 token e il 71 % è costituito da definizioni degli strumenti. Il system prompt è il 3 %. Ciò che l’utente ha digitato è il 6 %. L’agent non ha ancora fatto nulla e sta già trasportando 1.817 token di schema JSON.
Al turno 40 il prompt è di 10.632 token e le quote si sono invertite: definizioni 17 %, conversazione 29 %, risultati degli strumenti 53 %. L’output degli strumenti ha superato le definizioni al turno 5; la conversazione non le ha superate fino al turno 25, quindi per il primo sessanta per cento della sessione il catalogo degli strumenti era più grande di tutto ciò che era stato detto.
Poi il totale. Su 57 chiamate al modello, l’esecuzione ha fatturato 370.291 token di input per un contesto finale di 10.632 — l’ultimo prompt pagato circa trentacinque volte, il quadratico del Capitolo 16 con sopra il moltiplicatore di un agent. Di quei 370.291, 103.569, ovvero il 28 % di tutto il fatturato, erano le dodici definizioni degli strumenti, reinviate byte-identiche a ogni chiamata.
Quanto costa una definizione di strumento
Link alla sezione: Quanto costa una definizione di strumentoIl catalogo degli strumenti è il costo fisso più grande in un agent ed è invisibile, perché non lo vedi mai: passi un array di oggetti e il provider lo renderizza nel prompt per te. Misurato sugli stessi dodici strumenti:
system prompt + chat scaffolding, no tools: 85 tokens
all twelve definitions: 1,817 tokens
of which fixed tool-calling scaffolding: 126 tokens
three tools instead of twelve: 605 tokens
same twelve, one-sentence descriptions,
no parameter prose: 1,291 tokens (-29 %)Per strumento, il costo marginale va da 80 token per get_current_time, che prende una stringa, a 263 per search_tickets, che prende quattro parametri con un enum e una frase di guida ciascuno. Questo è il tasso di cambio dietro il consiglio centrale del Capitolo 18 secondo cui la descrizione è l’API: una buona descrizione costa circa cento token su ogni richiesta per il resto della vita dell’agent. Tre conseguenze.
Uno strumento che non usi fattura comunque. L’agent ha chiamato sette dei dodici strumenti. Gli altri cinque costano 697 token su ciascuna delle 57 richieste — 39.729 in totale, più di un decimo di tutto ciò che è stato fatturato all’esecuzione, per capacità che non ha mai toccato. Uno dei cinque contiene il dettaglio più netto della traccia: il modello ha provato tre volte a chiamare read_log, che non esiste. Lo strumento che voleva era search_logs, la seconda definizione più costosa del catalogo con 237 token. Ha pagato quella definizione 57 volte, non l’ha mai usata e non ne ha mai trovato il nome.
Tagliare la prosa è l’ottimizzazione più economica disponibile, ed è uno scambio. Ridurre le descrizioni a una frase ed eliminare la documentazione dei parametri ha risparmiato 526 token per chiamata, il 29 per cento, senza toccare una riga di logica — e ha peggiorato le chiamate agli strumenti da parte del modello, che è ciò che il Capitolo 18 ha misurato. Il punto è che entrambi i lati di quello scambio ora sono nella stessa unità.
A una certa scala, inviare definizioni smette di avere senso. Anthropic ci ha messo un numero nel novembre 2025: un grande set di server connessi significa elaborare «centinaia di migliaia di token» di definizioni prima che la richiesta venga letta, e sostituirlo con esecuzione di codice — l’agent che scopre e carica solo le definizioni di cui ha bisogno — «riduce l’uso di token da 150.000 token a 2.000 token, un risparmio di tempo e costo del 98,7%».3 Stessa idea del resto di questo capitolo, applicata agli schemi invece che alla cronologia: tieni l’indice, risolvi la voce on demand.
Romperlo apposta
Link alla sezione: Romperlo appostaIn quella trascrizione da quaranta turni sono state piantate due cose. Al turno 2, prima di qualunque lavoro reale, l’utente dichiara una regola permanente: qualsiasi ticket tu apra deve essere registrato sotto il mio numero dipendente, 4417. Al turno 19, nel mezzo dell’incidente, un fatto: lo shard interessato è pay-shard-7, confermato dal team pagamenti. Al turno 40 l’utente chiede all’agent di aprire il ticket di incidente, che richiede entrambi. Ogni probe viene chiesto in sei formulazioni diverse e valutato su sei — il greedy decoding è deterministico, quindi una chiamata dà un sì o no irripetibile e sei danno un tasso.
La trascrizione viene poi riprodotta sotto sette context policy. Riprodotta invece che rieseguita, deliberatamente: messaggi, chiamate agli strumenti e risultati degli strumenti sono byte-identici in tutte e sette, quindi l’unica variabile è che cosa ogni policy ha scelto di tenere. Il Capitolo 16 ha mostrato perché una sliding window è una cattiva mossa economica, perché distrugge il prefisso cacheable. Ecco che cosa fa al comportamento:
| context policy | token di input sui 40 turni | prompt al turno 40 | regola del turno 2 | fatto del turno 19 |
|---|---|---|---|---|
| cronologia completa | 370.291 | 10.632 | 6/6 | 5/6 |
| sliding window, ultimi 12 messaggi | 157.578 | 2.922 | 5/6 | 0/6 |
| elidere risultati strumenti più vecchi di 4 turni | 243.445 | 6.311 | 6/6 | 3/6 |
| compaction ogni 6 turni | 195.515 | 3.220 | 6/6 | 0/6 |
| compaction più note scritte dal modello | 200.849 | 3.286 | 6/6 | 0/6 |
| fissare i turni dell’utente, davanti | 168.550 | 3.559 | 6/6 | 5/6 |
| fissare i turni dell’utente, dietro | 168.835 | 3.564 | 6/6 | 6/6 |
| controllo: i due turni e nient’altro | — | 1.981 | 6/6 | 6/6 |
Le righe di compaction includono il costo della compaction: 18.581 token di input per sette riassunti e altri 3.392 per chi prendeva note. La riga di controllo è lì perché uno zero possa essere letto come zero — con i due messaggi soli in un prompt da 1.981 token, questo modello risponde perfettamente a entrambi i probe, quindi nessuna riga è il compito troppo difficile.
La cronologia completa ricorda, ed è la cosa più costosa nella tabella: 370.291 token di input per una sessione il cui contenuto durevole sono due frasi.
Questo risponde a una domanda che l’apertura aveva lasciato aperta. Perché una trascrizione da 10.632 token contiene un fatto che un registro da 853 token perde? Perché la lunghezza è la variabile sbagliata. Il registro contiene venticinque interni a quattro cifre in venticinque frasi identiche — ventiquattro esche quasi perfette per quello che vuoi. La trascrizione contiene esattamente un numero dipendente e un nome di shard. Il context rot è interferenza prima di essere volume, ed è per questo che 136 delle 205 risposte sbagliate sopra erano il valore di un vicino. La domanda utile su una window non è quanto sia lunga; è quante cose al suo interno assomigliano alla risposta.
La sliding window costa il 57 % in meno e ha perso l’incidente. Il numero dipendente sopravvive solo perché l’agent lo aveva ripetuto nei turni recenti. Lo shard, dichiarato una volta al turno 19, non è negli ultimi dodici messaggi — e il modello non lo dice. Interrogato sei volte ha risposto «lo shard di pagamento interessato è shard 4417», prendendo il numero dipendente, l’unico altro identificatore rimasto nella sua window, e due volte «pool», estratto dalla stringa pool_exhausted in una riga di log.
La compaction è economica e ha perso lo stesso fatto. Sette riassunti, scritti dal modello sotto un’istruzione esplicita a tenere identificatori, numeri, istruzioni permanenti e domande aperte, e pay-shard-7 non è in nessuno di quelli che contavano; le sei ipotesi sono state shard 1, pay_shard_1 e pool. La compaction non fallisce rumorosamente. Produce una sessione fluida, plausibile, molto più corta, che ha eliminato silenziosamente una riga.
Tre righe hanno ottenuto 0/6 sul fatto del turno 19 — la sliding window, la compaction e la compaction con note. Diciotto risposte sbagliate tra loro, e nemmeno una era «Non lo so.»
Poi la riga che dovrebbe essere imbarazzante. Tenere alla lettera i quaranta messaggi dell’utente, più gli ultimi quattro turni per intero e nient’altro, costa 168.550 token — il 54 % in meno della cronologia completa — e risponde a entrambi i probe bene quanto la cronologia completa o meglio. Nessun summariser, nessun note-taker, nessun secondo modello: un filtro su role === "user". Le parole dell’utente sono i token ad alto valore più economici nella window di un agent, e la maggior parte dei design le scarta insieme a tutto il resto.
Le ultime due righe sono di nuovo la tabella iniziale, dentro l’agent. Lo stesso blocco fissato, spostato dal messaggio di sistema alla fine del prompt: 5/6 diventa 6/6. Su sei prove non è una differenza significativa e non viene presentata come tale — viene presentata come promemoria che dove è un parametro che stai impostando, che tu lo sappia o no.
Quattro modi per spendere meno window
Link alla sezione: Quattro modi per spendere meno windowLe quattro strategie qui sotto sono di Anthropic, nel suo ordine, anche se solo le ultime tre fanno parte della sua lista long-horizon.1 Tutte e quattro sono variazioni di un’unica istruzione: non portare ciò che puoi recuperare, e non portare grezzo ciò che puoi portare compresso.
Retrieval just-in-time
Link alla sezione: Retrieval just-in-timeNon precaricare contenuti. Tieni identificatori — un percorso file, una query, un numero di ticket, il nome di uno strumento e i suoi argomenti — e risolvili quando servono. Il bucket più grande nell’agent sopra è output di strumenti che è stato letto una volta, usato una volta e poi trasportato per altri trenta turni. Sostituire ogni risultato più vecchio di quattro turni con uno stub che dica che cos’era e come recuperarlo richiede sei righe:
const elide: Policy = (h) => [SYSTEM, ...h.flatMap((turn, ti) =>
turn.map((m) => (ti < h.length - 4 && m.role === "tool"
? { role: "tool", name: m.name,
content: `[${m.name} result from turn ${ti + 1}, ${m.content.length} chars, ` +
`elided; call ${m.name} again with the same arguments to re-read it]` }
: m)))];Questo è il Capitolo 19 con il corpus sostituito dal passato stesso dell’agent. La macchina di retrieval è già lì — è il catalogo degli strumenti.
Compaction
Link alla sezione: CompactionQuando la trascrizione supera una soglia, sostituisci la sua parte più vecchia con un riassunto scritto dal modello e continua. Il prompt che scrive il riassunto è tutto il design, ed è dove la compaction si vince o si perde: tieni identificatori, numeri, istruzioni permanenti e domande aperte; elimina convenevoli e output di strumenti che puoi recuperare di nuovo.
La compaction è lossy per costruzione, ciò che perde viene scelto da un modello per tuo conto, e nulla va in errore quando sceglie male. Non è nemmeno gratis: ogni compaction è una chiamata extra il cui input è ciò che viene compattato.
Note strutturate
Link alla sezione: Note strutturateMantieni un piccolo archivio fuori dal contesto e reiniettalo intero a ogni turno. A differenza di un riassunto, è append-only e indirizzabile: una regola scritta al turno 2 è ancora lì alla lettera al turno 400. La versione misurata qui chiede al modello, dopo ogni messaggio dell’utente, se contiene qualcosa di durevole:
const r = await complete([
{ role: "system", content:
"You keep a durable note file for a support session. Given one user message, " +
"output one short note ONLY if it states a standing rule, an identifier or a fact " +
"that must survive the rest of the session. Otherwise output exactly NONE." },
{ role: "user", content: `Turn ${i + 1}: ${user}` },
], { maxTokens: 40 });
if (!/^none\b/i.test(r.text.trim())) notes.push(`turn ${i + 1}: ${r.text.trim()}`);Questa è la strategia con il soffitto più alto qui, ed è quella che ha fallito nella misurazione. Su quaranta messaggi utente, il note-taker ha conservato tre note e nessuna delle due che contavano: una riga di consigli da runbook, un annuncio che la sessione stava finendo e Europe/Madrid è attualmente 13:45 — un orario inventato, visto che lo strumento che stava parafrasando aveva restituito 09:52 UTC. Il note-taker è un modello, e tutto in questo capitolo si applica anche a lui.
Sub-agent
Link alla sezione: Sub-agentDai a un compito focalizzato la sua window — il suo system prompt, il suo piccolo catalogo, nessuna cronologia del genitore — e restituisci una risposta breve invece di una trascrizione. Il Capitolo 23 ne ha messo uno dietro uno schema di strumento e ha lasciato il conto qui; il conto è che la risposta del figlio è l’unica parte della window del figlio che il genitore paga mai.
Il sub-agent non è nella tabella sopra perché non gira per quaranta turni: gira una volta, in una window che qualcuno ha delimitato per lui. Con il system prompt, i turni da 17 a 19 e nient’altro — 2.737 token — ha risposto al probe dello shard 6/6, meglio di ogni policy nella tabella, e al probe del dipendente 0/6, perché quel numero non è nei tre turni che gli sono stati consegnati.
Questo sono i sub-agent in due numeri: una window pulita non è intelligenza, è scope, e lo scoping viene fatto in anticipo da codice che deve già sapere quali turni contano. Un’altra cosa in quelle risposte vale la pena conservare. Questa è stata l’unica policy che ha risposto «Nessuno disponibile» invece di inventare qualcosa. Un modello con un contesto piccolo e coerente sa cosa gli manca; un modello con uno grande e rumoroso no.
Le tre memorie
Link alla sezione: Le tre memorieQuasi ogni conversazione confusa sulla memoria degli agent è fatta di tre meccanismi che indossano la stessa parola. Hanno durate, proprietari e modalità di fallimento diverse, e un sistema che li tiene nello stesso posto ha un problema di cui non si è ancora accorto.
| cronologia conversazione | retrieval | memoria utente persistente | |
|---|---|---|---|
| contiene | ciò che è stato detto in questa sessione | documenti che possiedi | fatti su una persona |
| vive | una sessione | finché non viene reindicizzato | in tutte le sessioni, per sempre |
| scritta da | il loop, automaticamente | una pipeline di ingestione | il modello, di proposito |
| entra nel prompt | per intero, a ogni chiamata | quattro passaggi, quando una query corrisponde | per intero, a ogni chiamata |
| fallisce perché | cresce finché marcisce | recupera il chunk sbagliato | ricorda qualcosa di sbagliato su di te |
| costruita in | Capitolo 23 | Capitolo 19 | questo capitolo |
Il framing accademico è quello di CoALA, che organizza i language agents attorno a «componenti di memoria modulari» e separa working memory da store episodici, semantici e procedurali.4 MemGPT prende la stessa idea alla lettera, prendendo in prestito la memoria virtuale dai sistemi operativi: un livello veloce dentro la window, un livello lento fuori, e il modello stesso che sposta dati tra i due con function calls.5 Entrambi costringono alla domanda a cui un prodotto deve comunque rispondere — non quanto posso tenere, ma a quale store appartiene questo, e quando scade.
Il test pratico è una domanda per fatto: che cosa dovrebbe essere ancora vero domani? Un risultato di strumento del turno 12, nulla. Un riassunto della sessione, finché la sessione finisce. Che il numero dipendente dell’utente è 4417, finché non cambia lavoro. Tre risposte, tre store.
Dove si va adesso
Link alla sezione: Dove si va adessoOra puoi misurare che cosa c’è in una window, decidere che cosa resta al suo interno e distinguere tra un agent che ha dimenticato qualcosa e uno che lo stava trasportando ma non ha guardato.
L’ultima delle quattro strategie è quella che non sta qui. Un sub-agent non è una context policy, è un secondo agent, e nel momento in cui ce ne sono due devi decidere cosa passa tra loro e chi comanda. Il Capitolo 25 è questo: i cinque pattern di orchestrazione e da dove viene davvero ciascuno dei loro nomi, le due topologie che vengono confuse — chiedere a un sub-agent e ricevere una risposta, contro consegnargli la conversazione e non riaverla — e il risultato misurato secondo cui, sul compito a cui dà prezzo, la disposizione più semplice vince — seguito dal test per capire quando smette di vincere.
Eredita anche esattamente ciò che questo capitolo ha appena misurato. Un sub-agent restituisce un riassunto. Un riassunto è una compaction che non hai scritto, prodotta da un modello la cui window non puoi vedere, e il genitore non ha modo di distinguere uno buono da uno sbagliato ma sicuro — la stessa distinzione che separava l’84 % dal 19 % in cima a questa pagina, e che ha trasformato diciotto fatti mancanti in diciotto invenzioni. Quindi: quando il sub-agent sbaglia, che cosa esattamente può guardare il genitore?
Fonti e metodo
Link alla sezione: Fonti e metodoOgni numero qui è stato prodotto su questa macchina e nessuno è stato stimato. Il modello è Qwen2.5-0.5B-Instruct in float32 sulla CPU con greedy decoding, servito su loopback da un piccolo endpoint Python che parla nel formato chat-completions ed espone una route di conteggio token — di nuovo la cucitura del Capitolo 14, tensori sul lato Python e loop su quello TypeScript — quindi ogni conteggio è il tokenizer proprio di quel modello applicato al suo chat template. La tabella di posizione è composta da 288 chiamate, nove posizioni per trentadue prove con un ticket diverso a ogni prova; la tabella di lunghezza è di 140 chiamate; l’esecuzione dell’agent è di 57 chiamate al modello in 43 minuti di tempo reale; la tabella delle policy è quella singola trascrizione riprodotta sotto sette policy. Gli intervalli sono di Wilson, dal Capitolo 4. Non è stata chiamata alcuna API a pagamento, ed è anche per questo che nel capitolo non c’è un solo prezzo: i conteggi dei token sono esatti e le tariffe per cui li moltiplicheresti sono quelle del Capitolo 16.
Riferimenti
Link alla sezione: Riferimenti-
Anthropic, Effective context engineering for AI agents, 29 settembre 2025,
anthropic.com/engineering/effective-context-engineering-for-ai-agents, consultato il 7 settembre 2026. Fonte delle due definizioni citate all’inizio, del «budget di attention» e dell’affermazione che ogni nuovo token lo esaurisce, della descrizione del context rot, del framing delle relazioni a coppie n² e delle strategie usate come spina dorsale di questo capitolo. Tre di esse sono la sua lista long-horizon — compaction, note-taking strutturato e architetture multi-agent; il retrieval just-in-time compare prima nello stesso articolo, sotto context retrieval e agentic search, ed è raggruppato qui con le altre. ↩ ↩2 ↩3 ↩4 -
Liu, N. F., Lin, K., Hewitt, J., Paranjape, A., Bevilacqua, M., Petroni, F. e Liang, P. Lost in the Middle: How Language Models Use Long Contexts. arXiv:2307.03172 (v1 luglio 2023, v3 novembre 2023). Citato nei Capitoli 15, 16 e 19 e misurato qui. La frase citata viene dall’abstract; i due compiti del paper sono question answering multi-documento e retrieval key-value, e la sua scoperta che l’effetto persiste in modelli esplicitamente long-context è la parte che conta per una decisione di prodotto. ↩
-
Anthropic, Code execution with MCP: building more efficient agents, 4 novembre 2025,
anthropic.com/engineering/code-execution-with-mcp, consultato il 7 settembre 2026. Fonte della riduzione da 150.000 a 2.000 token e del dato del 98,7 %, e dell’osservazione che le definizioni degli strumenti caricate in anticipo occupano contesto prima che la richiesta venga letta. ↩ -
Sumers, T. R., Yao, S., Narasimhan, K. e Griffiths, T. L. Cognitive Architectures for Language Agents. arXiv:2309.02427 (2023). Organizza i language agents attorno a «componenti di memoria modulari, uno spazio d’azione strutturato per interagire con la memoria interna e gli ambienti esterni, e un processo decisionale generalizzato per scegliere azioni», e divide la memoria in working, episodica, semantica e procedurale. Il Capitolo 22 ha usato la sua tassonomia per il learning agent; la tabella a tre store sopra è la sua ombra pratica. ↩
-
Packer, C., Wooders, S., Lin, K., Fang, V., Patil, S. G., Stoica, I. e Gonzalez, J. E. MemGPT: Towards LLMs as Operating Systems. arXiv:2310.08560 (ottobre 2023). Propone «virtual context management, una tecnica ispirata ai sistemi di memoria gerarchici dei sistemi operativi tradizionali», con il modello stesso che sposta dati tra un livello veloce dentro la window e un livello lento fuori. La dichiarazione più chiara in assoluto del perché la window è una cache e non una memoria. ↩