I mattoni di CrewAI
14Il progetto ufficiale: crewai create e crewai run
Che cosa crea crewai create crew: il progetto JSON di oggi e il progetto classico con YAML e crew.py. Impari a leggere i file generati, a installarli con crewai install, ad avviarli con crewai run e a scegliere tra script e progetto.
Finora hai scritto ogni crew in un unico file: agenti, task e avvio uno sotto l'altro. Per imparare è perfetto, ma quando il lavoro cresce un file solo diventa come una cucina in cui ingredienti, ricette e pentole stanno tutti sullo stesso tavolo. Il progetto ufficiale di CrewAI è la cucina con i cassetti etichettati: gli agenti in un file, i task in un altro, il codice in un altro ancora, sempre negli stessi posti. Chi apre un progetto CrewAI, che sia un collega o un assistente di programmazione, sa subito dove guardare. Il comando che lo prepara è crewai create crew.
Due tipi di progetto#
La CLI: Command Line Interface: un programma che si usa dal terminale con comandi. CrewAI ne ha una: crewai create, crewai run… glossario di CrewAI, il programma crewai che hai installato nel capitolo 6, oggi crea due tipi di progetto diversi. Quando leggi una guida in rete, controlla sempre di quale parla.
| Comando | Che cosa crea | Dove descrivi agenti e task |
|---|---|---|
crewai create crew nome | il progetto JSON, il predefinito in CrewAI 1.15.21 | crew.jsonc e agents/*.jsonc |
crewai create crew nome --classic | il progetto classico | config/agents.yaml, config/tasks.yaml e crew.py |
Il progetto classico è quello che trovi nella maggior parte dei tutorial e nelle skill ufficiali di CrewAI, ed è quello che guardiamo più da vicino; il progetto JSON è la novità, e conviene saperlo riconoscere. In tutti e due i casi usa nomi con il trattino basso, come guida_viaggio. Python non accetta trattini nei nomi dei moduli: se scrivi guida-viaggio, in CrewAI 1.15.21 la CLI crea da sola la cartella guida_viaggio (lo abbiamo verificato con entrambi i tipi di progetto), ma poi il nome che hai scritto e quello della cartella non coincidono, e ci si confonde.
Il progetto JSON: crewai create crew#
Lanciato senza opzioni, il comando apre una procedura guidata nel terminale: ti chiede ruolo, obiettivo e backstory del primo agente, gli strumenti, la descrizione del task e il risultato atteso, poi il provider e il modello, e infine le chiavi API, che scrive nel file .env insieme a MODEL. Crea anche un archivio Git, cioè attiva nella cartella il sistema che tiene la storia delle modifiche ai file.
crewai create crew guida_viaggioPer fotografare il risultato senza rispondere alle domande abbiamo usato la modalità non interattiva, con la Variabile d'ambiente: Un valore con un nome (per esempio OPENAI_API_KEY) che i programmi leggono dal sistema invece che dal codice. Serve a tenere i segreti fuori dai file di codice. glossario CREWAI_DMN=true: accetta le risposte predefinite e non scrive il file .env.


Il cuore del progetto sono due file in JSONC, cioè JSON: Formato di testo per dati strutturati con graffe, virgolette e due punti. È il formato predefinito dei nuovi progetti CrewAI (crew.jsonc). glossario con i commenti: le righe che iniziano con // sono note per te, e il programma le ignora. I file generati sono pieni di commenti che elencano le opzioni disponibili; qui sotto trovi crew.jsonc con i commenti tolti, così si vede la struttura.
{
"name": "prova_json",
"agents": ["researcher"],
"tasks": [
{
"name": "research_task",
"description": "Research current AI trends and write a concise summary.",
"expected_output": "A concise markdown report with key findings.",
"agent": "researcher"
}
],
"process": "sequential",
"verbose": true,
"memory": true,
"inputs": {}
}Riconosci quasi tutto. agents elenca gli agenti per nome; ogni task ha description, expected_output e l'agent che lo esegue; process è il processo del capitolo 11; inputs contiene i valori predefiniti dei segnaposto. "memory": true attiva la memoria, che vedrai nel capitolo 15. Il nome researcher rimanda al file agents/researcher.jsonc, anche questo senza commenti:
{
"role": "Senior Researcher",
"goal": "Research the requested topic and identify useful findings.",
"backstory": "You are an experienced researcher who finds relevant information and presents it clearly.",
"llm": "openai/gpt-4o",
"tools": [],
"settings": {
"verbose": false,
"allow_delegation": false
}
}Nel file generato, i commenti accanto a "tools" spiegano che gli strumenti pronti si indicano per nome, per esempio "SerperDevTool", e quelli scritti da te con "custom:nome", che carica il file tools/nome.py. Il modello si cambia in "llm", nello stesso formato provider/modello che usi nel file .env.
La documentazione avverte di eseguire progetti JSON solo se vengono da fonti di cui ti fidi: gli strumenti custom: e i riferimenti {"python": ...} eseguono codice Python sul tuo computer appena il crew viene caricato. Un progetto scaricato da internet va letto prima di essere avviato.
YAML, spiegato da zero#
Il progetto classico descrive agenti e task in YAML: Formato di file di testo per scrivere configurazioni in modo leggibile, con rientri e coppie chiave: valore. Nei progetti CrewAI classici descrive agenti e task. glossario, un formato pensato per essere letto dalle persone: niente graffe e poche virgolette, perché la struttura la danno i rientri. Ecco un esempio inventato per mostrare tutte le regole in poche righe:
# Le righe che iniziano con # sono commenti
ricercatore:
role: Ricercatore di viaggi
goal: >
Trovare le 3 cose migliori da fare
a {citta} in un weekend
strumenti:
- ricerca web
- lettura pagineLe regole che ti servono:
- Ogni riga è una coppia
chiave: valore, con uno spazio dopo i due punti. - Il rientro dice che cosa sta dentro cosa:
role,goalestrumentiappartengono aricercatore. Usa sempre gli spazi (di solito due), mai il tasto Tab. - Il simbolo
>dopo i due punti annuncia un testo su più righe: le righe rientrate sotto vengono unite in un'unica frase, con uno spazio al posto di ogni a capo. - Le righe che iniziano con un trattino e uno spazio sono gli elementi di una Lista: Una sequenza ordinata di valori tra parentesi quadre:
[ricercatore, scrittore]. glossario. - I segnaposto come
{citta}funzionano come negli script: li sostituiscekickoff(inputs=...).
YAML e JSON possono descrivere gli stessi dati: la prima riga dell'esempio, in JSON, sarebbe {"ricercatore": {"role": "Ricercatore di viaggi"}}. YAML è più comodo da scrivere a mano; JSON è più rigido. Il rovescio della medaglia di YAML è che un rientro sbagliato cambia il significato senza avvisarti: se qualcosa non torna, controlla prima gli spazi.
Il progetto classico: --classic#
Nel laboratorio del corso abbiamo creato un progetto classico così; l'opzione --skip-provider salta le domande su provider e chiavi:
crewai create crew guida_viaggio --classic --skip-provider

Vediamo i file importanti, così come sono stati generati.
config/agents.yaml e config/tasks.yaml#
Il modello di partenza contiene due agenti e due task, in inglese, su un argomento {topic}:
researcher:
role: >
{topic} Senior Data Researcher
goal: >
Uncover cutting-edge developments in {topic}
backstory: >
You're a seasoned researcher with a knack for uncovering the latest
developments in {topic}. Known for your ability to find the most relevant
information and present it in a clear and concise manner.
reporting_analyst:
role: >
{topic} Reporting Analyst
goal: >
Create detailed reports based on {topic} data analysis and research findings
backstory: >
You're a meticulous analyst with a keen eye for detail. You're known for
your ability to turn complex data into clear and concise reports, making
it easy for others to understand and act on the information you provide.research_task:
description: >
Conduct a thorough research about {topic}
Make sure you find any interesting and relevant information given
the current year is {current_year}.
expected_output: >
A list with 10 bullet points of the most relevant information about {topic}
agent: researcher
reporting_task:
description: >
Review the context you got and expand each topic into a full section for a report.
Make sure the report is detailed and contains any and all relevant information.
expected_output: >
A fully fledged report with the main topics, each with a full section of information.
Formatted as markdown without '```'
agent: reporting_analystOgni voce di primo livello, come researcher o research_task, è un nome che crew.py userà. In tasks.yaml, la riga agent: researcher collega il task all'agente con quel nome. I segnaposto {topic} e {current_year} li riempie main.py.
crew.py: il collegamento#
from crewai import Agent, Crew, Process, Task
from crewai.project import CrewBase, agent, crew, task
from crewai.agents.agent_builder.base_agent import BaseAgent
@CrewBase
class GuidaViaggio():
"""GuidaViaggio crew"""
agents: list[BaseAgent]
tasks: list[Task]
@agent
def researcher(self) -> Agent:
return Agent(
config=self.agents_config['researcher'], # type: ignore[index]
verbose=True
)
@agent
def reporting_analyst(self) -> Agent:
return Agent(
config=self.agents_config['reporting_analyst'], # type: ignore[index]
verbose=True
)
@task
def research_task(self) -> Task:
return Task(
config=self.tasks_config['research_task'], # type: ignore[index]
)
@task
def reporting_task(self) -> Task:
return Task(
config=self.tasks_config['reporting_task'], # type: ignore[index]
output_file='report.md'
)
@crew
def crew(self) -> Crew:
"""Creates the GuidaViaggio crew"""
return Crew(
agents=self.agents,
tasks=self.tasks,
process=Process.sequential,
verbose=True,
)Le parti nuove, una alla volta:
- Le funzioni scritte dentro una Classe e oggetto: Una classe è uno stampo (per esempio
Agent); un oggetto è una cosa concreta creata con quello stampo (il tuo agente ricercatore). glossario si chiamano metodi;selfè l'oggetto stesso, e serve per raggiungere le sue parti. @CrewBaseè un Decoratore: Una riga che inizia con@sopra una funzione e le aggiunge un comportamento. In CrewAI:@agent,@task,@start,@listen. glossario applicato alla classe: legge da soloconfig/agents.yamleconfig/tasks.yamle li rende disponibili comeself.agents_configeself.tasks_config.- Ogni metodo con
@agentcrea un agente conconfig=self.agents_config['researcher']: role, goal e backstory arrivano dal YAML. Qui aggiungi ciò che nel YAML non c'è, cometools=[...]del capitolo 12. - I metodi con
@taskfanno lo stesso con i task;output_file='report.md'salva il risultato finale. - Il metodo con
@crewcostruisce laCrew.self.agentseself.tasksli raccoglie CrewAI da tutti i metodi decorati. - Il nome del metodo deve coincidere con il nome della voce nel YAML:
def researcherva conresearcher:. Secondo la guida ufficiale è la causa tipica dell'erroreKeyError. - Le scritte
# type: ignore[index]sono commenti per i programmi che controllano il codice: puoi ignorarle.
main.py: l'avvio#
Ecco la parte iniziale di main.py:
#!/usr/bin/env python
import sys
import warnings
from datetime import datetime
from guida_viaggio.crew import GuidaViaggio
warnings.filterwarnings("ignore", category=SyntaxWarning, module="pysbd")
def run():
"""
Run the crew.
"""
inputs = {
'topic': 'AI LLMs',
'current_year': str(datetime.now().year)
}
try:
GuidaViaggio().crew().kickoff(inputs=inputs)
except Exception as e:
raise Exception(f"An error occurred while running the crew: {e}")La funzione run prepara il Dizionario: Una raccolta di coppie nome → valore tra parentesi graffe: {"citta": "Arezzo"}. glossario inputs e chiama kickoff, proprio come la parte sotto if __name__ == "__main__": dei tuoi script. GuidaViaggio().crew() crea l'oggetto della classe e chiama il suo metodo crew. try ed except intercettano un eventuale errore per mostrarlo con un messaggio più chiaro. Più sotto il file contiene altre funzioni (train, replay, test, run_with_trigger) per usi avanzati che in questo corso non servono.
Gli altri file#
| File | A che cosa serve |
|---|---|
pyproject.toml | Nome del progetto, dipendenze (crewai[tools]>=1.15.21,<2.0.0) e comandi. La riga run_crew = "guida_viaggio.main:run" dice quale funzione avviare. |
tools/custom_tool.py | Un modello di strumento scritto con BaseTool, come nel capitolo 12. |
knowledge/user_preference.txt | Un file di esempio con informazioni per gli agenti (capitolo 15). |
AGENTS.md | Istruzioni lunghe 1.207 righe per gli assistenti di programmazione AI che lavorano sul progetto. |
README.md | Istruzioni generali, in inglese. |
.gitignore | L'elenco dei file che Git non deve salvare. Contiene .env, così le chiavi non finiscono online per sbaglio. |
tests/ | Una cartella vuota, pronta per i test. |
Dal primo crew al progetto classico#
Per trasformare il crew del capitolo 8 in un progetto classico basta modificare tre file. Abbiamo fatto la prova in un progetto creato con crewai create crew guida_arezzo --classic --skip-provider. Prima gli agenti:
# Ogni voce di primo livello è un agente: il nome deve coincidere con il metodo in crew.py.
ricercatore:
role: >
Ricercatore di viaggi
goal: >
Trovare le 3 cose migliori da fare a {citta} in un weekend
backstory: >
Hai girato l'Italia per vent'anni e conosci i posti che valgono davvero.
scrittore:
role: >
Autore di guide brevi
goal: >
Trasformare appunti di viaggio in un testo chiaro e invitante
backstory: >
Scrivi guide tascabili: frasi corte, niente giri di parole.Poi i task, con i nomi degli agenti appena scritti:
ricerca:
description: >
Elenca le 3 attività migliori per un weekend a {citta},
con un motivo per ciascuna.
expected_output: >
Un elenco puntato di 3 voci, in italiano.
agent: ricercatore
guida:
description: >
Usa l'elenco ricevuto per scrivere una mini-guida del weekend a {citta}.
expected_output: >
Un testo di massimo 120 parole in italiano, con un titolo.
agent: scrittoreIn crew.py cambiano solo i nomi dei metodi e delle voci, perché devono corrispondere al YAML:
from crewai import Agent, Crew, Process, Task
from crewai.project import CrewBase, agent, crew, task
from crewai.agents.agent_builder.base_agent import BaseAgent
@CrewBase
class GuidaArezzo():
"""GuidaArezzo crew"""
agents: list[BaseAgent]
tasks: list[Task]
@agent
def ricercatore(self) -> Agent: # stesso nome della voce in agents.yaml
return Agent(
config=self.agents_config['ricercatore'], # type: ignore[index]
verbose=True
)
@agent
def scrittore(self) -> Agent:
return Agent(
config=self.agents_config['scrittore'], # type: ignore[index]
verbose=True
)
@task
def ricerca(self) -> Task: # stesso nome della voce in tasks.yaml
return Task(
config=self.tasks_config['ricerca'], # type: ignore[index]
)
@task
def guida(self) -> Task:
return Task(
config=self.tasks_config['guida'], # type: ignore[index]
output_file='guida.md'
)
@crew
def crew(self) -> Crew:
"""Creates the GuidaArezzo crew"""
return Crew(
agents=self.agents,
tasks=self.tasks,
process=Process.sequential,
verbose=True,
)Infine, in main.py, dentro la funzione run sostituisci il dizionario degli inputs con inputs = {'citta': 'Arezzo'}. Due cose da notare. La classe si chiama GuidaArezzo perché CrewAI la nomina a partire dal nome del progetto. E nessun agente ha llm=: il modello arriva dalla variabile MODEL del file .env. Nella nostra prova, con MODEL=ollama/qwen2.5:7b nel .env, CrewAI ha creato entrambi gli agenti con qwen2.5:7b, e i due task nell'ordine in cui sono scritti, con {citta} sostituito da Arezzo.
Installare e avviare: crewai install e crewai run#
Entra nella cartella del progetto, quella che contiene pyproject.toml, e lancia due comandi:
cd guida_arezzo
crewai install
crewai runcrewai installinstalla le Dipendenza: Un pacchetto di cui il tuo progetto ha bisogno per funzionare. Le dipendenze si elencano inpyproject.tomlo in testa allo script. glossario del progetto. Dietro le quinte esegueuv sync: uv: Programma gratuito che installa Python e i pacchetti in modo rapido e ordinato. È lo strumento consigliato dalla documentazione di CrewAI. glossario crea l'Ambiente virtuale: Una copia isolata di Python dedicata a un progetto, con i suoi pacchetti. Evita che progetti diversi si pestino i piedi. uv lo crea da solo. glossario del progetto nella cartella.venve il fileuv.lock, che fissa le versioni esatte dei pacchetti. La prima volta scarica parecchio.crewai runavvia la crew. In un progetto classico esegueuv run run_crew, cioè la funzionerundimain.pyindicata inpyproject.toml. In un progetto JSON carica direttamentecrew.jsonce, se un segnaposto non ha un valore ininputs, te lo chiede nel terminale.
Ecco le prime righe di crewai install nella nostra prova (output reale, accorciato: abbiamo tolto le due righe con il percorso della cartella e l'elenco dei pacchetti):
$ crewai install
Using CPython 3.12.3 interpreter at: /usr/bin/python3
Creating virtual environment at: .venv
Resolved 158 packages in 6.89s
Prepared 1 package in 7.16s
Installed 145 packages in 1.52sI comandi vanno lanciati dalla cartella principale del progetto: da un'altra cartella crewai run non trova pyproject.toml e non sa che cosa avviare. Se più avanti aggiungi un pacchetto, la documentazione indica uv add nome-pacchetto.
Il file .env nel progetto#
Il file .env va nella cartella principale del progetto, accanto a pyproject.toml, con le stesse righe che usi negli script:
MODEL=ollama/qwen2.5:7b
CREWAI_DISABLE_TELEMETRY=trueQui non serve --env-file. CrewAI 1.15.21, quando viene caricato, cerca un file .env partendo dalla propria cartella di installazione e risalendo verso l'alto; in un progetto la sua cartella di installazione è dentro .venv, quindi la ricerca arriva alla cartella principale e trova il tuo .env. Negli script singoli, invece, uv installa CrewAI in una cartella a parte, e per questo lì usi --env-file .env. La procedura guidata del progetto JSON scrive il .env per te; con --skip-provider o con CREWAI_DMN=true non viene creato e lo scrivi tu. Grazie al .gitignore generato, resta fuori da Git.
Script o progetto: quando conviene cosa#
| Script singolo | Progetto ufficiale |
|---|---|
| Stai imparando o provando un'idea. | Il crew diventa uno strumento che usi spesso o che condividi. |
Un file da mandare a qualcuno, che lo lancia con uv run. | Più persone lavorano sugli stessi file; chi scrive i testi degli agenti può non toccare il codice. |
| Pochi agenti e task, nessuno strumento tuo. | Strumenti tuoi in tools/, file di conoscenza in knowledge/, test. |
| Nessuna installazione da mantenere. | Versioni fissate in uv.lock; è la forma che si aspetta la piattaforma commerciale CrewAI AMP: Agent Management Platform: la piattaforma commerciale di CrewAI Inc. per pubblicare, monitorare e scalare crew e flow. Il framework resta gratuito anche senza AMP. glossario per pubblicare un crew. |
Gli esempi pratici del corso restano script singoli, perché sono più facili da leggere tutti d'un fiato. Per un'applicazione vera la documentazione e le skill ufficiali vanno oltre: consigliano di partire da un Flow: Il "copione" che orchestra passi, crew e agenti con uno stato condiviso, condizioni e diramazioni. La documentazione lo consiglia come struttura per le applicazioni vere. glossario, con crewai create flow, che vedrai nel capitolo 16.
Prova tu: dare gli strumenti al ricercatore del progetto
Nel progetto guida_arezzo, dai al ricercatore la ricerca su Google e la lettura delle pagine del capitolo 12. Che cosa devi cambiare, e in quali file?
Soluzione. Il YAML non cambia: gli strumenti sono oggetti Python, quindi si aggiungono in crew.py. In cima al file aggiungi l'import, e nel metodo ricercatore il parametro tools:
# In cima a crew.py, insieme agli altri import:
from crewai_tools import ScrapeWebsiteTool, SerperDevTool
# Dentro la classe GuidaArezzo, al posto del metodo ricercatore di prima:
@agent
def ricercatore(self) -> Agent:
return Agent(
config=self.agents_config['ricercatore'], # type: ignore[index]
tools=[SerperDevTool(), ScrapeWebsiteTool()],
verbose=True
)Poi aggiungi SERPER_API_KEY=... al file .env del progetto. Il pacchetto crewai_tools è già installato, perché il pyproject.toml generato dipende da crewai[tools]. Conviene anche chiedere le fonti nell'expected_output del task ricerca, in tasks.yaml.
crewai create crew nomecrea oggi un progetto JSON (crew.jsonceagents/*.jsonc) con una procedura guidata;--classiccrea il progetto con YAML,crew.pyemain.py.- YAML usa coppie
chiave: valoree rientri fatti di spazi;>introduce un testo su più righe. - In
crew.py,@CrewBaselegge i YAML e ogni metodo@agento@taskdeve avere lo stesso nome della sua voce. crewai installesegueuv sync;crewai runavvia la crew dalla cartella principale, dove sta anche il.env.- Script per imparare e provare; progetto quando il crew cresce, si condivide o va pubblicato.
Nel prossimo capitolo dai alla squadra la capacità di ricordare e di consultare i tuoi documenti: memoria e knowledge.
Corso indipendente, non affiliato a CrewAI Inc. Contenuti verificati su CrewAI 1.15.21 il 15 settembre 2026.