Capire di quali strumenti l’agente ha davvero bisogno

Un tool (strumento) è una capacità che l’agente può invocare durante il proprio loop: leggere file, scriverli, eseguire comandi di shell, recuperare pagine web, oppure una funzione esposta da un server MCP che hai collegato. Il primo passo del dominio Implement tool use and environment interaction non è tecnico ma analitico: parti dal compito e ricava l’elenco minimo. Un agente che deve solo commentare la qualità del codice ha bisogno di lettura e ricerca, non di scrittura; un agente che apre issue ha bisogno del tool MCP corrispondente, non di tutta la superficie del server.

Nella Copilot CLI i tool nativi hanno nomi come shell, read, write, web_fetch, web_search, e nelle configurazioni dei custom agent esistono anche alias non sensibili alle maiuscole come execute, read, edit, search, agent, web, todo. Ridurre l’elenco non serve soltanto alla sicurezza: la documentazione motiva il tool search proprio col fatto che qualche decina di definizioni di tool consuma una quota rilevante di contesto prima che l’agente abbia fatto qualcosa, e che con troppi tool visibili contemporaneamente il modello sbaglia più spesso la scelta. Il tool search si attiva da sé sui modelli supportati quando i tool collegati sono abbastanza numerosi, carica i tool solo quando servono e poi li mantiene per il resto della conversazione. Lo disattivi con toolSearch: false nelle impostazioni personali, lo governi per singolo server MCP con deferTools impostato su auto o never, e per un custom agent in Markdown con deferred-tool-loading: true nel frontmatter.

Dichiarare gli strumenti: ogni superficie ha il suo posto

Qui l’errore da non fare è spostare un meccanismo da una superficie all’altra.

Nella Copilot CLI i server MCP a livello utente vivono in mcp-config.json nella directory di configurazione, sotto la chiave mcpServers, e ogni server ha un campo tools che accetta "*" oppure l’elenco dei soli tool ammessi. I custom agent locali sono file con estensione .agent.md in .github/agents/ per il progetto o nella cartella agents/ della configurazione utente; per default un agent accede a tutti i tool, e quando lo restringi viene aggiunta una specifica tools nel file.

Sul cloud agent — quello che gira su GitHub e produce pull request in bozza — il custom agent è un Markdown con frontmatter YAML in .github/agents/, oppure in agents/ dei repository .github e .github-private per organizzazione ed enterprise. Lì i permessi sugli strumenti si dichiarano nella configurazione dell’agent: la chiave tools limita i tool disponibili e la proprietà mcp-servers, valida solo per il cloud agent e non per gli IDE, aggiunge server e tool ulteriori. Due dettagli che l’esame può toccare: per default un agent accede a tutti i tool disponibili, inclusi quelli dei server MCP, e il cloud agent per default non ha accesso ai tool MCP di scrittura. La raccomandazione ufficiale è aggiornare il campo tools della configurazione MCP con il solo strumento necessario.

Il Copilot SDK non ha né flag di avvio né file di permessi: il controllo è programmatico, tramite l’hook onPreToolUse, che può restituire permissionDecision con valore allow, deny o ask, accompagnato da permissionDecisionReason, e può anche riscrivere gli argomenti con modifiedArgs. Nei GitHub Agentic Workflows, invece, il Markdown compilato con gh aw compile dichiara nel frontmatter tools per i toolset, permissions per gli scope del repository e safe-outputs per confinare le scritture ad azioni convalidate.

Permessi nella CLI: cosa dura, cosa no, e chi vince

Nella Copilot CLI --allow-tool e --deny-tool accettano un elenco separato da virgole di tipi di tool, con la possibilità di indicare il tool esatto e un pattern di sottocomando: shell, shell(git commit), shell(git:*), write(.github/copilot-instructions.md), MyMCP(create_issue). Valgono solo per la sessione corrente e non vengono scritti in permissions-config.json. Un’approvazione data interattivamente sì: viene registrata in quel file, organizzata per posizione del progetto, così nella stessa cartella o repository non ti viene richiesta di nuovo. Le approvazioni di dominio per gli URL stanno altrove, in settings.json nella lista allowedUrls.

Attenzione a non confondere due livelli diversi. --available-tools e --excluded-tools non concedono nulla: agiscono su quali tool il modello conosce, cioè disabilitano tutto tranne l’elenco indicato, e se usi entrambe le opzioni prevale l’allowlist di --available-tools. --allow-all-tools concede l’intera superficie disponibile, mentre --allow-all, alias --yolo, equivale a sommare i permessi su tool, path e URL.

La regola che l’esame verifica è la precedenza: le deny rule vincono sempre sulle allow rule, anche con --allow-all attivo e anche quando esiste già un’approvazione salvata.

copilot --allow-all-tools --deny-tool 'shell(git push)'

Per tornare indietro usa lo slash command /reset-allowed-tools: revoca i permessi concessi durante la sessione interattiva corrente e ripulisce anche le approvazioni salvate per la posizione corrente, riportandoti al default o allo stato definito dalle opzioni di avvio. Ricorda infine che il sandboxing locale è un asse separato: applica una filesystem policy in cui i path sono negati per default e si ispezionano con /sandbox policy e /sandbox status. Un tool concesso resta comunque soggetto a quella policy, e nel dubbio la domanda giusta è sempre quale delle due superfici ti sta bloccando.