Un modello linguistico, da solo, sa solo generare testo. Non conosce la data di oggi, non puo' leggere il tuo database, non sa che tempo fa a Milano in questo momento e non puo' inviare una email. Il function calling (chiamato tool use da Anthropic) e' il meccanismo che colma questa distanza: permette al modello di chiedere al tuo programma di eseguire una funzione — per esempio "cerca il meteo di Milano" — ricevere il risultato e usarlo per comporre la risposta finale. E' il mattone fondamentale di ogni agente IA.
A chi serve e cosa imparerai
Questa guida e' per chi ha gia' fatto qualche chiamata alle API di un modello (OpenAI, Claude o Gemini) e vuole fare il salto successivo: collegare l'IA al mondo reale. Useremo Python e le API di OpenAI come esempio, ma il concetto e' identico negli altri SDK. Al termine saprai definire uno strumento, gestire il "ciclo" delle chiamate e costruire un mini-assistente capace di usare funzioni che scrivi tu.
Prerequisiti: Python 3.8+, la libreria openai installata (pip install openai) e una chiave API impostata nella variabile d'ambiente OPENAI_API_KEY.
Come funziona davvero: il malinteso da chiarire
Il punto piu' frainteso e' questo: il modello non esegue le funzioni. Non si collega a internet ne' lancia codice da solo. Quello che fa e' molto piu' sottile: tu gli descrivi quali strumenti ha a disposizione, e lui — quando lo ritiene utile — risponde non con del testo, ma con una richiesta strutturata del tipo "esegui la funzione meteo con parametro citta'=Milano". A quel punto sei tu, nel tuo codice, a eseguire davvero la funzione e a rimandargli il risultato. Il modello poi lo trasforma in una risposta in linguaggio naturale.
Il flusso completo ha quindi quattro fasi: 1) invii la domanda e la lista degli strumenti; 2) il modello chiede di chiamare uno strumento; 3) tu esegui e restituisci il risultato; 4) il modello produce la risposta finale.
Passo 1: scrivere la funzione e descriverla
Partiamo da una funzione Python vera, qui semplificata. In un caso reale chiamerebbe un'API meteo; per l'esempio restituisce un valore fisso:
def get_meteo(citta):
# In produzione qui chiameresti una vera API meteo
dati = {"Milano": "22 gradi, sereno", "Roma": "27 gradi, poco nuvoloso"}
return dati.get(citta, "dati non disponibili")
Ora va descritta al modello con uno schema, in modo che sappia quando e come usarla. Si usa il formato JSON Schema:
tools = [{
"type": "function",
"function": {
"name": "get_meteo",
"description": "Restituisce il meteo attuale di una citta' italiana",
"parameters": {
"type": "object",
"properties": {
"citta": {"type": "string", "description": "Il nome della citta', es. Milano"}
},
"required": ["citta"]
}
}
}]
La descrizione e' cruciale: e' l'unico modo che il modello ha per capire a cosa serve lo strumento e quando invocarlo. Scrivila con cura, come se spiegassi la funzione a un collega.
Passo 2: il ciclo completo delle chiamate
Ecco l'esempio integrale che mette insieme le quattro fasi. Da leggere con attenzione, perche' e' lo schema che ritroverai in ogni agente:
import json
from openai import OpenAI
client = OpenAI()
messaggi = [{"role": "user", "content": "Che tempo fa a Milano?"}]
# Fase 1 e 2: il modello decide se chiamare lo strumento
r = client.chat.completions.create(
model="gpt-4o",
messages=messaggi,
tools=tools,
)
msg = r.choices[0].message
messaggi.append(msg)
# Fase 3: eseguiamo le funzioni richieste e restituiamo i risultati
if msg.tool_calls:
for chiamata in msg.tool_calls:
args = json.loads(chiamata.function.arguments)
risultato = get_meteo(args["citta"])
messaggi.append({
"role": "tool",
"tool_call_id": chiamata.id,
"content": risultato,
})
# Fase 4: il modello compone la risposta finale usando il risultato
r2 = client.chat.completions.create(model="gpt-4o", messages=messaggi)
print(r2.choices[0].message.content)
else:
print(msg.content)
Risultato atteso: una frase naturale come "A Milano ci sono 22 gradi ed e' sereno". Nota che abbiamo richiamato il modello due volte: la prima per ottenere la richiesta di chiamata, la seconda per la risposta finale. Questo "andata e ritorno" e' il cuore del function calling.
Passo 3: piu' strumenti e chiamate in parallelo
Nulla ti vieta di passare piu' strumenti contemporaneamente (meteo, calcolatrice, ricerca su database): il modello sceglie quali usare. I modelli recenti possono anche richiedere piu' chiamate in parallelo in un solo turno — per questo nel codice cicliamo su msg.tool_calls invece di gestirne una sola. La regola d'oro: per ogni chiamata richiesta devi restituire un messaggio con ruolo tool e lo stesso tool_call_id, altrimenti la conversazione va in errore.
Lo stesso concetto con Claude e Gemini
Il meccanismo e' universale. Con le API di Anthropic si passa il parametro tools e il modello risponde con blocchi di tipo tool_use, a cui rispondi con blocchi tool_result. Con Gemini di Google la logica e' analoga, con le function declarations. Cambiano i nomi dei campi, non l'idea: descrivi lo strumento, il modello lo richiede, tu lo esegui, lui usa il risultato.
Errori comuni e come evitarli
- Il modello non chiama mai lo strumento: la descrizione e' troppo vaga. Rendila esplicita e indica con esempi quando usarlo.
- "messages with role 'tool' must respond to a tool_call": hai dimenticato di restituire un risultato per ogni
tool_call_id, oppure non hai accodato il messaggio dell'assistente prima dei risultati. - Argomenti malformati: il modello potrebbe produrre JSON non valido. Proteggi sempre
json.loadscon un blocco try/except e, in caso di errore, restituisci un messaggio che spieghi il problema cosi' il modello puo' riprovare. - Loop infiniti: in un agente che concatena strumenti, imposta un numero massimo di iterazioni per sicurezza.
Quando usarlo (e quando no)
Il function calling e' indispensabile quando il modello ha bisogno di dati aggiornati o azioni reali: meteo, prezzi, ricerche nel tuo database, invio di messaggi, interrogazione di un gestionale. Non serve, invece, quando il compito e' puramente di testo (riassumere, tradurre, riscrivere): in quei casi aggiungere strumenti complica inutilmente il codice. Padroneggiato questo schema, hai in mano l'ingrediente principale degli agenti: da qui puoi costruire assistenti che prenotano, calcolano, cercano e agiscono per conto tuo, sempre tenendo il controllo su cosa possono e non possono fare.




