I mattoni di CrewAI
11La crew e i processi
Impari a configurare la Crew, a scegliere tra processo sequenziale e gerarchico, a lanciarla con inputs o su più casi con kickoff_for_each, a leggere il CrewOutput e a capire quando usare planning.
Hai gli agenti (capitolo 9) e i task (capitolo 10). La Crew: La squadra: un insieme di agenti e di task, più la regola con cui i task vengono eseguiti (il process). Si avvia con kickoff(). glossario li mette insieme e stabilisce come lavorano: in che ordine, chi decide, che cosa esce alla fine. La regola che organizza il lavoro si chiama Process: La regola con cui la crew esegue i task: sequential (uno dopo l'altro) oppure hierarchical (un manager decide chi fa cosa). glossario.
Pensa alla redazione di un giornale. In una piccola redazione il lavoro va a staffetta: il cronista scrive, il redattore sistema, il grafico impagina, sempre in quest'ordine. In una grande redazione c'è un caporedattore che riceve gli articoli da fare, decide chi li scrive e rilegge prima di approvare. CrewAI offre esattamente questi due modelli: il processo sequenziale e quello gerarchico.
I parametri della crew#
Una crew minima ha agenti e task. Ecco i parametri principali, con i valori predefiniti verificati su CrewAI 1.15.21.
| Parametro | Che cosa fa | Predefinito |
|---|---|---|
agents | La lista degli agenti della squadra | obbligatorio |
tasks | La lista dei task; nel sequenziale l'ordine della lista è l'ordine di esecuzione | obbligatorio |
process | Process.sequential oppure Process.hierarchical | sequenziale |
verbose | Stampa i passaggi nel terminale | False |
manager_llm | Il modello del manager, obbligatorio nel gerarchico (oppure manager_agent) | nessuno |
max_rpm | Richieste al minuto per la crew; in 1.15.21 vale per gli agenti che non hanno un loro max_rpm (i docs dicono che li sostituisce tutti) | nessun limite |
planning | Fa scrivere un piano prima di iniziare (lo vediamo più avanti) | False |
Altri parametri, come memory, arrivano nei capitoli successivi.
Il processo sequenziale#
Il Processo sequenziale: I task si eseguono nell'ordine in cui li scrivi; il risultato di ciascuno passa come contesto ai successivi. È il processo predefinito. glossario è quello predefinito e quello che hai usato finora. Funziona così:
- i task si eseguono nell'ordine della lista
tasks; - ogni task ha il suo
agent, scelto da te; - ogni task riceve i risultati dei precedenti (o quelli indicati in
context); - il risultato della crew è il risultato dell'ultimo task.
crew = Crew(
agents=[ricercatore, scrittore],
tasks=[ricerca, guida], # prima ricerca, poi guida
process=Process.sequential, # si può anche omettere: è il predefinito
verbose=True,
)È prevedibile, facile da capire e da correggere, e costa meno: nessuna chiamata al modello oltre a quelle degli agenti. Per la maggior parte dei casi, compresi quasi tutti gli esempi di questo corso, è la scelta giusta.
Il processo gerarchico#
Nel Processo gerarchico: Un agente manager riceve i task, li assegna ai membri più adatti e controlla i risultati. Richiede manager_llm o manager_agent. glossario i task non sono assegnati in anticipo. Un Manager (processo gerarchico): L'agente capo della crew gerarchica: non esegue i task di persona, li affida ai colleghi con la delega e controlla i risultati. CrewAI lo crea da solo a partire da manager_llm. glossario li riceve, decide a quale agente affidarli usando la Delega: La possibilità, per un agente con allow_delegation=True, di chiedere aiuto o passare un pezzo di lavoro a un collega della crew. glossario, valuta i risultati e stabilisce quando un task è completo.
Due cose da sapere prima di scriverne una:
manager_llmè obbligatorio (in alternativamanager_agent). Senza, in CrewAI 1.15.21 la crew non si crea nemmeno: l'errore diceAttribute manager_llm or manager_agent is required when using hierarchical process.- Il manager lo crea CrewAI. Con
manager_llmCrewAI costruisce da solo un agente con ruolo «Crew Manager», gli dà gli strumenti per affidare lavoro e fare domande ai colleghi e lo fa lavorare con il modello che indichi.
Un esempio completo#
Una biblioteca comunale vuole annunciare sul suo blog la «Settimana della lettura». Due specialisti, un ideatore di attività e un redattore, e due task senza agent: sarà il manager a decidere chi fa cosa.
# /// script
# requires-python = ">=3.10,<3.14"
# dependencies = ["crewai[tools]==1.15.21"]
# ///
"""Una crew gerarchica: un manager distribuisce il lavoro tra ideatore e redattore."""
import os
from crewai import Agent, Crew, Process, Task
# Il modello si sceglie nel file .env (capitolo 7). Se MODEL manca, si usa quello scritto qui.
MODELLO = os.getenv("MODEL", "openai/gpt-4.1-mini")
ideatore = Agent(
role="Ideatore di attività culturali per biblioteche comunali",
goal="Proporre attività semplici, gratuite e adatte a tutte le età",
backstory="Da dieci anni organizzi letture e laboratori in piccole biblioteche con pochi fondi.",
llm=MODELLO,
)
redattore = Agent(
role="Redattore del blog di una biblioteca comunale",
goal="Scrivere post brevi, chiari e accoglienti per i cittadini",
backstory="Scrivi per un pubblico di ogni età: frasi corte, nessun termine tecnico.",
llm=MODELLO,
)
# Nel processo gerarchico i task NON hanno agent: li assegna il manager.
idee = Task(
description="Proponi 4 attività per la {evento} della biblioteca, con il pubblico adatto a ciascuna.",
expected_output="Un elenco di 4 voci in italiano: nome dell'attività, pubblico, una frase di descrizione.",
)
post = Task(
description="Scrivi il post del blog che annuncia la {evento}, usando le attività proposte.",
expected_output="Un post in italiano di massimo 150 parole, con un titolo.",
context=[idee], # nel gerarchico il passaggio dei risultati si dichiara con context
output_file="post_blog.md",
)
crew = Crew(
agents=[ideatore, redattore],
tasks=[idee, post],
process=Process.hierarchical,
manager_llm=MODELLO, # obbligatorio: il modello del manager creato da CrewAI
verbose=True,
)
if __name__ == "__main__":
risultato = crew.kickoff(inputs={"evento": "Settimana della lettura"})
print("\n=== RISULTATO FINALE ===")
print(risultato.raw)
print("\n=== TOKEN USATI ===")
print(risultato.token_usage)Rispetto a una crew sequenziale cambiano tre righe: i task non hanno agent, la crew ha process=Process.hierarchical e manager_llm=MODELLO. Il context=[idee] nel secondo task non è indispensabile (anche qui i risultati precedenti passano in automatico), ma la guida ufficiale consiglia di dichiararlo nel gerarchico: rende esplicito da dove arrivano i dati. Nota anche che il compito è creativo, non chiede fatti da verificare: con modelli senza strumenti di ricerca il rischio di informazioni false è molto più basso.
Lanciandolo con uv run --env-file .env redazione_biblioteca.py, nei riquadri stampati da verbose vedrai lavorare prima il «Crew Manager», che affida il lavoro ai colleghi, e poi i due specialisti chiamati da lui.
Il manager è a sua volta un agente che interroga il modello: ogni decisione di delega e ogni controllo sono chiamate in più. Una crew gerarchica usa quindi più token e più tempo di una sequenziale con gli stessi task, e funziona bene solo se il modello del manager sa usare gli strumenti di delega. Per il manager conviene un modello capace; se il lavoro è una semplice fila di passaggi, resta sul sequenziale.
Un manager scritto da te#
Se vuoi decidere tu ruolo e stile del manager, crea un agente e passalo come manager_agent al posto di manager_llm. La documentazione lo scrive con allow_delegation=True, e il manager non deve avere strumenti: in 1.15.21, se ne ha, CrewAI si ferma con l'errore Manager agent should not have tools. Il manager non va messo nella lista agents: se lo fai, la crew non si crea e l'errore dice Manager agent should not be included in agents list.
caporedattore = Agent(
role="Caporedattore del blog della biblioteca",
goal="Far uscire post corretti e puntuali affidando ogni parte alla persona giusta",
backstory="Coordini volontari e bibliotecari da anni e rileggi tutto prima di pubblicare.",
llm=MODELLO,
allow_delegation=True,
)
crew = Crew(
agents=[ideatore, redattore], # il manager non va in questa lista
tasks=[idee, post],
process=Process.hierarchical,
manager_agent=caporedattore,
)Avviare la crew: kickoff, inputs e kickoff_for_each#
kickoff(): Il metodo che fa partire il lavoro di una crew, di un agente o di un flow. Il nome viene dal calcio d'inizio. glossario fa partire la crew. Con inputs, un Dizionario: Una raccolta di coppie nome → valore tra parentesi graffe: {"citta": "Arezzo"}. glossario, riempi i segnaposto: i valori vengono sostituiti in role, goal, backstory, description ed expected_output di tutti gli agenti e i task.
risultato = crew.kickoff(inputs={"evento": "Settimana della lettura"})Se vuoi eseguire la stessa crew su più casi, per esempio tre eventi diversi, usa kickoff_for_each: riceve una lista di dizionari, esegue la crew una volta per ciascuno e restituisce una lista di risultati, nello stesso ordine.
eventi = [
{"evento": "Settimana della lettura"},
{"evento": "Festa dei fumetti"},
{"evento": "Notte dei racconti di paura"},
]
risultati = crew.kickoff_for_each(inputs=eventi) # tre esecuzioni complete, una dopo l'altra
for caso, risultato in zip(eventi, risultati): # zip accoppia ogni evento al suo risultato
print(caso["evento"], "usa", risultato.token_usage.total_tokens, "token")Ogni esecuzione è completa: tre casi costano circa tre volte i token di uno. Esistono anche versioni asincrone (akickoff, akickoff_for_each) per chi deve lanciare molte crew insieme; non ci servono in questo corso.
Leggere il risultato: CrewOutput#
kickoff() restituisce un CrewOutput: L'oggetto restituito da crew.kickoff(): contiene il testo finale (raw), l'eventuale output strutturato, i risultati dei singoli task e i token usati. glossario. Questi sono i suoi campi, verificati su 1.15.21:
| Campo | Che cosa contiene |
|---|---|
raw | Il testo del risultato finale, cioè dell'ultimo task |
pydantic | Il risultato in forma strutturata, se l'ultimo task usa output_pydantic (capitolo 13); altrimenti None |
json_dict | Il risultato come dizionario, se l'ultimo task usa output_json (capitolo 13); altrimenti None |
tasks_output | La lista dei risultati di ogni task, ciascuno con raw, agent, description e altri campi |
token_usage | I token usati: total_tokens, prompt_tokens, completion_tokens, successful_requests (richieste al modello) |
risultato = crew.kickoff(inputs={"evento": "Settimana della lettura"})
print(risultato.raw) # il post finale
print(risultato.tasks_output[0].raw) # l'elenco di idee del primo task
print(risultato.token_usage.total_tokens) # quanti token in tutto
print(risultato.token_usage.successful_requests) # quante richieste al modelloLe parentesi quadre con un numero prendono un elemento di una Lista: Una sequenza ordinata di valori tra parentesi quadre: [ricercatore, scrittore]. glossario: [0] è il primo, perché in Python si conta da zero. Nel capitolo 8 la riga dei token del primo crew diceva total_tokens=1232 e successful_requests=2 con qwen2.5:7b: sono esattamente questi campi.
planning: un piano prima di iniziare#
Con planning: Opzione della crew (planning=True) che, prima di iniziare, fa scrivere a un agente pianificatore un piano passo passo per ogni task e lo aggiunge alla descrizione del task. glossario=True, prima che la crew inizi, CrewAI fa lavorare un agente in più, il «Task Execution Planner», che legge tutti i task e scrive un piano passo passo per ciascuno. Ogni piano viene aggiunto in fondo alla description del suo task. L'idea è dare agli agenti una traccia più dettagliata; il costo è una chiamata al modello in più, con un testo lungo.
crew = Crew(
agents=[ideatore, redattore],
tasks=[idee, post],
planning=True,
planning_llm=MODELLO, # indicalo sempre: altrimenti usa un modello OpenAI
)Se attivi planning senza planning_llm, il pianificatore usa un modello di OpenAI e serve una chiave OpenAI valida, anche se i tuoi agenti usano Ollama o un altro provider. La documentazione indica gpt-4o-mini; nel codice di CrewAI 1.15.21 il valore predefinito è invece gpt-5.4-mini. In entrambi i casi è un modello a pagamento che forse non volevi: scrivi sempre planning_llm=MODELLO.
Prova tu: il primo crew in versione gerarchica e su tre città
Parti da primo_crew.py del capitolo 8. Primo esercizio: trasformalo in una crew gerarchica. Secondo esercizio: torna al sequenziale e lancialo su Arezzo, Lecce e Trento con un solo comando, stampando per ogni città il titolo della guida (la prima riga di raw).
Per il gerarchico cambiano tre punti: togli agent=... dai due task, aggiungi alla crew process=Process.hierarchical e manager_llm=MODELLO.
Per le tre città, nel task guida scrivi output_file="guida_{citta}.md": il segnaposto funziona anche nel nome del file, così ogni città ha il suo file invece di sovrascrivere lo stesso. Poi sostituisci il blocco finale con:
if __name__ == "__main__":
citta = [{"citta": "Arezzo"}, {"citta": "Lecce"}, {"citta": "Trento"}]
risultati = crew.kickoff_for_each(inputs=citta)
for caso, risultato in zip(citta, risultati):
prima_riga = risultato.raw.splitlines()[0] # splitlines divide il testo in righe
print(caso["citta"], "→", prima_riga)Con un modello locale lento conta tre esecuzioni complete: tre volte il tempo. E ricorda che senza strumenti di ricerca le guide possono contenere luoghi inventati, per tutte e tre le città.
- La crew unisce
agentsetasks;processdecide come lavorano,verbosemostra i passaggi. - Sequenziale (predefinito): ordine e agenti li scegli tu; il risultato è quello dell'ultimo task. È la scelta giusta nella maggior parte dei casi.
- Gerarchico: i task non hanno agent, un manager delega e controlla. Serve
manager_llm(omanager_agentsenza strumenti), altrimenti la crew non si crea. Costa di più. kickoff(inputs={...})riempie i segnaposto;kickoff_for_each(inputs=[...])ripete la crew su più casi e restituisce una lista.- Il CrewOutput ha
raw,pydantic,json_dict,tasks_outputetoken_usage. planning=Trueaggiunge un piano a ogni task: indica sempreplanning_llm, altrimenti usa un modello OpenAI.
I nostri agenti finora hanno lavorato «a memoria», e hai visto che cosa succede. Nel prossimo capitolo gli diamo le mani: gli strumenti.
Corso indipendente, non affiliato a CrewAI Inc. Contenuti verificati su CrewAI 1.15.21 il 15 settembre 2026.