Tool permissions pour agents IA (least privilege) + Code

Dès que tu donnes des credentials à un système probabiliste, il te faut du least privilege. Un modèle de permissions outils enforceable et auditable.
Sur cette page
  1. Le problème (côté prod)
  2. Pourquoi ça casse en prod
  3. 1) “On donne l’accès, on contraindra après” finit en incident
  4. 2) Les tools sont des capacités, pas des fonctions
  5. 3) Default-allow → fuites et cross-tenant tôt ou tard
  6. Exemple d’implémentation (code réel)
  7. Incident réel (avec chiffres)
  8. Compromis
  9. Quand NE PAS l’utiliser
  10. Checklist (copier-coller)
  11. Config par défaut sûre (JSON/YAML)
  12. FAQ (3–5)
  13. Pages liées (3–6 liens)
Flux interactif
Scénario:
Étape 1/3: Execution

Action is proposed as structured data (tool + args).

Le problème (côté prod)

Un agent, c’est “juste du texte”. Jusqu’au moment où tu lui donnes des tools.

Dès qu’il peut appeler des tools, tu as construit un système de permissions. Que tu le veuilles ou non.

Et la vérité qui pique : les prompts ne sont pas des permissions. “Please don’t do X” n’est pas un control layer.

Pourquoi ça casse en prod

1) “On donne l’accès, on contraindra après” finit en incident

Si tu dis “on ajoutera des guardrails après avoir prouvé la valeur” : tu décris la scène d’ouverture du postmortem.

2) Les tools sont des capacités, pas des fonctions

db.write n’est pas “une fonction”. C’est une capacité : elle change l’état. Les side effects sont irréversibles ou coûteux.

Conçois les permissions comme un graphe de capacités :

  • read vs write
  • ressources scoppées (tenant/projet/utilisateur)
  • limites (rate/cost/steps)

3) Default-allow → fuites et cross-tenant tôt ou tard

Default-allow + un tool call faux et tu as :

  • PII dans les logs
  • writes dans le mauvais env
  • accès cross-tenant

Exemple d’implémentation (code réel)

Un modèle minimal :

  • allowlist capability-based
  • checks de scope (tenant_id)
  • write tools optionnels derrière approval
PYTHON
from dataclasses import dataclass


@dataclass(frozen=True)
class ToolPermission:
  name: str
  scopes: set[str]  # e.g. {"tenant:acme"}
  mode: str = "allow"  # allow | approve


class PolicyDenied(RuntimeError):
  pass


def check_permission(perms: list[ToolPermission], *, tool: str, scope: str) -> ToolPermission:
  for p in perms:
      if p.name == tool and scope in p.scopes:
          return p
  raise PolicyDenied(f"policy_denied:{tool}:{scope}")
JAVASCRIPT
export class PolicyDenied extends Error {}

export function checkPermission(perms, { tool, scope }) {
for (const p of perms) {
  if (p.name === tool && p.scopes.includes(scope)) return p;
}
throw new PolicyDenied("policy_denied:" + tool + ":" + scope);
}

Incident réel (avec chiffres)

Un agent avait accès à un wrapper DB “admin” parce que c’était “plus simple”. Il devait trier des tickets support.

Une prompt injection dans un ticket l’a poussé à exécuter une requête qui retournait plus de données que nécessaire.

Impact :

  • pas de fuite externe (heureusement)
  • mais PII dans les logs internes (ça compte quand même)
  • ~6 heures d’incident + cleanup + audit

Fix :

  1. least privilege par tool (scoped creds)
  2. redaction des outputs dans le tool gateway
  3. allowlist + approvals pour les writes

Compromis

  • Un modèle de permissions coûte du dev time. C’est moins cher que l’incident time.
  • Plus de scopes = plus de gestion de policy.
  • Trop restrictif peut freiner le produit → il faut de bons defaults et une escalade claire.

Quand NE PAS l’utiliser

  • Même avec des tools read-only, tu veux des scopes (boundaries tenant).
  • Si un tool ne peut pas être scoppé (il peut “tout faire”), corrige le tool, pas la policy.

Checklist (copier-coller)

  • [ ] Noms d’outils capability-based (read vs write)
  • [ ] Default-deny allowlist
  • [ ] Credentials scoppés (tenant/user/project)
  • [ ] Mode approval pour writes irréversibles
  • [ ] Redaction outputs (PII) + logging
  • [ ] Stop reasons : policy_denied

Config par défaut sûre (JSON/YAML)

YAML
tool_permissions:
  default: "deny"
  grants:
    - tool: "kb.read"
      scopes: ["tenant:acme"]
      mode: "allow"
    - tool: "ticket.close"
      scopes: ["tenant:acme"]
      mode: "approve"
logging:
  redact_outputs: true

FAQ (3–5)

Pourquoi un prompt ne suffit pas comme permission ?
Parce qu’un prompt n’enforce rien. Le modèle peut se tromper, halluciner ou être injecté.
J’ai vraiment besoin de scopes ?
Oui, dès que tu es multi-tenant ou que tu as plusieurs envs. Sinon tu vas leak tôt ou tard.
Comment combiner permissions et budgets ?
Permissions = ‘a-t-il le droit ?’. Budgets = ‘combien de temps / combien ça coûte ?’. Tu veux les deux.
Où enforce tout ça ?
Dans le tool gateway. Pas dans l’UI, pas dans le prompt.

Q: Pourquoi un prompt ne suffit pas comme permission ?
A: Parce qu’un prompt n’enforce rien. Le modèle peut se tromper, halluciner ou être injecté.

Q: J’ai vraiment besoin de scopes ?
A: Oui, dès que tu es multi-tenant ou que tu as plusieurs envs. Sinon tu vas leak tôt ou tard.

Q: Comment combiner permissions et budgets ?
A: Permissions = “a-t-il le droit ?”. Budgets = “combien de temps / combien ça coûte ?”. Tu veux les deux.

Q: Où enforce tout ça ?
A: Dans le tool gateway. Pas dans l’UI, pas dans le prompt.

Pages liées (3–6 liens)

Pas sur que ce soit votre cas ?

Concevez votre agent ->
⏱️ 5 min de lectureMis à jour Mars, 2026Difficulté: ★★★
Implémenter dans OnceOnly
Budgets + permissions you can enforce at the boundary.
Utiliser dans OnceOnly
# onceonly guardrails (concept)
version: 1
budgets:
  max_steps: 25
  max_tool_calls: 12
  max_seconds: 60
  max_usd: 1.00
policy:
  tool_allowlist:
    - search.read
    - http.get
writes:
  require_approval: true
  idempotency: true
controls:
  kill_switch: { enabled: true }
Intégré : contrôle en productionOnceOnly
Ajoutez des garde-fous aux agents tool-calling
Livrez ce pattern avec de la gouvernance :
  • Budgets (steps / plafonds de coût)
  • Permissions outils (allowlist / blocklist)
  • Kill switch & arrêt incident
  • Idempotence & déduplication
  • Audit logs & traçabilité
Mention intégrée : OnceOnly est une couche de contrôle pour des systèmes d’agents en prod.
Auteur

Cette documentation est organisée et maintenue par des ingénieurs qui déploient des agents IA en production.

Le contenu est assisté par l’IA, avec une responsabilité éditoriale humaine quant à l’exactitude, la clarté et la pertinence en production.

Les patterns et recommandations s’appuient sur des post-mortems, des modes de défaillance et des incidents opérationnels dans des systèmes déployés, notamment lors du développement et de l’exploitation d’une infrastructure de gouvernance pour les agents chez OnceOnly.