In questo articolo

🔍 Cosa sono gli agent team (e perché non sono subagent)

Un agent team è un insieme di sessioni Claude Code che lavorano insieme: una fa da team lead — spawna i teammate, spezza il lavoro in task, sintetizza i risultati — e le altre sono teammate indipendenti. La differenza chiave rispetto ai subagent non è il parallelismo, che c'era già: è la comunicazione orizzontale. I teammate si mandano messaggi tra loro, condividono una task list con dipendenze, e io posso aprire il transcript di ognuno e parlargli direttamente.

Il subagent resta lo strumento giusto quando mi serve un worker focalizzato che riporta un risultato e sparisce: costa meno token, perché nel contesto principale torna solo il sunto. Il team vale il sovrapprezzo quando i lavoratori devono discutere: review con prospettive diverse che si sfidano, debug con ipotesi concorrenti, feature che attraversano più layer con un owner per layer.

Il prezzo è esplicito nella documentazione: ogni teammate è un'istanza Claude completa con il suo context window, quindi i token scalano linearmente col numero di teammate. Per lavori sequenziali o con molte dipendenze, una singola sessione resta la scelta più efficiente.

Subagent vs agent team: chi parla con chi
Confronto tra subagent e agent team in Claude Code: a sinistra i subagent riportano i risultati solo all'agente principale; a destra il team lead coordina teammate che comunicano tra loro tramite mailbox e condividono una task list con dipendenze.

I subagent riportano solo al chiamante; i teammate si messaggiano tra loro e condividono la task list.

⚙️ Abilitare gli agent team: la variabile sperimentale

Gli agent team sono disabilitati di default: si accendono con la variabile d'ambiente CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS, che metto in .claude/settings.json del progetto così vale per ogni sessione. Senza la variabile, Claude non propone né spawna teammate; con la variabile, anche un normale subagent a cui Claude dà un nome parte come teammate — un effetto collaterale documentato che conviene conoscere prima di stupirsi.

Un vincolo importante per chi automatizza: lo spawn dei teammate richiede una sessione interattiva. In modalità headless con il flag -p (e nelle sessioni Agent SDK) Claude non crea teammate: un subagent con nome gira come subagent ordinario anche a variabile attiva.

Nel dubbio, la retromarcia è la stessa leva: impostare la variabile a 0 nel settings.json utente ripristina i subagent classici, senza riavviare la sessione.

.claude/settings.json · abilitare gli agent team
{
  "env": {
    "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1"
  },
  "teammateMode": "in-process"
}

Agent teams · Claude Code Docs

La variabile accende i team; teammateMode sceglie come vederli. Codice completo nel repo: https://github.com/fscamuzzi/claude-code-agent-teams-demo

🏗️ Il progetto demo: TeamBoard, tre moduli per tre teammate

Per vedere un team al lavoro serve un progetto che si presti alla spartizione senza conflitti: la regola d'oro degli agent team è che due teammate non devono toccare lo stesso file. TeamBoard è una Minimal API .NET 8 per una retro board, divisa in tre moduli verticali — Notes (le note della board), Tags (le etichette) e Stats (i conteggi) — ognuno con i suoi endpoint, il suo service e i suoi test xunit.

Lo stack è il mio solito: Minimal API senza Controllers, record tipizzati per i DTO, LINQ per la logica, store in-memory per non trascinarsi dietro un database in un tutorial che parla d'altro. Ogni modulo vive in una cartella propria: è la mappa naturale un modulo → un teammate.

La struttura di TeamBoard: un modulo per teammate
src/TeamBoard.Api/
├── Modules/
│   ├── Notes/    NoteEndpoints.cs · NoteService.cs · NoteModels.cs
│   ├── Tags/     TagEndpoints.cs  · TagService.cs  · TagModels.cs
│   └── Stats/    StatsEndpoints.cs · StatsService.cs
└── Program.cs    (MapNotes + MapTags + MapStats)

tests/TeamBoard.Tests/
├── NotesTests.cs · TagsTests.cs · StatsTests.cs

.claude/
├── settings.json    (agent teams ON + hook TaskCompleted)
├── agents/          security-reviewer.md · test-runner.md
└── hooks/           task-completed-gate.sh
Tre moduli verticali, zero file condivisi tra teammate. Codice completo nel repo: https://github.com/fscamuzzi/claude-code-agent-teams-demo

🚀 Il primo team: review parallela su tre fronti

Il modo migliore per iniziare con gli agent team — lo suggerisce la stessa documentazione — è un compito che non scrive codice: la review. Un singolo reviewer tende a fissarsi su una classe di problemi alla volta; tre teammate con tre lenti diverse coprono sicurezza, prestazioni e test insieme, e il lead sintetizza alla fine.

Lo spawn è linguaggio naturale: descrivo il task e i teammate che voglio, Claude popola la task list e li lancia. Do a ogni teammate un nome esplicito nel prompt: i nomi prevedibili mi servono dopo, per mandare messaggi diretti ("chiedi a security di...") senza ambiguità.

Un dettaglio da conoscere: Claude a volte decide che il compito non merita un team e usa subagent ordinari. I due casi si distinguono male nel pannello — la conferma è chiedere esplicitamente un agent team se il primo tentativo ha spawnato subagent.

Il prompt che spawna il team di review
Spawna tre teammate per la review dei moduli di TeamBoard:
- "security": vulnerabilità e input validation sugli endpoint
- "perf": allocazioni, LINQ inefficiente, lock contention nello store
- "coverage": buchi nella suite xunit, casi limite mancanti

Ognuno rivede TUTTI e tre i moduli con la sua lente,
scrive i finding come task nella lista condivisa e li discute
con gli altri due prima del report finale. Sintetizza tu alla fine.

Use case · Claude Code Docs

Tre lenti sullo stesso codice, nomi espliciti per i messaggi diretti. Codice completo nel repo: https://github.com/fscamuzzi/claude-code-agent-teams-demo

🗂️ La task list condivisa: assegnazioni, dipendenze, self-claim

Il coordinamento del team passa da una task list condivisa: il lead crea i task, i teammate li reclamano e li completano. Un task può dipendere da un altro: finché la dipendenza non è chiusa, nessuno può reclamarlo — e quando il task a monte si completa, Claude Code sblocca i dipendenti da solo. Il claim usa file locking, quindi due teammate non possono aggiudicarsi lo stesso task in gara.

I task si assegnano in due modi: dico al lead chi fa cosa, oppure lascio il self-claim — un teammate che finisce si prende il primo task libero e non bloccato. Per la fase di implementazione uso la regola dei moduli: nello spawn scrivo esplicitamente che Notes è di un teammate, Tags di un altro, Stats del terzo, così la spartizione dei file è nel contratto fin dall'inizio.

Tutto questo stato vive in locale: config del team in ~/.claude/teams/, task list in ~/.claude/tasks/, sotto un nome derivato dalla sessione. La config è runtime, non si scrive a mano: per definire ruoli riutilizzabili la strada giusta sono le subagent definition del prossimo passo.

Il pannello agenti del lead: teammate e task list
Il terminale della sessione lead di Claude Code con il pannello agenti: tre teammate al lavoro sui moduli Notes, Tags e Stats, la task list condivisa con task completati, in corso e bloccati da dipendenze, e i messaggi tra teammate.

Frecce per selezionare un teammate, Invio per entrare nel suo transcript, Ctrl+T per la task list.

🧩 Ruoli riutilizzabili: una subagent definition come teammate

I ruoli che uso spesso non li ridescrivo a ogni spawn: li fisso in una subagent definition — un file markdown in .claude/agents/ — e la cito per nome quando chiedo il teammate. La stessa definizione lavora in due modi: come subagent classico quando delego, come teammate quando c'è un team. Il teammate ne eredita la lista tools e il model; il corpo del file viene aggiunto al system prompt, non lo sostituisce.

Due asterischi da conoscere: i campi skills e mcpServers del frontmatter non si applicano quando la definizione gira come teammate (skills e MCP arrivano dalle impostazioni di progetto e utente, come in una sessione normale); e a un teammate in-process Claude Code aggiunge da sé SendMessage e i tool della task list, perché senza non potrebbe coordinarsi.

Il mio security-reviewer è in sola lettura per costruzione: Read, Grep, Glob e Bash. Un reviewer che non può scrivere codice è un reviewer di cui mi fido di più — la stessa logica del test-guardian che uso nel flusso TDD.

.claude/agents/security-reviewer.md
---
name: security-reviewer
description: Read-only security reviewer for TeamBoard. Checks input
  validation, injection risks and error handling on every endpoint.
tools: Read, Grep, Glob, Bash
---

You are the security reviewer of this codebase. You never write code.

1. Review every endpoint for missing input validation and
   unbounded payloads (note text length, tag names, ids).
2. Check the in-memory stores for race conditions.
3. File one finding per issue in the shared task list and
   discuss disagreements with the other reviewers by message.

Subagents · Claude Code Docs

Un ruolo definito una volta, usabile come subagent o teammate. Codice completo nel repo: https://github.com/fscamuzzi/claude-code-agent-teams-demo

📝 Plan approval: il lead approva prima che si scriva codice

Per i task rischiosi c'è una marcia in più: chiedere che il teammate lavori in plan mode finché il lead non approva. Il teammate esplora in sola lettura, scrive il piano e manda al lead una richiesta di approvazione; il lead la valuta in autonomia — approva, o respinge con un feedback che rimanda il teammate a rivedere il piano.

Il punto interessante è che il criterio di giudizio del lead si programma nel prompt: "approva solo piani che includono i test", "respingi piani che toccano più di un modulo". È una review di piano automatica, con me nel ruolo di chi scrive la policy invece di leggere ogni piano.

Per la fase di build di TeamBoard la uso così: i tre teammate implementano ognuno una feature nel proprio modulo, ma nessuno tocca un file prima che il suo piano sia passato dal lead con la policy "un modulo solo, test inclusi".

Spawn con plan approval e policy di approvazione
Spawna tre teammate per implementare, in parallelo:
- "notes-dev":  archiviazione note (POST /notes/{id}/archive) — modulo Notes
- "tags-dev":   rename tag con merge (PUT /tags/{id}) — modulo Tags
- "stats-dev":  conteggi per tag (GET /stats/by-tag) — modulo Stats

Richiedi il plan approval prima di qualsiasi modifica.
Approva solo piani che: restano nel proprio modulo,
aggiungono test xunit per la feature, non toccano Program.cs
se non per il map dell'endpoint.

Plan approval · Claude Code Docs

La policy di approvazione sta nel prompt del lead. Codice completo nel repo: https://github.com/fscamuzzi/claude-code-agent-teams-demo

🪝 Il quality gate del team: TaskCompleted con exit 2

Con più agenti che chiudono task in parallelo, il rischio di un "completato" ottimista si moltiplica per il numero di teammate. La risposta è la stessa dei flussi a sessione singola: un hook deterministico. Gli agent team portano tre eventi dedicati — TaskCreated, TaskCompleted e TeammateIdle — e su tutti vale la semantica nota: exit code 2 blocca l'operazione e rimanda lo stderr all'agente come istruzione.

Il mio gate sta su TaskCompleted: quando un teammate prova a marcare un task come completato, lo script lancia dotnet test; se la suite è rossa, il task non si chiude e il teammate riceve l'output del fallimento. Nessun task "completato" con i test rotti, qualunque cosa creda il modello che l'ha chiuso.

TeammateIdle è il gemello per il fine turno: scatta quando un teammate sta per fermarsi, e un exit 2 lo rimanda a lavorare. La coppia copre i due momenti in cui un agente può dichiarare vittoria troppo presto.

.claude/hooks/task-completed-gate.sh + registrazione
#!/usr/bin/env bash
# TaskCompleted hook: a task cannot be completed while tests are red.
cd "${CLAUDE_PROJECT_DIR:-.}" || exit 0

output=$(dotnet test --nologo 2>&1)
if [ $? -ne 0 ]; then
  {
    echo "Team gate: the suite is RED - this task is NOT complete."
    echo "$output" | tail -20
  } >&2
  exit 2   # blocca il completamento, lo stderr torna al teammate
fi
exit 0

# .claude/settings.json
# { "hooks": { "TaskCompleted": [ { "hooks": [ { "type": "command",
#     "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/task-completed-gate.sh" } ] } ] } }

Hooks · Claude Code Docs

Un task si chiude solo a suite verde, chiunque lo chiuda. Codice completo nel repo: https://github.com/fscamuzzi/claude-code-agent-teams-demo

🖥️ In-process o split panes: come seguo il team

Di default il team gira in-process: tutti i teammate dentro il terminale del lead, col pannello agenti sotto il prompt — frecce per selezionare, Invio per aprire il transcript del teammate e parlargli, Esc per interromperne il turno, Ctrl+T per la task list. Funziona in qualsiasi terminale, zero setup.

L'alternativa sono gli split panes: ogni teammate nel suo riquadro, tutto l'output visibile insieme. Richiede tmux oppure iTerm2 con la CLI it2, e si attiva con teammateMode ("auto" o "tmux") nel settings.json o col flag --teammate-mode per la singola sessione. Su iTerm2 la via consigliata è tmux -CC.

Un'avvertenza pratica sui teammate "spariti": una riga idle si nasconde dopo trenta secondi di pannello fermo, ma il teammate resta vivo e raggiungibile — un messaggio col suo nome la fa ricomparire. Prima di pensare a un crash, conviene chiamarlo per nome.

⚠️ Costi, limiti e quando NON usare un team

Gli agent team sono sperimentali e la documentazione è onesta sui limiti. I principali, a oggi: /resume e /rewind non ripristinano i teammate in-process (il lead può provare a messaggiare teammate che non esistono più); un task può restare marcato in-progress anche se il lavoro è finito e va sbloccato a mano; c'è un solo team per sessione, il lead è fisso e i teammate non possono spawnare altri teammate.

Sul portafoglio: ogni teammate è un'istanza completa, quindi i token scalano linearmente. La taglia consigliata è 3-5 teammate con 5-6 task a testa: tre teammate concentrati rendono più di cinque dispersi.

La bussola che uso per scegliere lo strumento è questa:

  • Sessione singola: lavoro sequenziale, modifiche sugli stessi file, refactor piccoli.
  • Subagent: serve solo il risultato — ricerca, verifica, review one-shot a contesto pulito.
  • Agent team: i lavoratori devono discutere — review multi-prospettiva, ipotesi in competizione, moduli indipendenti in parallelo.
  • Worktree separati: parallelismo che deve sopravvivere alla sessione, con branch e commit indipendenti.

📦 GitHub repo

Tutto il materiale dell'articolo è in un repository pubblico: la soluzione TeamBoard completa (Minimal API .NET 8 a tre moduli + 12 test xunit), il .claude/settings.json con gli agent team abilitati e l'hook TaskCompleted registrato, le subagent definition security-reviewer e test-runner, e i prompt di spawn pronti in prompts/. Clono, dotnet test è verde, apro Claude Code e il team si spawna col primo prompt.

Non servono servizi esterni: niente database, niente Docker — la soluzione gira in-process col solo SDK .NET 8.

Clona e prova il repo
$ git clone https://github.com/fscamuzzi/claude-code-agent-teams-demo.git
$ cd claude-code-agent-teams-demo
$ dotnet test    # Passed! - Failed: 0, Passed: 12

# l'API dal vivo
$ dotnet run --project src/TeamBoard.Api
$ curl -s http://localhost:5000/notes \
    -H "Content-Type: application/json" \
    -d '{"text":"Retro: meno standup, più pair","tags":["process"]}'

# poi, dentro Claude Code:
$ claude   # e incolla prompts/01-parallel-review.md

claude-code-agent-teams-demo · GitHub

Codice completo nel repo: https://github.com/fscamuzzi/claude-code-agent-teams-demo

✅ Checklist finale: il team in otto mosse

Ricapitolo il percorso. La sintesi che mi porto a casa dopo settimane di uso: il team non sostituisce la sessione singola né i subagent — è un terzo attrezzo, che paga quando la discussione tra agenti produce qualcosa che il singolo agente non trova. Review multi-prospettiva e ipotesi concorrenti sono i casi dove la differenza si vede subito.

E gli stessi guardrail che uso da mesi sulla sessione singola — regole nel CLAUDE.md, hook deterministici, ruoli in sola lettura — scalano al team senza cambiare filosofia: cambia solo l'evento a cui si agganciano.

Agent team su un progetto .NET in 8 mosse
  1. 01
    Variabile ONCLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 in settings.json
  2. 02
    Progetto spartibilemoduli verticali, zero file condivisi
  3. 03
    Primo team in reviewtre lenti, nessun codice scritto
  4. 04
    Nomi esplicitiper messaggi diretti ai teammate
  5. 05
    Task listdipendenze + self-claim, un modulo a testa
  6. 06
    Ruoli riutilizzabilisubagent definition come teammate
  7. 07
    Plan approvalpolicy di approvazione nel prompt del lead
  8. 08
    Hook TaskCompletedexit 2 se la suite è rossa

Un lead, tre teammate, una task list: il parallelismo con i guardrail di sempre.

Domande frequenti su agent team di Claude Code

Che differenza c'è tra un subagent e un teammate di un agent team?

Un subagent riporta il risultato solo all'agente che l'ha spawnato e non comunica con gli altri; un teammate è una sessione Claude Code completa che messaggia direttamente gli altri teammate, condivide una task list con dipendenze e può essere interpellata da me senza passare dal lead. Il subagent costa meno token; il team vale quando i lavoratori devono discutere tra loro.

Come abilito gli agent team di Claude Code?

Con la variabile d'ambiente CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1, nel blocco env di settings.json o nella shell. Sono sperimentali e disabilitati di default. Attenzione a due effetti: con la variabile attiva anche un subagent a cui Claude dà un nome parte come teammate, e in modalità headless (-p) i teammate non si spawnano affatto.

I teammate ereditano il contesto della sessione lead?

In parte: caricano lo stesso contesto di progetto di una sessione normale — CLAUDE.md, MCP server, skills — più il prompt di spawn, ma NON ereditano la cronologia di conversazione del lead. Per questo conviene mettere nel prompt di spawn tutti i dettagli specifici del task: file da toccare, vincoli, criteri di accettazione.

Posso impedire che un task venga chiuso con i test rotti?

Sì, con l'hook TaskCompleted: quando un teammate prova a marcare un task come completato, lo script agganciato gira e, se esce con codice 2, il completamento viene bloccato e lo stderr torna al teammate come istruzione. Nel mio gate lo script lancia dotnet test e blocca la chiusura a suite rossa; TeammateIdle fa lo stesso per il fine turno.

Gli agent team funzionano anche con Codex o altri agenti?

No, sono una funzione nativa di Claude Code. Con Codex il parallelismo si ottiene a mano: più istanze in worktree git separati, coordinate da me. Il pattern però è replicabile in parte: regole condivise in AGENTS.md, spartizione per moduli e una CI severa come gate — quello che manca è la task list condivisa e la messaggistica tra istanze.

Parliamone

Se questo tema ti riguarda, scrivimi: confrontarsi su codice e AI è sempre tempo speso bene.