Anti-pattern Write Access by Default : accès write par défaut

Anti-pattern où l'agent dispose d'un accès write sans restrictions.
Sur cette page
  1. Idée en 30 secondes
  2. Exemple d'anti-pattern
  3. Pourquoi ça apparaît et ce qui se passe mal
  4. Bonne approche
  5. Test rapide
  6. Différence avec les autres anti-patterns
  7. Blind Tool Trust vs Write Access by Default
  8. Agents Without Guardrails vs Write Access by Default
  9. Tool Calling for Everything vs Write Access by Default
  10. Auto-vérification : avez-vous cet anti-pattern ?
  11. FAQ
  12. Et ensuite

Idée en 30 secondes

Write Access by Default est un anti-pattern où l'agent reçoit des write-tools par défaut, sans policy-gate ni vérification avant exécution.

Résultat : une erreur du modèle ou un mauvais routage ne donne pas seulement une mauvaise réponse, mais un vrai changement d'état externe.

Règle simple : le write ne doit pas être "par défaut". Il doit passer par une voie séparée et contrôlée avec vérification explicite des droits, du contexte et des conditions d'exécution.


Exemple d'anti-pattern

L'équipe construit un agent de support qui lit le statut d'une commande et peut fermer un ticket ou envoyer un email si nécessaire.

L'agent reçoit les write-tools immédiatement, sans étape dédiée de vérification avant action.

PYTHON
decision = agent.decide_next_action(user_message)
# route erronée, mais write reste disponible
result = run_tool(decision.tool, decision.args)
return result

Dans ce schéma, la protection de base manque :

PYTHON
# pas de deny-by-default pour les write-tools
# pas de approval_required pour les actions risquées
# pas de idempotency_key pour les retries
# pas de tenant/env scope strict

Pour ce cas, il faut un policy-gate avant toute étape write :

PYTHON
if decision.tool in WRITE_TOOLS and not is_write_allowed(ctx, decision):
    return stop("approval_required")

Si les conditions ne sont pas remplies, le run ne doit pas passer à une action write externe.

Dans ce cas, Write Access by Default ajoute :

  • risque de changements indésirables dans les systèmes externes
  • opérations write dupliquées lors des retries
  • blast radius plus large en environnement multi-tenant

Pourquoi ça apparaît et ce qui se passe mal

Cet anti-pattern apparaît souvent quand l'équipe veut un agent "le plus autonome possible" et ouvre l'accès write avant de construire les limites de contrôle.

Causes typiques :

  • approche démo : donner tous les tools d'abord, ajouter les limites ensuite
  • absence de séparation explicite des routes read et write
  • règles d'accès décrites dans le prompt, pas imposées dans le gateway
  • absence d'idempotency_key obligatoire pour les write-opérations

Résultats :

  • side effects dangereux (changements d'état) - l'agent peut écrire alors qu'il devait seulement lire
  • actions répétées - retry ou loop répète la même write-opération
  • blast radius élevé - sans scope strict, l'erreur touche le mauvais tenant/env
  • analyse d'incident difficile - compliqué de prouver pourquoi write a été autorisé
  • perte de prévisibilité - l'équipe ne contrôle pas quand le système passe en write

Contrairement à Blind Tool Trust, le problème principal ici n'est pas la validation de payload, mais l'accès write ouvert par défaut.

Signaux de production typiques d'un contrôle write faible :

  • des write-tools sont appelés même dans des scénarios censés être read-only
  • les logs montrent beaucoup d'appels write avec le même args_hash ou sans idempotency_key
  • approval_required apparaît presque jamais alors que la part de write est élevée
  • les blocked write attempts sont rares alors que le système propose souvent des risky actions
  • les audit-logs ne montrent pas quelle règle policy a autorisé le write
  • l'équipe ne peut pas expliquer clairement pourquoi un write précis a été autorisé dans ce run
  • les erreurs sont détectées après l'action externe, pas au policy-gate

Point important : chaque write-call modifie l'état externe et n'a souvent pas de rollback simple. Sans deny-by-default et write path contrôlé, une inference ratée devient un incident production.

Bonne approche

Commencez par un modèle read-first : les read-tools sont accessibles par route, et les étapes write passent une vérification dédiée via policy-gate.

Cadre pratique :

  • appliquez deny-by-default à tous les write-tools
  • séparez les routes read_only et write_candidate
  • exigez approval pour les write-actions risquées
  • prenez tenant_id et env uniquement depuis le contexte authentifié, jamais depuis model output
  • ajoutez idempotency_key à chaque write-opération
  • loggez stop_reason et la décision policy-gate pour chaque write-step
PYTHON
WRITE_TOOLS = {"ticket.close", "refund.create", "email.send"}


def execute_action(user_message: str, ctx: dict):
    decision = agent.next_action(user_message)

    if decision.tool in WRITE_TOOLS:
        if not is_write_allowed(ctx, decision):  # policy gate: role, route allowlist, tenant/env scope
            return stop("approval_required")

        scoped_args = enforce_scope(
            decision.args,
            tenant_id=ctx["tenant_id"],
            env=ctx["env"],
        )
        scoped_args["idempotency_key"] = make_idempotency_key(ctx["run_id"], decision)
        return run_tool(decision.tool, scoped_args)

    return run_tool(decision.tool, decision.args)  # read-only tool from allowed set

Dans ce schéma, l'étape write devient contrôlée : le système exécute de façon sûre ou arrête le run de manière transparente.

Test rapide

Si la réponse à ces questions est "oui", vous avez un risque d'anti-pattern Write Access by Default :

  • Un write-tool peut-il être appelé sans vérification explicite policy/approval ?
  • Un retry répète-t-il parfois la même write-action sans idempotency_key ?
  • L'équipe ne peut-elle pas expliquer rapidement pourquoi un write précis a été autorisé ?

Différence avec les autres anti-patterns

Blind Tool Trust vs Write Access by Default

Blind Tool TrustWrite Access by Default
Problème principal : le tool output est accepté sans validation.Problème principal : l'accès write est ouvert par défaut.
Quand il apparaît : quand les checks parse/schema/invariant manquent avant la décision.Quand il apparaît : quand l'étape write ne passe pas par deny-by-default et approval-gate.

En bref : Blind Tool Trust concerne la qualité des données avant action, alors que Write Access by Default concerne les droits de l'action elle-même.

Agents Without Guardrails vs Write Access by Default

Agents Without GuardrailsWrite Access by Default
Problème principal : les limites runtime et le contrôle policy manquent globalement.Problème principal : les write-opérations n'ont pas de contour d'accès strict.
Quand il apparaît : quand le système manque de safety-policy claire pour l'execution.Quand il apparaît : quand write est autorisé comme chemin standard au lieu d'une exception via policy-gate.

En bref : Agents Without Guardrails est un problème plus large de limites d'exécution, alors que Write Access by Default cible un modèle d'accès write dangereux.

Tool Calling for Everything vs Write Access by Default

Tool Calling for EverythingWrite Access by Default
Problème principal : les tools sont appelés inutilement, même quand on peut s'en passer.Problème principal : une fois l'appel tool fait, write peut passer sans contrôle suffisant.
Quand il apparaît : quand il n'y a pas de route no_tool stable pour les cas simples.Quand il apparaît : quand le système ne sépare pas les niveaux d'accès read et write.

En bref : Tool Calling for Everything augmente le volume d'appels, alors que Write Access by Default augmente le coût d'erreur de chaque write-call.

Auto-vérification : avez-vous cet anti-pattern ?

Vérification rapide de l'anti-pattern Write Access by Default.
Cochez les points pour votre système et regardez le statut ci-dessous.

Vérifiez votre système :

Progression: 0/8

⚠ Il y a des signes de cet anti-pattern

Essayez de déplacer les étapes simples dans un workflow et de garder l'agent uniquement pour les décisions complexes.

FAQ

Q : Est-ce que cela veut dire que l'agent ne doit jamais faire d'actions write ?
R : Non. Les actions write sont possibles, mais seulement via un chemin contrôlé : policy-gate, approval (si nécessaire), scope enforcement et idempotency.

Q : Quelle différence entre policy-gate et approval ?
R : Policy-gate est un contrôle déterministe des règles à l'exécution. Approval est une confirmation séparée pour une action risquée précise. Ce sont deux niveaux de contrôle différents.

Q : Quel minimum implémenter d'abord ?
R : Commencez avec deny-by-default pour write, idempotency_key obligatoire, tenant/env scope strict et logging stop_reason pour les tentatives write bloquées.


Et ensuite

Anti-patterns proches :

Ce qu'il faut construire à la place :

⏱️ 8 min de lectureMis à jour 17 mars 2026Difficulté: ★★★
Implémenter dans OnceOnly
Safe defaults for tool permissions + write gating.
Utiliser dans OnceOnly
# onceonly guardrails (concept)
version: 1
tools:
  default_mode: read_only
  allowlist:
    - search.read
    - kb.read
    - http.get
writes:
  enabled: false
  require_approval: true
  idempotency: true
controls:
  kill_switch: { enabled: true, mode: disable_writes }
audit:
  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

Nick — ingénieur qui construit une infrastructure pour des agents IA en production.

Focus : patterns d’agents, modes de défaillance, contrôle du runtime et fiabilité des systèmes.

🔗 GitHub: https://github.com/mykolademyanov


Note éditoriale

Cette documentation est assistée par l’IA, avec une responsabilité éditoriale humaine pour l’exactitude, la clarté et la pertinence en production.

Le contenu s’appuie sur des défaillances réelles, des post-mortems et des incidents opérationnels dans des systèmes d’agents IA déployés.