Un requisito che nessun singolo agente riesce a tenere in testa — «rivedi ogni file cambiato in questa PR», «migra 500 componenti» — non si risolve alzando l’effort. Si risolve rispondendo a due domande separate: chi tiene il piano, e dove vivono i risultati intermedi. Sono i due assi su cui la documentazione fa scegliere la forma della scomposizione.
Chi tiene il piano
«Building effective agents» separa due regimi. Nei workflow «LLMs and tools are orchestrated through predefined code paths»; negli agenti «LLMs dynamically direct their own processes and tool usage, maintaining control over how they accomplish tasks». La stessa pagina nomina i pattern di scomposizione che userai davvero: il prompt chaining «decomposes a task into a sequence of steps, where each LLM call processes the output of the previous one»; il sectioning è «breaking a task into independent subtasks run in parallel»; nell’orchestrator-workers «a central LLM dynamically breaks down tasks, delegates them to worker LLMs, and synthesizes their results».
In Claude Code queste forme hanno costi diversi, e il confronto documentato si gioca su due colonne. Con subagent, skill e agent team decide Claude turno per turno, e i risultati intermedi atterrano in una finestra di contesto. Con un dynamic workflow decide lo script, i risultati intermedi stanno in variabili dello script — «a workflow moves the plan into code» — e il contesto di Claude tiene solo la risposta finale. La scala dichiarata differisce di due ordini di grandezza: «a few delegated tasks per turn» contro «dozens to hundreds of agents per run». Il criterio pratico è questo: se i risultati intermedi non servono a Claude per decidere la mossa dopo, tenerli nel suo contesto è solo spesa.
Il confine di una sotto-attività è il suo prompt
Qui c’è il vincolo che rompe le scomposizioni ingenue. Un subagent non-fork parte con una finestra di contesto propria, e la regola è secca: «the only content you pass from parent to subagent is the Agent tool’s prompt string, so include any file paths, error messages, or decisions the subagent needs directly in that prompt». Non eredita la conversazione del genitore né il suo system prompt, e al ritorno «only its final message returns to the parent».
Tradotto in regola di progettazione: una sotto-attività è tagliata bene se il suo prompt è autosufficiente e se il suo messaggio finale è esattamente ciò che serve al passo successivo. Se ti ritrovi a scrivere «continua da dove eravamo rimasti», la scomposizione è sbagliata, non il modello.
Il fan-out ha inoltre limiti espliciti da mettere in preventivo:
CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH default 3 livelli sotto l'agente principale
CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS default 20 in esecuzione contemporanea
maxBudgetUsd / max_budget_usd nessun default; chiude con error_max_budget_usd
Il runtime dei dynamic workflow ne aggiunge di propri: fino a 16 agent concorrenti, al massimo 4.096 elementi in una singola chiamata a parallel() o pipeline(), e 1.000 agent totali per esecuzione.
La sessione persiste la conversazione, non il filesystem
«A session is the conversation history the SDK accumulates while your agent works»: il prompt, ogni chiamata di tool, ogni risultato, ogni risposta. L’SDK la scrive su disco automaticamente. E poi la precisazione che evita l’errore più costoso: «Sessions persist the conversation, not the filesystem».
Tre opzioni, con criteri distinti:
- continue riprende la sessione più recente nella directory corrente. Non tracci nulla, e funziona finché l’applicazione gestisce una conversazione per volta.
- resume prende un ID specifico, che leggi dal campo
session_iddel messaggio di risultato — presente su ogni risultato, riuscito o no. È obbligatorio in un’applicazione multi-utente e per tornare a una sessione che non è l’ultima. È anche la via di recupero quando un’esecuzione è finita inerror_max_turnsoerror_max_budget_usd: riprendi con un limite più alto invece di rifare tutto. - fork crea una sessione nuova che parte da una copia della storia dell’originale. «The fork gets its own session ID; the original’s ID and history stay unchanged».
Il fork non è una copia di file
Due precisazioni che cambiano l’architettura. La prima: «Forking branches the conversation history, not the filesystem. If a forked agent edits files, those changes are real and visible to any session working in the same directory». Se vuoi due rami che scrivono davvero, servono directory o worktree separati: il fork da solo non dà nessun isolamento sui file, e due rami che si sovrascrivono sono un modo di rompersi silenzioso.
La seconda riguarda chi implementa uno storage proprio: il fork «reads the source entries, rewrites every sessionId field and remaps message UUIDs, then appends the transformed entries under a new key». Una copia a livello di adapter produrrebbe una trascrizione che punta ancora alla sessione vecchia.
Riprendere altrove
I file di sessione sono locali alla macchina che li ha creati e vivono sotto la directory dei progetti.
~/.claude/projects/<encoded-cwd>/<session-id>.jsonl
Per CI, container effimeri e serverless la documentazione dà tre strade in ordine crescente di robustezza: collegare un adapter SessionStore che specchia le trascrizioni sul tuo backend, tenendo presente che la chiave deriva dalla working directory e quindi devi riprendere da una directory corrispondente; spostare a mano il file della sessione sul nuovo host; oppure non contare affatto sulla ripresa. Quest’ultima è la raccomandazione esplicita: «capture the results you need (analysis output, decisions, file diffs) as application state and pass them into a fresh session’s prompt. This is often more robust than shipping transcript files around». Per un sistema che deve sopravvivere a un redeploy, è quasi sempre la risposta giusta.