Nelle lezioni precedenti abbiamo costruito le fondamenta del nostro sistema multi-agente. Abbiamo imparato a creare agenti specializzati, assegnare loro task, farli collaborare all'interno di una Crew e utilizzare Ollama per eseguire i modelli linguistici direttamente in locale. Abbiamo inoltre introdotto memoria, knowledge base e strumenti, dando ai nostri agenti la possibilità di utilizzare informazioni aggiuntive e interagire con risorse esterne o locali.
A questo punto possiamo fare un ulteriore passo avanti. Finora ci siamo concentrati soprattutto su che cosa devono fare i nostri agenti; ora dobbiamo concentrarci su come organizzare e automatizzare l'intero processo.
Quando un'applicazione diventa più complessa, infatti, non è sufficiente avere una serie di agenti che eseguono dei task. Dobbiamo stabilire in quale ordine devono essere eseguiti, quali attività dipendono da altre, cosa deve accadere quando un risultato non è soddisfacente e come possiamo combinare più Crew all'interno di un workflow più ampio.
In questa lezione vedremo quindi come passare da una semplice Crew a un sistema di orchestrazione, introducendo workflow più strutturati e automatizzabili.
Dalla Crew al processo automatizzato
Possiamo pensare a una Crew come a una squadra di lavoro. Abbiamo diversi agenti, ognuno con un proprio ruolo, e una serie di attività da completare.Un processo automatizzato aggiunge però un ulteriore livello di organizzazione.
Immaginiamo, per esempio, di voler creare automaticamente un articolo tecnico. Potremmo avere questo processo:

Possiamo realizzare ogni fase utilizzando uno o più agenti.La prima fase potrebbe essere affidata a un agente ricercatore, la seconda a un analista, la terza a uno scrittore e l'ultima a un revisore.
Il vantaggio dell'orchestrazione consiste nel fatto che non dobbiamo gestire manualmente ogni passaggio. Possiamo definire il workflow una volta e lasciare che sia il programma a occuparsi dell'esecuzione.
Il processo sequenziale
Abbiamo già incontrato Process.sequential nelle lezioni precedenti.
È il modello più semplice per organizzare una Crew: i task vengono eseguiti secondo un ordine prestabilito.
Possiamo creare, per esempio, una Crew composta da tre agenti:
from crewai import Agent, Task, Crew, Process, LLM
llm = LLM(
model="ollama/llama3.2",
base_url="http://localhost:11434"
)
researcher = Agent(
role="Ricercatore",
goal="Raccogliere le informazioni necessarie",
backstory="Siamo esperti nella ricerca e organizzazione delle informazioni.",
llm=llm
)
writer = Agent(
role="Scrittore",
goal="Creare un documento chiaro e completo",
backstory="Siamo esperti di scrittura tecnica.",
llm=llm
)
reviewer = Agent(
role="Revisore",
goal="Controllare la qualità del documento",
backstory="Siamo esperti nella revisione di documenti tecnici.",
llm=llm
)
Definiamo ora i task:
research_task = Task(
description=(
"Studiare l'argomento {topic} e produrre "
"un rapporto con le informazioni principali."
),
expected_output="Un rapporto strutturato.",
agent=researcher
)
writing_task = Task(
description=(
"Utilizzare la ricerca precedente per scrivere "
"un documento completo sull'argomento."
),
expected_output="Un documento tecnico completo.",
agent=writer,
context=[research_task]
)
review_task = Task(
description=(
"Controllare il documento prodotto dallo scrittore. "
"Individuare eventuali errori e proporre correzioni."
),
expected_output="Una revisione del documento.",
agent=reviewer,
context=[writing_task]
)
A questo punto possiamo creare la Crew:
crew = Crew(
agents=[researcher, writer, reviewer],
tasks=[research_task, writing_task, review_task],
process=Process.sequential,
verbose=True
)
Infine avviamo il processo:
result = crew.kickoff(
inputs={
"topic": "Intelligenza artificiale locale"
}
)
print(result)
In questo caso abbiamo costruito una piccola pipeline automatizzata.
Non dobbiamo chiamare manualmente il ricercatore, aspettare il risultato e successivamente chiamare lo scrittore. La Crew gestisce il processo seguendo l'ordine che abbiamo definito.
Perché l'orchestrazione diventa importante?
Quando il numero di agenti aumenta, la gestione manuale del workflow diventa rapidamente difficile.
Immaginiamo di avere dieci agenti e venti attività. Alcuni task devono essere eseguiti prima di altri, mentre alcuni potrebbero essere eseguiti contemporaneamente. In una situazione simile, dobbiamo separare due concetti:
l'intelligenza degli agenti e l'organizzazione del processo.
Gli agenti si occupano di ragionare e svolgere i propri compiti. L'orchestratore si occupa invece di stabilire come deve procedere il sistema. Questa separazione rende l'applicazione più facile da comprendere e da modificare. Se domani vogliamo sostituire il revisore, per esempio, non dobbiamo necessariamente modificare tutto il workflow. Possiamo intervenire solamente sul componente interessato.
Quando utilizzare una Crew e quando un Flow
CrewAI mette a disposizione due concetti che possiamo utilizzare insieme: Crews e Flows.
Una Crew è particolarmente adatta quando vogliamo che più agenti collaborino per risolvere un problema. Possiamo quindi lasciare agli agenti una certa autonomia.
Un Flow, invece, ci permette di definire in maniera più precisa il percorso che deve seguire l'applicazione.
Possiamo quindi immaginare:

In questo modello il Flow diventa il coordinatore generale, mentre le Crew possono occuparsi di singole parti del lavoro. È un'architettura particolarmente interessante perché ci permette di combinare controllo deterministico e autonomia degli agenti.
Creare un primo Flow
Possiamo definire un Flow utilizzando le funzionalità messe a disposizione da CrewAI.
Un esempio semplice può essere:
from crewai.flow.flow import Flow, start, listen
class ArticleFlow(Flow):
@start()
def start_process(self):
return {
"topic": "Intelligenza artificiale locale"
}
@listen(start_process)
def create_article(self, data):
print("Creiamo un articolo su:", data["topic"])
flow = ArticleFlow()
result = flow.kickoff()
print(result)
Il concetto fondamentale è rappresentato dai decorator @start() e @listen().
Con @start() indichiamo il punto dal quale deve iniziare il workflow.
Con @listen() indichiamo invece che un metodo deve essere eseguito in risposta al completamento di un'altra fase.
In questo modo possiamo costruire un flusso nel quale ogni fase reagisce agli eventi prodotti dalla fase precedente.
Utilizzare un Flow per avviare una Crew
La parte più interessante arriva quando utilizziamo un Flow per orchestrare una vera Crew. Possiamo, per esempio, creare una funzione che costruisce e avvia la nostra Crew:
from crewai.flow.flow import Flow, start
class ResearchFlow(Flow):
@start()
def research(self):
crew = create_research_crew()
result = crew.kickoff(
inputs={
"topic": "Ollama e modelli locali"
}
)
return result
La funzione create_research_crew() potrebbe essere:
def create_research_crew():
return Crew(
agents=[researcher, analyst],
tasks=[research_task, analysis_task],
process=Process.sequential,
verbose=True
)
In questo modo il Flow non deve occuparsi direttamente dei dettagli del lavoro degli agenti. Il Flow decide quando avviare la Crew, mentre la Crew si occupa di come gli agenti devono collaborare.
Conclusioni
In questa lezione abbiamo fatto un passo importante verso la costruzione di sistemi AI realmente automatizzati. Abbiamo visto come organizzare i task in processi sequenziali, come utilizzare i Flow per controllare l'esecuzione e come combinare un'orchestrazione strutturata con Crew composte da agenti specializzati.
A questo punto abbiamo tutti gli elementi necessari per costruire un sistema multi-agente completo, locale e autonomo. Abbiamo imparato a creare gli agenti, definirne i compiti, gestire la memoria, utilizzare una Knowledge Base, integrare strumenti e orchestrare l'intero processo attraverso CrewAI e Ollama.
Se vuoi aggiornamenti su Automazione dei processi e orchestrazione delle crew inserisci la tua email nel box qui sotto: