Le Claude Agent SDK fournit des contrôles de permission puissants qui vous permettent de gérer comment Claude utilise les outils dans votre application.
Ce guide couvre comment implémenter des systèmes de permission en utilisant le callback canUseTool, les hooks et les règles de permission settings.json. Pour la documentation complète de l'API, consultez la référence du SDK TypeScript.
Le Claude Agent SDK fournit quatre façons complémentaires de contrôler l'utilisation des outils :
Cas d'utilisation pour chaque approche :
canUseTool - Approbation dynamique pour les cas non couverts, demande à l'utilisateur la permissionOrdre de traitement : PreToolUse Hook → Deny Rules → Allow Rules → Ask Rules → Permission Mode Check → canUseTool Callback → PostToolUse Hook
Les modes de permission fournissent un contrôle global sur la façon dont Claude utilise les outils. Vous pouvez définir le mode de permission lors de l'appel de query() ou le modifier dynamiquement pendant les sessions de streaming.
Le SDK supporte quatre modes de permission, chacun avec un comportement différent :
| Mode | Description | Comportement des outils |
|---|---|---|
default | Comportement de permission standard | Les vérifications de permission normales s'appliquent |
plan | Mode planification - pas d'exécution | Claude ne peut utiliser que les outils en lecture seule ; présente un plan avant l'exécution (Non actuellement supporté dans le SDK) |
acceptEdits | Auto-acceptation des modifications de fichiers | Les modifications de fichiers et les opérations du système de fichiers sont automatiquement approuvées |
bypassPermissions | Contourner toutes les vérifications de permission | Tous les outils s'exécutent sans invites de permission (à utiliser avec prudence) |
Vous pouvez définir le mode de permission de deux façons :
Définissez le mode lors de la création d'une requête :
import { query } from "@anthropic-ai/claude-agent-sdk";
const result = await query({
prompt: "Help me refactor this code",
options: {
permissionMode: 'default' // Standard permission mode
}
});Modifiez le mode pendant une session de streaming :
acceptEdits)En mode accept edits :
Opérations auto-approuvées :
bypassPermissions)En mode bypass permissions :
Les modes de permission sont évalués à un point spécifique dans le flux de permission :
bypassPermissions - S'il est actif, autorise tous les outils restantscanUseToolcanUseTool - Gère les cas restantsCela signifie :
bypassPermissionsbypassPermissions remplace le callback canUseTool pour les outils non appariésExemple de progression du mode :
// Start in default mode for controlled execution
permissionMode: 'default'
// Switch to acceptEdits for rapid iteration
await q.setPermissionMode('acceptEdits')Le callback canUseTool est passé en tant qu'option lors de l'appel de la fonction query. Il reçoit le nom de l'outil et les paramètres d'entrée, et doit retourner une décision - soit autoriser soit refuser.
canUseTool se déclenche chaque fois que Claude Code afficherait une invite de permission à un utilisateur, par exemple les hooks et les règles de permission ne la couvrent pas et elle n'est pas en mode acceptEdits.
Voici un exemple complet montrant comment implémenter l'approbation interactive des outils :
L'outil AskUserQuestion permet à Claude de poser des questions de clarification à l'utilisateur pendant une conversation. Quand cet outil est appelé, votre callback canUseTool reçoit les questions et doit retourner les réponses de l'utilisateur.
Quand canUseTool est appelé avec toolName: "AskUserQuestion", l'entrée contient :
{
questions: [
{
question: "Which database should we use?",
header: "Database",
options: [
{ label: "PostgreSQL", description: "Relational, ACID compliant" },
{ label: "MongoDB", description: "Document-based, flexible schema" }
],
multiSelect: false
},
{
question: "Which features should we enable?",
header: "Features",
options: [
{ label: "Authentication", description: "User login and sessions" },
{ label: "Logging", description: "Request and error logging" },
{ label: "Caching", description: "Redis-based response caching" }
],
multiSelect: true
}
]
}Retournez les réponses dans updatedInput.answers en tant qu'enregistrement mappant le texte de la question aux étiquettes d'option sélectionnées :
return {
behavior: "allow",
updatedInput: {
questions: input.questions, // Pass through original questions
answers: {
"Which database should we use?": "PostgreSQL",
"Which features should we enable?": "Authentication, Caching"
}
}
}Les réponses multi-sélection sont des chaînes séparées par des virgules (par exemple, "Authentication, Caching").
import { query } from "@anthropic-ai/claude-agent-sdk";
// Create an async generator for streaming input
async function* streamInput() {
yield {
type: 'user',
message: {
role: 'user',
content: "Let's start with default permissions"
}
};
// Later in the conversation...
yield {
type: 'user',
message: {
role: 'user',
content: "Now let's speed up development"
}
};
}
const q = query({
prompt: streamInput(),
options: {
permissionMode: 'default' // Start in default mode
}
});
// Change mode dynamically
await q.setPermissionMode('acceptEdits');
// Process messages
for await (const message of q) {
console.log(message);
}import { query } from "@anthropic-ai/claude-agent-sdk";
async function promptForToolApproval(toolName: string, input: any) {
console.log("\n🔧 Tool Request:");
console.log(` Tool: ${toolName}`);
// Display tool parameters
if (input && Object.keys(input).length > 0) {
console.log(" Parameters:");
for (const [key, value] of Object.entries(input)) {
let displayValue = value;
if (typeof value === 'string' && value.length > 100) {
displayValue = value.substring(0, 100) + "...";
} else if (typeof value === 'object') {
displayValue = JSON.stringify(value, null, 2);
}
console.log(` ${key}: ${displayValue}`);
}
}
// Get user approval (replace with your UI logic)
const approved = await getUserApproval();
if (approved) {
console.log(" ✅ Approved\n");
return {
behavior: "allow",
updatedInput: input
};
} else {
console.log(" ❌ Denied\n");
return {
behavior: "deny",
message: "User denied permission for this tool"
};
}
}
// Use the permission callback
const result = await query({
prompt: "Help me analyze this codebase",
options: {
canUseTool: async (toolName, input) => {
return promptForToolApproval(toolName, input);
}
}
});