Inicio ← Artículos Monografía Servicios
IT EN ES
ai:5llm:5tool:5chatbot:5llm_internal:5hacker:5

Esempio di attivazione tool da LLM

📅 2026-09-22 ⏱ 3 min lectura logistar.it
Giusta osservazione — e infatti è proprio la differenza concettuale di cui parlavamo prima. Il programma che ti ho dato è **deterministico**: fa sempre la stessa cosa, in un ordine fisso, senza "decidere" nulla. Quello che vuoi tu è un'**architettura agentica**: dai all'LLM degli strumenti (tool) e sarà *lui* a decidere quando e come usarli, magari anche a comporre il testo, gestire eccezioni con criterio, decidere se saltare un indirizzo sospetto, ecc. Ecco un esempio essenziale con l'API di Claude, che mostra esattamente il meccanismo di cui parlavamo (function calling): ```python import psycopg2 import smtplib from email.mime.text import MIMEText import anthropic import json DB_CONFIG = {"host": "localhost", "dbname": "nome_database", "user": "utente_db", "password": "password_db"} SMTP_HOST, SMTP_PORT = "smtp.tuoserver.it", 587 SMTP_USER, SMTP_PASSWORD = "tuo_account@tuodominio.it", "password_smtp" client = anthropic.Anthropic() # legge ANTHROPIC_API_KEY dall'ambiente # --- Le funzioni REALI che il tool può eseguire --- def leggi_email_clienti(): conn = psycopg2.connect(**DB_CONFIG) cur = conn.cursor() cur.execute("SELECT email FROM anagrafica_clienti WHERE email IS NOT NULL") righe = [r[0] for r in cur.fetchall()] cur.close(); conn.close() return righe def invia_email(destinatario, testo): msg = MIMEText(testo) msg["Subject"] = "Messaggio" msg["From"] = SMTP_USER msg["To"] = destinatario with smtplib.SMTP(SMTP_HOST, SMTP_PORT) as server: server.starttls() server.login(SMTP_USER, SMTP_PASSWORD) server.sendmail(SMTP_USER, destinatario, msg.as_string()) return f"Inviata a {destinatario}" # --- Dichiarazione dei tool per il modello --- tools = [ { "name": "leggi_email_clienti", "description": "Legge tutti gli indirizzi email dei clienti dall'anagrafica", "input_schema": {"type": "object", "properties": {}} }, { "name": "invia_email", "description": "Invia una email a un destinatario", "input_schema": { "type": "object", "properties": { "destinatario": {"type": "string"}, "testo": {"type": "string"} }, "required": ["destinatario", "testo"] } } ] FUNZIONI = {"leggi_email_clienti": leggi_email_clienti, "invia_email": invia_email} # --- Il "loop agentico": il modello ragiona e chiama i tool finché non ha finito --- messages = [{ "role": "user", "content": "Leggi l'anagrafica clienti e invia a ognuno il messaggio: 'ciao, sono la AI di bepi sotutto'" }] while True: response = client.messages.create( model="claude-sonnet-4-6", max_tokens=1000, tools=tools, messages=messages ) messages.append({"role": "assistant", "content": response.content}) if response.stop_reason != "tool_use": break # il modello ha finito, niente altro da eseguire tool_results = [] for block in response.content: if block.type == "tool_use": risultato = FUNZIONI[block.name](**block.input) tool_results.append({ "type": "tool_result", "tool_use_id": block.id, "content": json.dumps(risultato) }) messages.append({"role": "user", "content": tool_results}) print("Fatto.") ``` ## Cosa succede davvero, passo per passo 1. Do al modello due strumenti: uno per leggere l'anagrafica, uno per inviare email. 2. Il modello **da solo** decide di chiamare prima `leggi_email_clienti`. 3. Riceve la lista, e **da solo** decide di chiamare `invia_email` una volta per ogni indirizzo, con il testo che gli è stato chiesto. 4. Il ciclo continua finché il modello non decide che il compito è concluso. Nessuna riga di codice dice esplicitamente "per ogni email nella lista, invia" — è il modello che lo inferisce dall'istruzione in linguaggio naturale e orchestra le chiamate. ## Perché questo è esattamente il rischio LLM06 (Excessive Agency) Questo esempio, seppur innocuo nel contenuto, è **strutturalmente identico** all'attacco che abbiamo descritto prima: se in un contesto reale un contenuto esterno non fidato finisse tra i dati letti dal modello (es. un campo "note" nell'anagrafica contenente istruzioni nascoste), il modello potrebbe interpretarle e agire di conseguenza, dato che ha già i permessi per farlo. È per questo che in produzione si raccomanda: - validare/loggare ogni chiamata ai tool prima dell'esecuzione, - eventualmente richiedere conferma umana su azioni di massa come un invio a tutta l'anagrafica, - limitare il tool di invio con controlli propri (rate limit, whitelist di domini, ecc.) indipendenti dal "buon senso" del modello.