Vai al contenuto

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.

Tempo di lettura: 25 minuti

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.

ParametroChe cosa faPredefinito
agentsLa lista degli agenti della squadraobbligatorio
tasksLa lista dei task; nel sequenziale l'ordine della lista è l'ordine di esecuzioneobbligatorio
processProcess.sequential oppure Process.hierarchicalsequenziale
verboseStampa i passaggi nel terminaleFalse
manager_llmIl modello del manager, obbligatorio nel gerarchico (oppure manager_agent)nessuno
max_rpmRichieste 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
planningFa 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.
Python
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.

Processo sequenziale e processo gerarchico a confronto A sinistra il processo sequenziale: task 1 e task 2 hanno ciascuno l'agente scelto da te e si eseguono in ordine, passando il risultato. A destra il processo gerarchico: un manager creato da CrewAI con manager_llm riceve i task senza agente, delega il lavoro all'ideatore o al redattore e controlla i risultati. Sequenziale process=Process.sequential task 1 · idee agent=ideatore (lo scegli tu) task 2 · post agent=redattore (lo scegli tu) risultato ordine e agenti li decidi tu Gerarchico process=Process.hierarchical riceve task 1 e task 2, senza agent Manager creato da CrewAI con manager_llm Ideatore Redattore delega e controlla delega e controlla il manager decide chi fa cosa e valuta
A sinistra, nel sequenziale, sei tu a fissare ordine e agenti. A destra, nel gerarchico, un manager riceve i task senza agente, delega a ideatore e redattore e controlla i risultati.

Due cose da sapere prima di scriverne una:

  1. manager_llm è obbligatorio (in alternativa manager_agent). Senza, in CrewAI 1.15.21 la crew non si crea nemmeno: l'errore dice Attribute manager_llm or manager_agent is required when using hierarchical process.
  2. Il manager lo crea CrewAI. Con manager_llm CrewAI 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.

redazione_biblioteca.py
# /// 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.

Attenzione

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.

Python
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.

Python
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.

Python
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:

CampoChe cosa contiene
rawIl testo del risultato finale, cioè dell'ultimo task
pydanticIl risultato in forma strutturata, se l'ultimo task usa output_pydantic (capitolo 13); altrimenti None
json_dictIl risultato come dizionario, se l'ultimo task usa output_json (capitolo 13); altrimenti None
tasks_outputLa lista dei risultati di ogni task, ciascuno con raw, agent, description e altri campi
token_usageI token usati: total_tokens, prompt_tokens, completion_tokens, successful_requests (richieste al modello)
Python
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 modello

Le 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.

Python
crew = Crew(
    agents=[ideatore, redattore],
    tasks=[idee, post],
    planning=True,
    planning_llm=MODELLO,  # indicalo sempre: altrimenti usa un modello OpenAI
)
Attenzione

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:

Python
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à.

In breve
  • La crew unisce agents e tasks; process decide come lavorano, verbose mostra 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 (o manager_agent senza 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_output e token_usage.
  • planning=True aggiunge un piano a ogni task: indica sempre planning_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.