Idée en 30 secondes
Human approval est un runtime-gate pour les actions write risquées : avant exécution, l'agent reçoit approval_required et attend une confirmation humaine.
Quand c'est nécessaire : quand un agent peut modifier des données, envoyer des messages clients, ou lancer des actions irréversibles en production.
Problème
Sans approval, les actions write sont exécutées immédiatement si la policy les autorise. En demo, c'est pratique. En production, une erreur de l'agent devient un incident réel.
Le problème n'est pas seulement un modèle "mauvais". Même un bon modèle se trompe parfois sur des demandes atypiques. S'il n'y a pas de gate humain entre l'agent et l'outil write, une erreur devient immédiatement un side effect dans des systèmes réels.
Analogie : c'est comme un paiement sans 3D Secure. Tant que tout se passe bien, il n'y a pas de délai. Quand quelque chose tourne mal, les conséquences deviennent coûteuses en quelques secondes.
Solution
La solution est d'ajouter dans la policy layer un flow d'approval dédié aux actions write risquées.
La policy renvoie l'une des décisions suivantes : allow, deny ou approval_required.
approval_required n'exécute pas l'action immédiatement : runtime crée une approval request, attend une décision humaine, et n'exécute le tool call qu'après approval_granted.
Cette décision est prise à chaque étape, pas seulement à la fin du run.
Human Approval != Manual Mode
Ce sont des modèles différents :
- Manual mode : un humain exécute presque chaque action à la place de l'agent.
- Human approval : l'agent travaille de façon autonome, et l'humain confirme seulement les actions write risquées.
L'un sans l'autre n'est pas suffisant :
- sans approval, les actions risquées passent sans contrôle supplémentaire
- si on utilise manual mode pour tout, le système perd en vitesse et en scalabilité
Exemple :
- sans approval :
ticket.close_bulkest exécuté immédiatement - avec approval : la policy renvoie
approval_required, et l'action attend une confirmation
Métriques de contrôle d'approval
Ces métriques et signaux travaillent ensemble à chaque étape de l'agent.
| Métrique | Ce qu'elle contrôle | Mécaniques clés | Pourquoi |
|---|---|---|---|
| Approval scope | Quelles actions nécessitent une confirmation | write policy risk tiers | Réduit le risque sur les actions irréversibles |
| Approval request context | Ce que l'humain voit exactement avant de décider | preview + args hash reason + policy context | Permet une décision fondée |
| TTL et annulation | Cycle de vie de l'approval request | approval TTL cancel flow | Empêche qu'un run reste bloqué indéfiniment |
| Execution gate | Exécution réelle de l'action write | approval token gateway enforcement | Garantit que le write ne part pas sans confirmation |
| Approval observability | Visibilité sur les décisions d'approval | audit logs alerts on timeout spikes | Ne limite pas directement l'action, mais aide à détecter les goulots du process d'approval |
Comment cela se place dans l'architecture
La policy layer (tool gateway) se place entre runtime et tools et constitue le point unique de contrôle d'accès avant chaque étape.
Chaque décision (allow, deny, approval_required) est journalisée dans l'audit log.
Chaque étape de l'agent passe par ce flow avant exécution : runtime n'exécute pas directement une action write — d'abord vérification policy -> approval gate -> exécution.
Résumé du flow :
- Runtime forme un tool call
- la policy layer vérifie le risque et peut renvoyer
approval_required - en cas de
approval_granted, le write est exécuté - en cas de
approval_deniedouapproval_timeout, le run reçoit un stop reason - chaque décision est écrite dans l'audit log
Dans runtime, deny est aussi converti en stop reason explicite, visible dans les logs et la réponse du run.
Une approval request contient en général :
- tool
- preview courte de l'action
- args hash
- reason / risk tier
- TTL
Exemple
Un agent support veut exécuter email.send pour un client.
La policy définit qu'une confirmation humaine est nécessaire pour ce tool.
Résultat :
- sans approval token, le write n'est pas exécuté
- après
approval_granted, l'appel passe - en cas de timeout, l'agent renvoie
stop("approval_timeout")
Human approval arrête l'action risquée avant le side effect, pas après l'incident.
Dans le code, cela ressemble à ceci
Dans le schéma simplifié ci-dessus, le control flow principal est montré. En pratique, vérification et exécution doivent passer par un seul policy/tool gateway.
Exemple de configuration d'approval :
approvals:
required_for:
- email.send
- ticket.close_bulk
- db.write
ttl_seconds: 300
fallback_when_not_approved: stop
decision = policy.evaluate(tool, user_context, mode="normal")
if decision.outcome == "approval_required":
request = approvals.create_request(
run_id=run_id,
tool=tool,
args_hash=hash_args(args),
ttl_seconds=300,
)
audit.log(run_id, decision.outcome, reason="pending_human_review", tool=tool, pending_id=request.id)
return stop("approval_required", pending_id=request.id)
elif decision.outcome == "deny":
audit.log(run_id, decision.outcome, reason=decision.reason, tool=tool)
return deny(decision.reason)
# later, in resume flow with pending_id
approval = approvals.get_decision(pending_id)
if approval.outcome != "approved":
audit.log(run_id, "deny", reason=approval.outcome, tool=tool, pending_id=pending_id)
return stop(approval.outcome)
audit.log(run_id, "approval_granted", reason="human_approved", tool=tool, approver=approval.approved_by)
result = tool.execute({**args, "approval_token": approval.token})
decision = Decision.allow(reason="policy_ok")
audit.log(run_id, decision.outcome, reason=decision.reason, tool=tool, result=result.status)
return result
En production, le flow d'approval est généralement asynchrone : runtime crée une request, renvoie un état pending/stop sans bloquer le worker, puis reprend le run après la décision humaine.
Comment cela se passe pendant l'exécution
Scénario 1 : confirmé (approval granted)
1. Runtime forme un appel email.send.
2. La policy renvoie approval_required.
3. Runtime crée une approval request et renvoie un état pending/stop.
4. Un humain confirme l'action dans la TTL.
5. Runtime reprend le run, exécute le tool call et écrit `approval_granted -> allow`.
---
Scénario 2 : timeout d'approval
1. Runtime forme un appel db.write.
2. La policy renvoie approval_required.
3. Runtime crée une approval request et renvoie un état pending/stop.
4. Aucune confirmation n'est reçue avant la fin de la TTL.
5. Runtime renvoie stop (approval_timeout), l'action n'est pas exécutée.
---
Scénario 3 : policy deny sans approval
1. Runtime forme un appel write hors du scope autorisé.
2. La policy renvoie immédiatement deny.
3. Runtime renvoie un stop reason.
4. Audit : decision=deny, reason=policy_denied.
5. L'action n'est pas exécutée.
Erreurs fréquentes
- approval uniquement dans l'UI, mais pas dans le policy/tool gateway
- approval sans TTL ni annulation
- même approche pour actions write low-risk et high-risk
- absence d'approval token à l'exécution du tool
- ne pas logguer
approval_requiredetapproval_granted - bloquer tous les runs en attente d'approval au lieu de renvoyer un état stop/pending explicite
Résultat : le système laisse passer des actions dangereuses, ou se bloque dans des files d'approval sans état transparent.
Auto-vérification
Vérification rapide human-approval avant lancement en production :
Progression: 0/8
⚠ Les contrôles de governance de base manquent
Avant la production, il faut au minimum le contrôle d'accès, des limites, des audit logs et un arrêt d'urgence.
FAQ
Q: Quelles actions doivent obligatoirement avoir un approval ?
A: Les actions write irréversibles ou visibles côté client : changements de données, fermetures en masse, envoi de messages, opérations financières.
Q: Comment éviter de noyer l'équipe sous l'approval-spam ?
A: Découper les actions write en risk tiers. High-risk -> approval obligatoire, low-risk -> policy séparée avec tighter limits et audit.
Q: Faut-il bloquer le worker pendant l'attente d'approval ?
A: Mieux vaut non. Retourne un état pending/stop et reprends le run après décision pour éviter files d'attente et deadlocks.
Q: Est-ce que l'approval peut remplacer RBAC et budgets ?
A: Non. Approval est un gate supplémentaire pour actions risquées. RBAC, limits et budgets restent nécessaires.
Q: Que faut-il logguer au minimum ?
A: approval_required, approval_granted|approval_denied|approval_timeout, qui a approuvé, quel tool, quel reason, et le résultat d'exécution.
Où Human Approval se place dans le système global
Human approval est une des couches d'Agent Governance. Avec allowlist/RBAC, budgets, limits et audit, il forme un système unifié de contrôle d'exécution.
Pages liées
Pour continuer :
- Vue d'ensemble Agent Governance — modèle global de contrôle des agents en production.
- Allowlist vs Blocklist — comment construire un accès tools en default-deny.
- Contrôle d'accès (RBAC) — comment limiter l'accès par rôles et tenant scope.
- Contrôle des budgets — comment contenir runaway-coûts et boucles.
- Audit logs pour agents — comment expliquer les décisions approval/policy en incident.