Mettre un agent Claude en production sans contrôle, c’est comme donner les clefs de votre serveur à un stagiaire enthousiaste : ça finit mal. Le Claude Agent SDK intègre deux mécanismes essentiels pour reprendre la main : les permissions (qui contrôlent quels outils l’agent peut utiliser et quand demander confirmation) et les hooks (qui permettent d’intercepter chaque étape pour valider, logger, modifier ou bloquer). Voici le tutoriel complet pour les configurer correctement avant la mise en production.
Ce tutoriel s’inscrit dans notre série Claude Agent SDK. Pour les bases conceptuelles, voir notre guide complet Claude Agent SDK 2026.
Permissions : les 4 modes
- default — l’agent demande confirmation à l’utilisateur pour chaque action sensible (Write, Edit, Bash). Sécurisé mais interactif.
- acceptEdits — l’agent peut écrire/modifier des fichiers sans demander, mais demande pour Bash et autres actions externes. Pratique pour des sessions de coding intensives.
- bypassPermissions — toutes les permissions sont contournées. À utiliser uniquement dans un environnement isolé (CI sandbox, conteneur jetable).
- plan — mode planification. L’agent ne fait rien, il propose un plan que l’utilisateur valide. Excellent pour les tâches complexes.
import { query } from "@anthropic-ai/claude-agent-sdk";
const result = query({
prompt: "Refactor le module auth.ts",
options: {
permissionMode: "default", // ou "acceptEdits", "plan", "bypassPermissions"
},
});
Restreindre les outils accessibles
const result = query({
prompt: "...",
options: {
allowedTools: ["Read", "Grep", "Glob"], // whitelist
disallowedTools: ["Bash", "WebFetch"], // blacklist additionnelle
},
});
Pour un agent en lecture seule (audit, analyse), n’autorisez que Read/Grep/Glob. Pour un agent qui modifie le code, ajoutez Edit/Write. Pour un agent qui peut exécuter, ajoutez Bash mais avec des règles fines (voir hooks plus bas).
Permissions par regex sur Bash
L’outil Bash est le plus dangereux. Pour le contrôler finement, utilisez les permissions avancées :
// Configuration via .claude/settings.json
{
"permissions": {
"allow": [
"Bash(git status)",
"Bash(git diff*)",
"Bash(git log*)",
"Bash(npm test*)",
"Bash(bun test*)",
"Bash(ls*)",
"Bash(cat *.log)"
],
"deny": [
"Bash(rm -rf*)",
"Bash(* --no-verify*)",
"Bash(curl * | bash*)",
"Read(.env*)",
"Read(**/*.pem)",
"Read(**/secrets/**)"
]
}
}
Les patterns supportent les wildcards. Toute commande non listée tombe dans le mode par défaut (demande confirmation). C’est un mécanisme puissant pour automatiser ce qui est sûr et bloquer ce qui ne l’est pas.
Hooks : intercepter chaque étape
Les hooks sont des fonctions que vous attachez à des événements de la boucle agentique. Le SDK supporte :
- PreToolUse : avant chaque exécution d’outil. Peut valider, logger, ou refuser.
- PostToolUse : après chaque exécution. Peut logger le résultat, modifier la sortie, alerter.
- UserPromptSubmit : avant que le prompt utilisateur soit envoyé à Claude. Peut enrichir le contexte.
- Stop : à la fin de chaque réponse de Claude. Peut déclencher un suivi.
- SubagentStop : à la fin d’un sub-agent.
- SessionStart / SessionEnd : début et fin de session.
Hook PreToolUse : valider et logger
// hooks/audit.ts
import type { PreToolUseHook } from "@anthropic-ai/claude-agent-sdk";
import { writeFileSync } from "fs";
export const auditPreToolUse: PreToolUseHook = async (input) => {
// Logger l'appel
const log = {
timestamp: new Date().toISOString(),
tool: input.toolName,
params: input.toolInput,
user: process.env.AGENT_USER ?? "anonymous",
};
writeFileSync("./agent-audit.log", JSON.stringify(log) + "\n", { flag: "a" });
// Bloquer certaines commandes Bash dangereuses
if (input.toolName === "Bash") {
const cmd = input.toolInput.command as string;
const dangerous = [/rm -rf/, /dd if=/, /mkfs/, /:.*\(\)/];
if (dangerous.some((re) => re.test(cmd))) {
return {
decision: "deny",
reason: "Commande potentiellement dangereuse bloquée par hook audit",
};
}
}
// Bloquer la lecture de secrets
if (input.toolName === "Read") {
const path = input.toolInput.file_path as string;
if (/\.(env|pem|key)$/.test(path)) {
return { decision: "deny", reason: "Lecture de secret bloquée" };
}
}
return { decision: "allow" };
};
Le hook reçoit chaque tool call avant exécution et peut décider allow, deny, ou modifier les paramètres. C’est votre dernière ligne de défense contre les actions non voulues.
Hook PostToolUse : alerte si action sensible
export const auditPostToolUse: PostToolUseHook = async (input) => {
// Notifier sur Slack si l'agent a écrit dans un fichier de prod
if (input.toolName === "Write" || input.toolName === "Edit") {
const path = input.toolInput.file_path as string;
if (path.includes("/prod/") || path.includes("/production/")) {
await fetch(SLACK_WEBHOOK, {
method: "POST",
body: JSON.stringify({
text: `Agent a modifié : ${path}`,
}),
});
}
}
};
Hook UserPromptSubmit : enrichir le contexte
export const enrichContext: UserPromptSubmitHook = async (input) => {
// Ajouter du contexte projet à chaque prompt utilisateur
const projectContext = `
Contexte projet (auto-injecté) :
- Stack : Bun + Hono + Drizzle + Postgres
- Conventions : TypeScript strict, tests bun:test, lint biome
- Branche actuelle : ${getCurrentBranch()}
`;
return {
additionalSystemContext: projectContext,
};
};
Cette astuce économise du retravail : l’agent connaît toujours votre stack, ce qui réduit le besoin de répéter les conventions à chaque message.
Configurer les hooks via settings.json
// .claude/settings.json
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash|Write|Edit",
"hooks": [
{ "type": "command", "command": "bun run hooks/audit-pre.ts" }
]
}
],
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{ "type": "command", "command": "bun run hooks/notify-slack.ts" }
]
}
],
"Stop": [
{
"hooks": [
{ "type": "command", "command": "bun run hooks/log-conversation.ts" }
]
}
]
}
}
Les hooks shell reçoivent les paramètres en JSON sur stdin et écrivent leur décision en JSON sur stdout. C’est le mode portable, utilisable même sans SDK programmatique (ex : Claude Code en CLI).
Cas d’usage typiques
- Audit log immuable : chaque action de l’agent dans une base append-only (idéal pour la conformité)
- Garde-fou financier : compteur de tokens consommés, alerte si dépassement budget
- Hard block sur secrets : empêcher la lecture de .env, ou la copie de secrets dans le prompt
- Auto-format après Edit : déclencher prettier/biome après chaque modification
- Validation pré-PR : avant Stop, lancer tests + linter et bloquer si échec
- Notification équipe : Slack/Discord à chaque action critique
Sécurité critique : injection de prompt
Si votre agent ingère des données externes (emails, web pages, fichiers utilisateurs), un attaquant peut tenter une injection de prompt : cacher des instructions dans le contenu pour manipuler l’agent. Mécanismes de défense :
- Hook PreToolUse qui détecte les patterns d’injection courants (« ignore previous instructions », « you are now… »)
- Whitelist stricte des outils : un agent qui lit des emails ne devrait jamais pouvoir Write ou Bash
- Pas d’élévation de permission automatique sur la base du contenu lu
- Validation utilisateur systématique pour les actions externes (envoi mail, paiement, etc.)
Adaptation Afrique de l’Ouest
Pour les PME ouest-africaines qui automatisent des workflows sensibles (facturation, paiement Wave/OM, gestion clientèle), les hooks et permissions sont la condition non-négociable de la mise en production. Particulièrement crucial : tout ce qui touche à un montant financier doit déclencher une notification WhatsApp ou email à un valideur humain via PostToolUse hook avant exécution réelle.
Bonnes pratiques production
- Whitelist plutôt que blacklist : commencez par tout interdire, autorisez progressivement
- Audit log dans une base distincte : Postgres séparé, ou append-only files comme S3 avec Object Lock
- Test des hooks en isolation avant de les coller en prod
- Latence des hooks : un hook lent ralentit toute la session. Optez pour de l’asynchrone (queue) si possible
- Échec de hook = échec d’agent : si un hook crash, le SDK considère que l’action est refusée. Loggez les exceptions
Erreurs fréquentes
| Erreur | Cause | Solution |
|---|---|---|
| Hook PreToolUse jamais appelé | Matcher mal écrit | Vérifier le nom exact de l’outil (case sensitive) |
| Agent bloque sur tout | Whitelist trop stricte | Ajouter les outils essentiels (Read, Grep, Glob au minimum) |
| Logs explosent en taille | Pas de rotation | Logrotate sur le fichier audit, ou base Postgres avec partition |
| Hook ralentit massivement | Appel HTTP sync dans le hook | Faire le call en arrière-plan, retourner allow immédiatement |
| Settings.json non chargé | Mauvais chemin (workspace vs user) | Vérifier .claude/settings.json à la racine du projet |