I mattoni di CrewAI
12Gli strumenti: dare le mani agli agenti
Perché un agente senza strumenti inventa, come sceglie lo strumento giusto, gli strumenti pronti di crewai_tools, come crearne uno tuo con @tool o BaseTool e che cos'è MCP.
Nel capitolo 8 il primo crew ha scritto con grande sicurezza una guida del weekend ad Arezzo, ma dentro c'erano luoghi sbagliati o inventati, come una gita a Norcia «a circa 45 minuti». Non era solo colpa del modello piccolo: gli agenti non avevano nessun modo di controllare. Pensa a un cuoco bravissimo chiuso in una stanza senza dispensa e senza telefono: se gli chiedi che cosa c'è oggi al mercato, tira a indovinare. Gli Strumento (tool): Una funzione che l'agente può chiamare per agire fuori dal modello: cercare sul web, leggere un file, interrogare un database, inviare una email. glossario sono la dispensa e il telefono dell'agente. In questo capitolo vedi come funzionano, usi quelli pronti e ne costruisci uno tuo.
Perché un agente ha bisogno di strumenti#
Un LLM: Large Language Model, grande modello linguistico: un programma addestrato su enormi quantità di testo che, data una frase, prevede le parole che seguono. È il motore di ChatGPT, Claude, Gemini. glossario sa soltanto quello che ha letto durante l'addestramento e quello che trova nel Prompt: Il testo che dai in ingresso a un modello: domanda, istruzioni, esempi. La qualità della risposta dipende molto dalla chiarezza del prompt. glossario. Non naviga su internet, non apre i tuoi file, non usa una calcolatrice: produce il testo più plausibile. Quando l'informazione manca, il testo plausibile può essere falso, ed ecco l'Allucinazione: Quando un modello scrive con sicurezza una cosa falsa o inventata. Succede perché il modello genera testo plausibile, non verifica fatti. glossario.
Uno strumento è una Funzione: Un blocco di codice con un nome che fa un lavoro e restituisce un risultato. Si definisce con def e si chiama con le parentesi: somma(2, 3). glossario Python che CrewAI esegue per conto dell'agente: cerca sul web, legge una pagina, apre un file, fa un calcolo. Il risultato torna al modello come testo, e da quel momento l'agente ragiona su dati veri invece che su ricordi vaghi. La guida ufficiale di CrewAI per progettare i task lo dice chiaramente: se un task deve procurarsi dei dati e l'agente non ha strumenti, l'agente li inventa. (Che cos'è esattamente una funzione lo vedi più avanti, quando ne scrivi una.)
Come l'agente decide di usare uno strumento#
Quando dai a un Agent (in CrewAI): Il membro della squadra. Si definisce con tre testi obbligatori — role, goal, backstory — più modello e strumenti opzionali. glossario una lista di strumenti, CrewAI mostra al modello una specie di catalogo: per ogni strumento, il nome, una descrizione e i parametri che accetta. È il ciclo del capitolo 9: il modello decide se rispondere o chiedere uno strumento con certi valori, CrewAI esegue davvero la funzione e rimette il risultato nella conversazione, fino alla risposta finale o al limite di max_iter: Numero massimo di giri di ragionamento che un agente può fare su un task prima di dare la risposta migliore che ha. In CrewAI 1.15 il valore predefinito è 25. glossario.
La descrizione conta più del codice#
Se la descrizione è vaga, l'agente non capisce quando usare lo strumento, oppure lo usa nel momento sbagliato. Il modello di strumento che CrewAI mette nei progetti nuovi lo ricorda proprio nella descrizione: «Descrizione chiara di a cosa serve questo strumento: il tuo agente avrà bisogno di questa informazione per usarlo» (traduzione nostra).
| Descrizione debole | Descrizione utile |
|---|---|
| «Fa dei conti.» | «Calcola il costo di un weekend: alloggio, pasti, totale e quota a persona. Usalo ogni volta che servono conti sul budget di un viaggio.» |
| «Legge dati.» | «Legge il listino prezzi del negozio. Usalo quando ti serve il prezzo aggiornato di un prodotto; il parametro è il codice del prodotto.» |
Una buona descrizione dice che cosa fa lo strumento, quando usarlo e che cosa significano i parametri.
Gli strumenti pronti di crewai_tools#
CrewAI ha un pacchetto di strumenti già scritti, crewai_tools. Non arriva con il solo crewai (lo abbiamo verificato): serve la Dipendenza: Un pacchetto di cui il tuo progetto ha bisogno per funzionare. Le dipendenze si elencano in pyproject.toml o in testa allo script. glossario crewai[tools], che è proprio quella scritta in testa a tutti gli script del corso. Ecco i cinque che userai più spesso.
| Strumento | Che cosa fa |
|---|---|
SerperDevTool | Cerca su Google e restituisce titoli, link e brevi estratti dei risultati. È l'unico dei cinque che richiede una chiave, SERPER_API_KEY. |
ScrapeWebsiteTool | Legge il testo di una pagina web. |
FileReadTool | Legge il contenuto di un file sul tuo computer. |
DirectoryReadTool | Elenca i file contenuti in una cartella. |
FileWriterTool | Scrive un testo in un file. |
Si Import: La riga from ... import ... che rende disponibili in un file Python le parti di una libreria, per esempio Agent e Task di CrewAI. glossario tutti allo stesso modo e si creano con le parentesi, eventualmente con qualche impostazione:
from crewai_tools import DirectoryReadTool, FileReadTool, FileWriterTool, ScrapeWebsiteTool, SerperDevTool
ricerca_web = SerperDevTool(n_results=5) # quanti risultati restituire (predefinito: 10)
lettore_pagine = ScrapeWebsiteTool() # senza indirizzo: l'agente sceglie quale pagina leggere
lettore_file = FileReadTool() # legge file dentro la cartella da cui lanci lo script
elenco_file = DirectoryReadTool(directory="appunti") # elenca i file della cartella appunti
scrittore_file = FileWriterTool() # scrive file, sempre dentro la cartella consentitaSerperDevTool: la ricerca su Google#
Serper: Servizio online (serper.dev) che restituisce i risultati di ricerca di Google a un programma. Lo usa SerperDevTool; serve la chiave SERPER_API_KEY. glossario è un servizio online che fa ricerche su Google per conto di un programma. Per usarlo ti registri su serper.dev, copi la tua Chiave API: Una lunga password personale che identifica chi usa un'API e a chi addebitare i costi. Va tenuta segreta: mai pubblicarla o condividerla. glossario e la metti nel File .env: File di testo nella cartella del progetto con le variabili d'ambiente, una per riga: NOME=valore. Non va mai condiviso né caricato online. glossario con il nome SERPER_API_KEY. Il 15 settembre 2026 la pagina principale del sito prometteva «2,500 free queries» e «No credit card required», cioè 2.500 ricerche gratuite senza carta di credito. Le offerte cambiano: controlla sul sito prima di contarci.
MODEL=openai/gpt-4.1-mini
OPENAI_API_KEY=sk-...la-tua-chiave...
SERPER_API_KEY=...la-tua-chiave-serper...
CREWAI_DISABLE_TELEMETRY=trueOgni ricerca che l'agente fa consuma una ricerca del tuo piano, e un agente indeciso può farne diverse per un solo task. Per questo conviene fissare max_iter, che limita i giri di ragionamento.
ScrapeWebsiteTool: leggere una pagina#
La ricerca restituisce solo titoli ed estratti. Per leggere una pagina intera serve il Web scraping: Leggere automaticamente il contenuto di una pagina web da un programma. In CrewAI: ScrapeWebsiteTool. glossario, cioè far scaricare a un programma il testo di un sito. ScrapeWebsiteTool fa esattamente questo. Se lo crei senza indirizzo, l'agente può leggere le pagine che trova; se scrivi ScrapeWebsiteTool(website_url="https://..."), lo limiti a quella pagina. Alcuni siti bloccano i programmi che leggono le pagine, e le condizioni d'uso di un sito possono vietarlo: rispettale.
Gli strumenti per i file#
FileReadTool, DirectoryReadTool e FileWriterTool lavorano sul tuo computer. In CrewAI 1.15.21 lettura e scrittura sono confinate: FileReadTool e FileWriterTool rifiutano i percorsi che escono dalla cartella da cui hai lanciato lo script, a meno che tu non indichi un'altra cartella con il parametro base_dir. È una protezione utile: un agente confuso non può leggere o sovrascrivere file fuori dal tuo progetto.
Molti tutorial in rete usano CodeInterpreterTool, uno strumento che faceva eseguire codice Python all'agente. È stato rimosso: in CrewAI 1.15.21 la riga from crewai_tools import CodeInterpreterTool fallisce con un ImportError (lo abbiamo verificato), anche se la pagina riassuntiva degli strumenti nella documentazione lo elenca ancora. Sono deprecate anche le opzioni degli agenti allow_code_execution e code_execution_mode; per eseguire codice la documentazione rimanda ad ambienti isolati esterni come E2B o Modal. Nei tutorial vecchi trovi anche from crewai_tools import BaseTool: oggi si scrive from crewai.tools import BaseTool, tool.
Strumenti all'agente o al task#
Puoi dare gli strumenti in due punti.
- All'agente, con
Agent(tools=[...]): l'agente li ha a disposizione in tutti i suoi task. - Al task, con
Task(tools=[...]): valgono solo per quel task e prendono il posto di quelli dell'agente.
In questo frammento il ricercatore ha due strumenti in generale, ma nel task sugli orari può solo leggere pagine:
ricercatore = Agent(
role="Ricercatore di viaggi",
goal="Trovare informazioni verificate su {citta}",
backstory="Controlli sempre le fonti.",
tools=[ricerca_web, lettore_pagine], # validi per tutti i task di questo agente
llm=MODELLO,
)
controllo_orari = Task(
description="Leggi la pagina degli orari del museo e riporta gli orari del sabato.",
expected_output="Gli orari del sabato, in italiano, con il link alla pagina.",
agent=ricercatore,
tools=[lettore_pagine], # solo per questo task: niente ricerche, solo lettura
)Il primo crew, questa volta con la ricerca#
Ora riprendi il crew del capitolo 8 e dai al ricercatore due strumenti: la ricerca su Google e la lettura delle pagine. Cambiano anche i testi: al ricercatore chiedi di annotare le fonti, allo scrittore di non aggiungere nulla che non sia nell'elenco. Gli strumenti da soli non bastano: devi anche chiedere di usarli e di dire da dove vengono le informazioni.
# /// script
# requires-python = ">=3.10,<3.14"
# dependencies = ["crewai[tools]==1.15.21"]
# ///
"""Il primo crew, migliorato: il ricercatore cerca sul web e legge le pagine prima di scrivere."""
import os
from crewai import Agent, Crew, Process, Task
from crewai_tools import ScrapeWebsiteTool, SerperDevTool
# 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")
# Gli strumenti si creano una volta e poi si danno agli agenti.
ricerca_web = SerperDevTool(n_results=5) # cerca su Google tramite serper.dev (serve SERPER_API_KEY)
lettore_pagine = ScrapeWebsiteTool() # legge il testo di una pagina web
ricercatore = Agent(
role="Ricercatore di viaggi",
goal="Trovare 3 cose da fare a {citta} in un weekend, controllate su fonti web",
backstory=(
"Non ti fidi della memoria: cerchi sul web, leggi le pagine dei siti ufficiali "
"e annoti sempre l'indirizzo della fonte. Se non trovi conferma, lo dici."
),
tools=[ricerca_web, lettore_pagine], # solo il ricercatore ha gli strumenti
llm=MODELLO,
max_iter=10, # tetto ai giri di ragionamento, e quindi alle ricerche
verbose=True,
)
scrittore = Agent(
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, niente informazioni inventate.",
llm=MODELLO,
verbose=True,
)
ricerca = Task(
description=(
"Cerca sul web le attività migliori per un weekend a {citta}. "
"Leggi almeno una pagina di un sito ufficiale o affidabile, poi scegli 3 attività."
),
expected_output=(
"Un elenco puntato di 3 voci in italiano. Per ogni voce: nome del luogo, "
"un motivo per andarci, indirizzo web della fonte."
),
agent=ricercatore,
)
guida = Task(
description=(
"Usa solo l'elenco ricevuto per scrivere una mini-guida del weekend a {citta}. "
"Non aggiungere luoghi che non sono nell'elenco."
),
expected_output="Un testo di massimo 150 parole in italiano, con un titolo e l'elenco delle fonti in fondo.",
agent=scrittore,
output_file="guida.md",
)
crew = Crew(
agents=[ricercatore, scrittore],
tasks=[ricerca, guida],
process=Process.sequential,
verbose=True,
)
if __name__ == "__main__":
risultato = crew.kickoff(inputs={"citta": "Arezzo"})
print(risultato.raw)Rispetto al capitolo 8 cambiano tre cose: solo il ricercatore riceve gli strumenti (lo scrittore lavora sul testo del task precedente); n_results=5 gli dà meno testo da leggere; l'expected_output chiede l'indirizzo della fonte, così puoi controllare tu. Con la chiave Serper nel file .env, lo lanci come sempre:
uv run --env-file .env guida_con_ricerca.pyNel terminale vedrai anche i riquadri degli strumenti (quale strumento, con quali valori, che cosa ha restituito); alla fine la guida finisce in guida.md. Questo script l'abbiamo verificato a secco ma non eseguito, perché richiede una chiave Serper personale: per questo non ne trovi l'output. Il prossimo gira senza chiavi e l'abbiamo eseguito davvero.
Creare uno strumento tuo#
Per tutto ciò che gli strumenti pronti non coprono (il listino del tuo negozio, un calcolo della tua azienda) ne scrivi uno tu. Prima servono due parole di Python: funzione e decoratore.
La funzione, spiegata da zero#
Una Funzione si definisce con la parola def, seguita dal nome, dai Parametro: Un valore che passi a una funzione o a una classe tra parentesi, con un nome: Agent(role="...") — qui role è il parametro. glossario tra parentesi e dai due punti. Il corpo, rientrato di quattro spazi, fa il lavoro; return restituisce il risultato. Ecco una funzione che somma due numeri, e come si usa:
def somma(a: int, b: int) -> int:
"""Somma due numeri interi."""
return a + b
totale = somma(2, 3) # si "chiama" la funzione con le parentesi: ora totale vale 5Tre dettagli contano molto quando la funzione diventa uno strumento:
a: intdice che il parametroaè un numero intero. Si chiama annotazione di tipo:intè un intero,floatun numero con la virgola,struna Stringa: Un testo nel codice, scritto tra virgolette:"Ricercatore". glossario. CrewAI la usa per spiegare al modello che valori passare.-> intdice che cosa restituisce la funzione.- Il testo tra tre virgolette subito sotto
defsi chiama docstring ed è la descrizione della funzione. In uno strumento diventa la descrizione che il modello legge.
Il decoratore#
Un Decoratore: Una riga che inizia con @ sopra una funzione e le aggiunge un comportamento. In CrewAI: @agent, @task, @start, @listen. glossario è una riga che comincia con @, scritta subito sopra una funzione: prende la funzione e le aggiunge un comportamento, senza che tu debba riscriverla. CrewAI ne offre uno per gli strumenti, @tool. La funzione fa sempre lo stesso lavoro, ma diventa un oggetto che un agente può usare, con un nome e una descrizione.
Uno strumento con @tool: il calcolatore del budget#
Fare conti è un punto debole dei modelli linguistici: producono numeri plausibili, non numeri calcolati. Lo script seguente dà a un agente un calcolatore del budget per il weekend. Non servono chiavi: con Ollama gira gratis sul tuo computer.
# /// script
# requires-python = ">=3.10,<3.14"
# dependencies = ["crewai[tools]==1.15.21"]
# ///
"""Un agente calcola il budget di un weekend con uno strumento fatto a mano (nessuna chiave)."""
import os
from crewai import Agent, Crew, Process, Task
from crewai.tools import tool
# 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")
# Il decoratore @tool trasforma la funzione qui sotto in uno strumento per gli agenti.
# Il testo tra parentesi è il nome che l'agente vede.
@tool("Calcolatore budget weekend")
def calcola_budget(notti: int, prezzo_camera: float, persone: int, prezzo_pasto: float) -> str:
"""Calcola il costo di un weekend: alloggio, pasti, totale e quota a persona.
Usalo ogni volta che servono conti sul budget di un viaggio.
notti = numero di notti; prezzo_camera = euro a notte per l'intera camera;
persone = quante persone viaggiano; prezzo_pasto = euro a persona per un pasto.
Conta due pasti al giorno per ogni notte."""
alloggio = notti * prezzo_camera
pasti = notti * 2 * persone * prezzo_pasto
totale = alloggio + pasti
# Lo strumento restituisce sempre un testo: è quello che l'agente leggerà.
return (
f"Alloggio: {alloggio:.2f} euro. Pasti: {pasti:.2f} euro. "
f"Totale: {totale:.2f} euro. A persona: {totale / persone:.2f} euro."
)
consulente = Agent(
role="Consulente di budget per viaggi",
goal="Dire con precisione quanto costa un weekend a {citta}",
backstory=(
"Non fai mai i conti a mente: usi sempre il Calcolatore budget weekend "
"e riporti esattamente i numeri che ti restituisce."
),
tools=[calcola_budget], # la lista degli strumenti che questo agente può usare
llm=MODELLO,
max_iter=5,
verbose=True,
)
budget = Task(
description=(
"{persone} persone passano {notti} notti a {citta}. La camera costa {prezzo_camera} euro "
"a notte e un pasto costa in media {prezzo_pasto} euro a persona. "
"Calcola il budget usando lo strumento Calcolatore budget weekend."
),
expected_output=(
"Quattro righe in italiano: alloggio, pasti, totale e quota a persona, "
"con i numeri restituiti dallo strumento."
),
agent=consulente,
)
crew = Crew(agents=[consulente], tasks=[budget], process=Process.sequential, verbose=True)
if __name__ == "__main__":
risultato = crew.kickoff(
inputs={"citta": "Arezzo", "persone": "2", "notti": "2", "prezzo_camera": "95", "prezzo_pasto": "28"}
)
print("\n=== RISULTATO FINALE ===")
print(risultato.raw)Che cosa succede:
@tool("Calcolatore budget weekend")trasformacalcola_budgetin uno strumento con quel nome; la docstring diventa la descrizione e le annotazioni (notti: inte le altre) i parametri che il modello deve riempire.- Le righe con
f"...{totale:.2f}..."costruiscono la stringa di risposta: Python mette al posto delle graffe il valore della variabile, con due cifre dopo la virgola. - Nel
backstorye nelladescriptionchiedi esplicitamente di usare lo strumento: con i modelli piccoli questa insistenza aiuta.
Uno strumento si può provare da solo, senza agente, con il metodo run: è il modo più veloce per scoprire un errore nel tuo codice. Aggiungi questa riga in fondo allo script:
print(calcola_budget.run(notti=2, prezzo_camera=95, persone=2, prezzo_pasto=28))Alloggio: 190.00 euro. Pasti: 224.00 euro. Totale: 414.00 euro. A persona: 207.00 euro.Questo output è reale. I conti tornano: 2 notti a 95 euro fanno 190 euro di alloggio; 2 notti per 2 pasti per 2 persone a 28 euro fanno 224 euro di pasti.
Eseguirlo davvero con Ollama#
Abbiamo lanciato lo script con il modello locale qwen2.5:7b, cioè con MODEL=ollama/qwen2.5:7b nel file .env come nel capitolo 7. Ecco la parte centrale dell'output.


Come leggerlo:
- Il riquadro Tool Execution Started mostra i valori scelti dal modello:
{'prezzo_camera': 95, 'persone': 2, 'prezzo_pasto': 28, 'notti': 2}. Li ha ricavati dalla frase del task, e sono corretti. - Il riquadro Tool Execution Completed mostra il testo restituito dalla funzione. Compare prima di «Started» solo per l'ordine di stampa: la chiamata è una sola (
#1in entrambi). Il nomecalcolatore_budget_weekendè quello che hai scritto, messo da CrewAI in minuscolo e senza spazi. - La risposta finale riporta il totale giusto, 414 euro, ma su una riga sola invece delle «quattro righe» chieste nell'
expected_output: i modelli piccoli seguono il formato in modo approssimativo. Nel prossimo capitolo vedrai come controllarlo in automatico. - Nel titolo del task si legge «a Arezzo»: il Segnaposto {…}: Una parola tra graffe, come
{citta}, dentro i testi di agenti e task. Alkickoff(inputs={...})viene sostituita con il valore vero. glossario{citta}sostituisce la parola e basta, non corregge la preposizione.
Nella nostra prova qwen2.5:7b ha usato lo strumento correttamente al primo tentativo, ma non è garantito che succeda sempre: con i modelli piccoli può capitare che l'agente risponda senza chiamare lo strumento, o che passi valori sbagliati. Se nell'output non vedi nessun riquadro «Tool Execution», i numeri della risposta sono stati scritti dal modello, non calcolati.
Lo stesso strumento con BaseTool#
Il secondo modo di creare uno strumento è scrivere 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 che parte dallo stampo BaseTool di CrewAI e ne riempie i pezzi. Scrivi più righe, ma hai più controllo: descrivi ogni parametro separatamente e puoi aggiungere impostazioni tue. È anche la forma che trovi nei progetti creati con crewai create (capitolo 14).
from typing import Type
from crewai.tools import BaseTool
from pydantic import BaseModel, Field
class ParametriBudget(BaseModel):
"""I parametri che l'agente deve fornire."""
notti: int = Field(..., description="Numero di notti")
prezzo_camera: float = Field(..., description="Euro a notte per l'intera camera")
persone: int = Field(..., description="Quante persone viaggiano")
prezzo_pasto: float = Field(..., description="Euro a persona per un pasto")
class CalcolatoreBudget(BaseTool):
name: str = "Calcolatore budget weekend"
description: str = (
"Calcola alloggio, pasti, totale e quota a persona di un weekend. "
"Conta due pasti al giorno per ogni notte."
)
args_schema: Type[BaseModel] = ParametriBudget # collega i parametri allo strumento
def _run(self, notti: int, prezzo_camera: float, persone: int, prezzo_pasto: float) -> str:
alloggio = notti * prezzo_camera
pasti = notti * 2 * persone * prezzo_pasto
totale = alloggio + pasti
return f"Totale: {totale:.2f} euro. A persona: {totale / persone:.2f} euro."ParametriBudgetelenca i parametri, ognuno con tipo e descrizione.BaseModeleFieldvengono da una libreria che si chiama Pydantic: la conoscerai bene nel prossimo capitolo.nameedescriptionsono il nome e la descrizione che il modello legge._runcontiene il lavoro vero; i nomi dei suoi parametri devono essere gli stessi diParametriBudget.
Si usa come uno strumento pronto, con le parentesi perché dalla classe crei un oggetto: tools=[CalcolatoreBudget()]. Quale scegliere? @tool per strumenti semplici fatti da una funzione; BaseTool quando lo strumento ha bisogno di impostazioni (un percorso, un indirizzo) o di descrizioni dettagliate per ogni parametro.
MCP, in parole semplici#
Scrivere uno strumento per ogni servizio (il calendario, la posta, GitHub, un database) sarebbe faticoso. MCP: Model Context Protocol: standard aperto per collegare agenti a servizi esterni (calendari, database, GitHub…) tramite "server MCP" già pronti. glossario, Model Context Protocol, è uno standard aperto che funziona come una presa USB: un servizio mette a disposizione un «server MCP» con i suoi strumenti, e qualunque programma compatibile può collegarsi e usarli.
In CrewAI un agente riceve i server MCP nel parametro mcps, accanto a tools. Ecco l'esempio della documentazione, ridotto a un solo server (l'indirizzo è quello di Exa, un motore di ricerca, e richiede una chiave tua; i testi sono in inglese perché copiati dai docs):
research_agent = Agent(
role="Research Analyst",
goal="Find and analyze information using advanced search tools",
backstory="Expert researcher with access to multiple data sources",
mcps=[
# l'indirizzo di un server MCP remoto: i suoi strumenti si aggiungono a quelli dell'agente
"https://mcp.exa.ai/mcp?api_key=your_key&profile=your_profile",
],
)Per usare mcps la documentazione indica di aggiungere il pacchetto mcp (uv add mcp). E ripete, in grassetto, una regola da prendere sul serio: usa solo server MCP di cui ti fidi, perché i loro strumenti agiscono davvero sui servizi a cui li colleghi. Negli esempi del corso non useremo MCP; se vuoi approfondire, parti dalla panoramica ufficiale su MCP.
Prova tu: uno strumento che conta le parole
Scrivi con @tool uno strumento «Contatore di parole» che riceve un testo e restituisce quante parole contiene, poi provalo da solo con run. Una soluzione:
from crewai.tools import tool
@tool("Contatore di parole")
def conta_parole(testo: str) -> str:
"""Conta quante parole ci sono in un testo. Usalo per controllare la lunghezza di una bozza."""
return f"Il testo contiene {len(testo.split())} parole."
print(conta_parole.run(testo="Arezzo è una città toscana"))L'output è Il testo contiene 5 parole.: split() divide il testo negli spazi e len conta i pezzi. Per usarlo davvero, aggiungilo alla lista tools dello scrittore e chiedi nel task di controllare che la guida non superi 120 parole.
- Senza strumenti un agente può solo generare testo plausibile: su fatti e numeri rischia di inventare.
- Del catalogo degli strumenti il modello vede solo nome, descrizione e parametri: scrivi descrizioni chiare.
crewai_toolsoffre strumenti pronti comeSerperDevTool(chiaveSERPER_API_KEY),ScrapeWebsiteTool,FileReadTool,DirectoryReadTooleFileWriterTool;CodeInterpreterToolnon esiste più.- Gli strumenti si danno all'agente, per tutti i suoi task, o al task, solo per quello.
- Uno strumento tuo si crea con
@toolsu una funzione o con una classeBaseTool; provalo prima conrun. - MCP collega gli agenti a server di strumenti già pronti, con il parametro
mcps.
Nel prossimo capitolo impari a ottenere dagli agenti risultati con una forma precisa e a controllarli in automatico: risultati strutturati e guardrail.
Corso indipendente, non affiliato a CrewAI Inc. Contenuti verificati su CrewAI 1.15.21 il 15 settembre 2026.