0Pricing
AI Engineering Academy · Lezione

Proteggere l'accesso degli agenti agli strumenti

Applichi i principi del privilegio minimo alle autorizzazioni degli strumenti degli agenti, implementi passaggi di conferma prima delle azioni distruttive e verifichi i log delle azioni degli agenti per rilevare comportamenti anomali.

Proteggere l'accesso degli agenti agli strumenti è una lezione AI Engineering Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento AI Engineering Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso AI Engineering Academy include 4 lezioni in totale.

Il problema della sicurezza dell'accesso agli strumenti

Quando fornite uno strumento a un agente AI, gli date la possibilità di compiere azioni nel mondo reale. Uno strumento che invia email, esegue query SQL, chiama API di pagamento o modifica file può causare danni ingenti se l'agente viene compromesso da un attacco di prompt injection o commette semplicemente un errore. Proteggere l'accesso degli agenti agli strumenti significa progettare il livello degli strumenti in modo che i danni derivanti da ogni singolo utilizzo siano limitati, verificabili e reversibili quando possibile.

Il principio del privilegio minimo

Applicate il principio del privilegio minimo a ogni strumento: assegnate all'agente l'accesso minimo necessario per completare l'attività assegnata, e nulla di più. Se l'agente deve leggere i dati dei clienti, fornitegli una connessione di sola lettura al database, non la connessione completa da amministratore che usate per la manutenzione. Se invia notifiche, limitate la sua chiave API al solo endpoint delle notifiche. Il privilegio minimo limita l'entità dei danni di qualsiasi incidente di sicurezza.

from enum import Enum
from dataclasses import dataclass

class Permission(Enum):
    READ_CUSTOMER_PROFILE = 'read_customer_profile'
    SEND_NOTIFICATION = 'send_notification'
    READ_ORDER_HISTORY = 'read_order_history'
    WRITE_CUSTOMER_PROFILE = 'write_customer_profile'  # higher privilege
    PROCESS_REFUND = 'process_refund'                  # highest risk

@dataclass
class AgentIdentity:
    agent_id: str
    allowed_permissions: set[Permission]

# Support chat agent: read-only + send notification only
SUPPORT_AGENT = AgentIdentity(
    agent_id='support-agent-v1',
    allowed_permissions={
        Permission.READ_CUSTOMER_PROFILE,
        Permission.READ_ORDER_HISTORY,
        Permission.SEND_NOTIFICATION  # can notify, but NOT write or refund
    }
)

# NOT: give every agent all permissions for convenience

Esecuzione degli strumenti con controllo delle autorizzazioni

Applicate il privilegio minimo a livello di esecuzione, non solo a livello di progettazione. Ogni chiamata a uno strumento deve passare attraverso un controllo delle autorizzazioni che verifichi che l'agente chiamante disponga dell'autorizzazione richiesta per quella specifica azione. Questo controllo non può essere aggirato dall'agente né da un attacco di prompt injection, perché viene applicato nel codice e non nel prompt dell'LLM.

class ToolGateway:
    def __init__(self, agent: AgentIdentity):
        self.agent = agent
        self.audit_log = []

    def execute_tool(self, tool_name: str, required_permission: Permission, tool_fn, **kwargs) -> dict:
        # Permission check - enforced in code, not in the LLM prompt
        if required_permission not in self.agent.allowed_permissions:
            self.log_denied(tool_name, required_permission, kwargs)
            raise PermissionError(
                f'Agent {self.agent.agent_id} does not have permission: {required_permission.value}'
            )
        
        # Execute tool
        result = tool_fn(**kwargs)
        self.log_allowed(tool_name, kwargs, result)
        return result

    def log_denied(self, tool: str, permission: Permission, args: dict):
        entry = {'type': 'DENIED', 'agent': self.agent.agent_id, 'tool': tool, 'permission': permission.value, 'args': args}
        self.audit_log.append(entry)
        print(f'SECURITY: Permission denied - {entry}')

    def log_allowed(self, tool: str, args: dict, result):
        entry = {'type': 'ALLOWED', 'agent': self.agent.agent_id, 'tool': tool, 'args': args}
        self.audit_log.append(entry)

gateway = ToolGateway(SUPPORT_AGENT)

# This will succeed (agent has READ permission)
gateway.execute_tool('read_profile', Permission.READ_CUSTOMER_PROFILE, read_customer_profile, user_id='123')

# This will raise PermissionError (agent lacks PROCESS_REFUND permission)
gateway.execute_tool('process_refund', Permission.PROCESS_REFUND, process_refund, order_id='456', amount=50.00)

Passaggi di conferma per le azioni distruttive

Alcune azioni sono irreversibili o hanno un impatto elevato: eliminare record, inviare email in massa, elaborare transazioni finanziarie. Richiedete una conferma esplicita da parte di una persona prima che l'agente esegua una di queste azioni. L'agente propone l'azione, indicando cosa vuole fare e perché; una persona la approva o la rifiuta; solo a quel punto l'esecuzione può procedere. Questo controllo di conferma è la difesa singola più efficace contro gli errori degli agenti e gli abusi derivanti da injection.

HIGH_RISK_ACTIONS = {
    'delete_customer_record',
    'send_bulk_email',
    'process_refund_over_100',
    'deploy_code',
    'revoke_user_access'
}

def execute_with_confirmation(tool_name: str, tool_args: dict, agent_reasoning: str) -> dict:
    if tool_name in HIGH_RISK_ACTIONS:
        # Pause and request human approval
        approval_request = {
            'action': tool_name,
            'arguments': tool_args,
            'agent_reasoning': agent_reasoning,
            'risk_level': 'HIGH'
        }
        approval = request_human_approval(approval_request)  # blocks until human responds
        
        if not approval.approved:
            return {'status': 'rejected', 'reason': approval.rejection_reason}
        
        # Log the approval for audit trail
        log_approval(tool_name, tool_args, approved_by=approval.approver_id)
    
    # Execute only after confirmation
    return execute_tool(tool_name, **tool_args)

Limitare gli strumenti: tempo, utenti e dati

Oltre ai tipi di autorizzazione, limitate l'accesso agli strumenti lungo tre dimensioni. Limiti temporali: chiavi API o token che scadono al termine della sessione dell'agente. Limiti per utente: un agente che assiste l'utente A non deve mai accedere ai dati dell'utente B, anche se gli viene ordinato di farlo. Limiti sui dati: un agente del supporto clienti deve accedere solo ai dati del cliente che sta assistendo in quel momento, non a quelli di tutti i clienti. Implementate questi limiti nelle implementazioni degli strumenti, non nei prompt degli agenti.

class ScopedCustomerTool:
    def __init__(self, current_user_id: str, session_token: str):
        self.user_id = current_user_id  # agent can only access THIS user's data
        self.token = session_token       # expires at end of session

    def get_customer_profile(self) -> dict:
        # Hardcoded to current user - agent cannot change this via prompt
        return db.query(
            'SELECT * FROM customers WHERE id = %s',
            (self.user_id,)  # parameterized, always this user's ID only
        )

    def get_order_history(self, limit: int = 10) -> list:
        # Even if the agent says 'get orders for user 999', it gets self.user_id
        return db.query(
            'SELECT * FROM orders WHERE customer_id = %s ORDER BY date DESC LIMIT %s',
            (self.user_id, min(limit, 50))  # cap limit too
        )

# Inject scoped tool into agent - cannot be overridden by prompt
def create_support_agent(user_id: str, session_token: str):
    scoped_tools = ScopedCustomerTool(user_id, session_token)
    return AgentExecutor(llm=llm, tools=[scoped_tools.get_customer_profile, scoped_tools.get_order_history])

Convalida degli input degli argomenti degli strumenti

Gli agenti generano gli argomenti degli strumenti sotto forma di testo. Prima di eseguire qualsiasi strumento, convalidate tutti gli argomenti rispetto a uno schema rigoroso. Questo previene: l'SQL injection tramite i parametri degli strumenti, gli attacchi di path traversal (l'agente che passa '../../../etc/passwd' come percorso di un file), gli attacchi SSRF (l'agente che passa l'URL di un servizio interno come parametro 'remote URL') e l'overflow degli interi o i valori fuori intervallo che potrebbero causare comportamenti imprevisti.

from pydantic import BaseModel, validator, constr, confloat
import re

class SendEmailArgs(BaseModel):
    to: str
    subject: constr(max_length=200)
    body: constr(max_length=10000)

    @validator('to')
    def must_be_company_email(cls, v):
        if not re.match(r'^[^@]+@(?:yourcorp\.com|partner\.com)$', v):
            raise ValueError('Email must be sent to yourcorp.com or partner.com domains only')
        return v

class ReadFileArgs(BaseModel):
    filename: constr(pattern=r'^[a-zA-Z0-9_\-\.]+$')  # alphanumeric only, no path traversal

    @validator('filename')
    def no_parent_directory(cls, v):
        if '..' in v or '/' in v or '\\' in v:
            raise ValueError('Path traversal detected')
        return v

# Validate before execution
def validated_send_email(args_dict: dict) -> dict:
    args = SendEmailArgs(**args_dict)  # raises ValueError on invalid input
    return send_email(args.to, args.subject, args.body)

Logging di audit immutabile

Ogni chiamata a uno strumento effettuata da un agente deve essere registrata in un log di audit immutabile. La voce di log deve includere: l'ID dell'agente e l'ID della sessione, il nome dello strumento e tutti gli argomenti, il valore restituito, il timestamp e il ragionamento dichiarato dall'agente per effettuare la chiamata. Immutabile significa che l'agente, o un attaccante, non può eliminare o modificare le voci di log. Usate uno storage append-only, come i servizi di logging cloud, i database write-once o lo storage WORM.

import hashlib
import json
import time

class ImmutableAuditLog:
    def __init__(self, log_backend):
        self.backend = log_backend  # e.g., CloudWatch, BigQuery, or append-only file
        self.previous_hash = '0' * 64  # genesis hash

    def record(self, agent_id: str, tool_name: str, args: dict, result, reasoning: str):
        entry = {
            'agent_id': agent_id,
            'tool': tool_name,
            'args': args,
            'result_summary': str(result)[:500],  # truncate large results
            'reasoning': reasoning[:1000],
            'timestamp': time.time(),
            'previous_hash': self.previous_hash  # chain entries like a blockchain
        }
        
        entry_json = json.dumps(entry, sort_keys=True)
        entry['hash'] = hashlib.sha256(entry_json.encode()).hexdigest()
        
        self.backend.append(entry)  # append-only, never update
        self.previous_hash = entry['hash']
        
        return entry['hash']

Rilevamento dei comportamenti anomali degli agenti

Anche in presenza di controlli delle autorizzazioni e log di audit, monitorate i pattern di comportamento anomalo che indicano che un agente potrebbe essere stato compromesso o si comporta in modo imprevisto. Tra i segnali di anomalia figurano: un agente di supporto che improvvisamente chiama strumenti mai utilizzati prima, un aumento insolito nella frequenza delle chiamate agli strumenti da parte di un agente, argomenti che differiscono dalla norma in modi sospetti, come stringhe insolitamente lunghe o sequenze di caratteri insolite, oppure chiamate effettuate in orari inconsueti.

from collections import Counter

class AgentBehaviorMonitor:
    def __init__(self):
        self.tool_call_counts = Counter()  # tracks historical tool usage
        self.arg_length_history = {}       # tracks typical argument lengths

    def record_and_check(self, agent_id: str, tool_name: str, args: dict) -> list[str]:
        key = f'{agent_id}:{tool_name}'
        anomalies = []
        
        self.tool_call_counts[key] += 1
        
        # Flag tools never called before by this agent
        if self.tool_call_counts[key] == 1 and tool_name not in COMMON_TOOLS:
            anomalies.append(f'First time agent {agent_id} called unusual tool: {tool_name}')
        
        # Flag unusually long arguments (potential injection payload)
        total_arg_length = sum(len(str(v)) for v in args.values())
        if tool_name not in self.arg_length_history:
            self.arg_length_history[tool_name] = []
        self.arg_length_history[tool_name].append(total_arg_length)
        
        if len(self.arg_length_history[tool_name]) > 10:
            avg = sum(self.arg_length_history[tool_name]) / len(self.arg_length_history[tool_name])
            if total_arg_length > avg * 5:
                anomalies.append(f'Unusually long arguments for {tool_name}: {total_arg_length} chars (avg: {avg:.0f})')
        
        return anomalies

Scadenza dei token e limitazione delle sessioni

Le sessioni degli agenti devono avere una durata definita. Rilasciate all'agente token o credenziali di breve durata all'avvio della sessione e revocateli al termine della sessione. Se la sessione di un agente viene compromessa durante l'esecuzione, la capacità dell'attaccante di sfruttarla è limitata dalla scadenza del token. La limitazione delle sessioni garantisce inoltre che un singolo agente compromesso non possa essere utilizzato per attacchi successivi a distanza di giorni.

import secrets
import time

class SessionTokenManager:
    def __init__(self, ttl_seconds=3600):
        self.tokens = {}  # token -> (agent_id, user_id, expires_at)
        self.ttl = ttl_seconds

    def issue_token(self, agent_id: str, user_id: str) -> str:
        token = secrets.token_urlsafe(32)
        expires_at = time.time() + self.ttl
        self.tokens[token] = (agent_id, user_id, expires_at)
        return token

    def validate_token(self, token: str) -> dict | None:
        if token not in self.tokens:
            return None
        agent_id, user_id, expires_at = self.tokens[token]
        if time.time() > expires_at:
            del self.tokens[token]  # clean up expired token
            return None
        return {'agent_id': agent_id, 'user_id': user_id}

    def revoke_token(self, token: str):
        self.tokens.pop(token, None)

token_manager = SessionTokenManager(ttl_seconds=1800)  # 30-minute sessions

Test della sicurezza degli strumenti

Testate il livello di sicurezza degli strumenti simulando attacchi: provate a chiamare uno strumento limitato con un agente non autorizzato, fornite argomenti con path traversal, inserite stringhe di istruzioni nei parametri degli strumenti e tentate di chiamare strumenti con token scaduti. Una suite completa di test per la sicurezza degli strumenti deve coprire tutti i limiti delle autorizzazioni, tutte le regole di convalida e tutti i trigger di rilevamento delle anomalie.

Progettare la reversibilità

Quando possibile, progettate strumenti reversibili o con esecuzione a fasi. Invece di eliminare immediatamente un record, contrassegnatelo come eliminato con un tombstone, in modo da poterlo ripristinare. Invece di inviare subito un'email, inseritela in una coda 'pending send' che venga elaborata dopo una finestra di revisione di 5 minuti. Sottoponete le transazioni finanziarie a un blocco temporaneo prima del regolamento. La reversibilità non elimina il rischio per la sicurezza, ma riduce drasticamente l'impatto degli attacchi riusciti.

Verifica rapida

Verificate la vostra comprensione della protezione dell'accesso degli agenti agli strumenti trattata in questa lezione.

Riepilogo della lezione

In questa lezione avete imparato che il principio del privilegio minimo limita le autorizzazioni degli strumenti a ciò di cui ogni ruolo dell'agente ha effettivamente bisogno; i controlli delle autorizzazioni a livello di codice applicano queste autorizzazioni in modo da non poter essere aggirate tramite prompt injection; e i passaggi di conferma da parte di una persona per le azioni ad alto rischio forniscono un'ultima rete di sicurezza prima dell'esecuzione di operazioni irreversibili. Ora passeremo a un esercizio strutturato di red teaming sulle applicazioni LLM.

Domande Frequenti

La lezione «Proteggere l'accesso degli agenti agli strumenti» è gratuita?

Sì — il testo completo di «Proteggere l'accesso degli agenti agli strumenti» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso AI Engineering Academy, passa a CoddyKit PRO. Il corso AI Engineering Academy include 4 lezioni in totale.

Cosa imparerò in «Proteggere l'accesso degli agenti agli strumenti»?

Applichi i principi del privilegio minimo alle autorizzazioni degli strumenti degli agenti, implementi passaggi di conferma prima delle azioni distruttive e verifichi i log delle azioni degli agenti… Eserciti AI Engineering Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare AI Engineering Academy?

Non è richiesta alcuna esperienza precedente. AI Engineering Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.

Quanto tempo richiede la lezione «Proteggere l'accesso degli agenti agli strumenti»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione AI Engineering Academy?

Sì. Ogni lezione AI Engineering Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Tassonomia degli attacchi di prompt injection
  2. Difendersi dall'injection nei sistemi RAG
  3. Proteggere l'accesso degli agenti agli strumenti
  4. Eseguire un red team sulla propria applicazione LLM
← Torna a AI Engineering Academy