Tenxyte AIRS (Responsabilité et Sécurité de l'IA)¶
Sommaire¶
- Présentation
- 1. Parité Agentique de Base — AgentToken
- 2. Disjoncteur et Limitation de Débit
- 3. Intervention Humaine (Human in the Loop - HITL)
- 4. Garde-fous : Caviardage des PII et Suivi Budgétaire
- 5. Audit Forensique
- Référence de Configuration
Présentation¶
Tenxyte AIRS est une suite complète de mesures de responsabilité, de sécurité et de protection pour les agents IA intégrés. Elle répond aux défis majeurs posés par les LLM et les modèles agentiques dans les environnements de production (ex : EchoLeak, Shadow Escape, dépenses incontrôlées).
Principe fondamental : Un agent IA n'agit jamais sous sa propre autorité. Il emprunte l'identité et les permissions d'un utilisateur humain via un jeton délimité et limité dans le temps (AgentToken), et chaque action qu'il entreprend est auditable, contrôlable et suspendable.
1. Parité Agentique de Base — AgentToken¶
Un AgentToken est le jeton d'identité délivré à un agent IA. Il permet une délégation sécurisée : l'agent agit au nom d'un utilisateur humain, avec un sous-ensemble strict de ses permissions, sans jamais manipuler les identifiants de l'utilisateur.
Création (API)¶
POST /ai/tokens/
Authorization: Bearer <user_jwt>
Content-Type: application/json
{
"agent_id": "finance-agent-v2",
"expires_in": 3600,
"permissions": ["read:reports", "write:invoices"],
"organization": "acme-corp",
"budget_limit_usd": 5.00,
"circuit_breaker": {
"max_requests_per_minute": 30,
"max_requests_total": 500
},
"dead_mans_switch": {
"heartbeat_required_every": 300
}
}
Réponse (201) :
{
"id": 42,
"token": "eKj3...raw_token...Xz9",
"agent_id": "finance-agent-v2",
"status": "ACTIVE",
"expires_at": "2024-01-20T16:00:00Z"
}
⚠️ La valeur brute du
tokenn'est renvoyée qu'une seule fois lors de la création. Stockez-la de manière sécurisée — seul son hachage SHA-256 est conservé dans la base de données.
L'agent utilise ensuite AgentBearer <token> dans l'en-tête Authorization pour toutes les requêtes suivantes.
Double Validation RBAC¶
Chaque requête effectuée avec un AgentToken passe par deux vérifications de permissions :
- Vérification du périmètre de l'agent : L'
AgentTokeninclut-il la permission requise dans sesgranted_permissions? - Vérification humaine : L'utilisateur délégant détient-il toujours cette permission dans la base de données (ou au sein de l'organisation) ?
Si l'une des vérifications échoue, la requête est rejetée avec une erreur 403 Forbidden.
Cycle de vie du jeton¶
| Statut | Description |
|---|---|
ACTIVE |
Le jeton est valide et peut être utilisé |
SUSPENDED |
Désactivé automatiquement (disjoncteur, budget, battement de cœur) |
REVOKED |
Révoqué manuellement — permanent, irréversible |
EXPIRED |
Durée de vie dépassée (expires_at) |
2. Disjoncteur et Limitation de Débit (Circuit Breaker)¶
Le disjoncteur est un pare-feu autonome qui protège contre les comportements incontrôlés des agents : boucles infinies, pics d'exfiltration de données ou cascades d'échecs inattendues.
Seuils configurables (par jeton)¶
| Champ | Par défaut | Description |
|---|---|---|
max_requests_per_minute |
60 | Limite de requêtes par minute (RPM) via le cache |
max_requests_total |
1000 | Plafond absolu de requêtes pour la durée de vie du jeton |
max_failed_requests |
10 | Nombre max d'erreurs consécutives avant suspension |
Si un seuil est dépassé, le jeton passe automatiquement au statut SUSPENDED avec la raison appropriée :
| Raison | Déclencheur |
|---|---|
RATE_LIMIT |
RPM ou total de requêtes dépassé |
ANOMALY |
Nombre max d'échecs consécutifs dépassé |
HEARTBEAT_MISSING |
Expiration de la sécurité "Dead Man's Switch" |
BUDGET_EXCEEDED |
Le coût LLM a dépassé la limite budgétaire |
MANUAL |
Suspendu manuellement par l'utilisateur délégant |
Dead Man's Switch (Sécurité d'absence)¶
Si heartbeat_required_every (en secondes) est défini, l'agent doit appeler périodiquement :
Si aucun battement de cœur n'est reçu dans l'intervalle configuré, le jeton est automatiquement suspendu avec HEARTBEAT_MISSING. Cela garantit que si le conteneur d'orchestration plante ou est corrompu, l'agent perd automatiquement son accès.
Interrupteur d'urgence (Kill Switch)¶
Pour révoquer immédiatement tous les jetons actifs d'un utilisateur (option radicale) :
3. Intervention Humaine (Human in the Loop - HITL)¶
Certaines actions sont trop sensibles pour qu'un agent IA les exécute de manière autonome. Le HITL garantit qu'un humain doit explicitement les approuver avant leur exécution.
Fonctionnement¶
Les points de terminaison décorés avec @require_agent_clearance(human_in_the_loop_required=True) se comportent différemment lorsqu'ils sont appelés par un agent :
- L'agent appelle le point de terminaison normalement.
- Au lieu de s'exécuter, Tenxyte crée une action en attente (
AgentPendingAction) et renvoie202 Accepted(pas200). - L'humain est notifié (email, webhook, etc.) avec un
confirmation_token. - L'humain confirme ou refuse via l'API.
- L'agent peut interroger (poll) ou être notifié pour réessayer.
Actions HITL globales¶
Configurez les actions qui nécessitent toujours une approbation humaine dans le fichier settings.py :
Points de terminaison de confirmation/refus¶
# L'humain approuve
POST /ai/pending-actions/<confirmation_token>/confirm/
Authorization: Bearer <user_jwt>
# L'humain refuse
POST /ai/pending-actions/<confirmation_token>/deny/
Authorization: Bearer <user_jwt>
Les actions en attente de l'agent peuvent également être listées :
4. Garde-fous : Caviardage des PII et Suivi Budgétaire¶
Caviardage des PII (Informations Personnelles Identifiables)¶
Lorsque TENXYTE_AIRS_REDACT_PII = True, un middleware intercepte toutes les réponses JSON envoyées à un demandeur AgentBearer et anonymise automatiquement les champs sensibles (emails, numéros de téléphone, IBAN, etc.) en les remplaçant par ***REDACTED***.
Cela empêche les LLM d'ingérer ou de mémoriser des informations personnelles identifiables provenant de votre backend.
Suivi Budgétaire¶
Le suivi budgétaire vous permet de plafonner l'impact financier qu'un agent peut avoir via des appels d'API LLM (OpenAI, Anthropic, Google, etc.).
Important : Tenxyte ne connaît pas les tarifs des LLM. Il est agnostique vis-à-vis du modèle. Votre code est responsable de la conversion du nombre de jetons en un coût USD et de son signalement. Tenxyte ne fait qu'accumuler le
cost_usdsignalé et suspend l'agent lorsque la limite est atteinte.
Activer dans les paramètres¶
Créer un jeton avec un plafond budgétaire¶
from tenxyte.services.agent_service import AgentTokenService
service = AgentTokenService()
token = service.create(
triggered_by=user,
application=app,
granted_permissions=[],
budget_limit_usd=1.00, # 1.00 $ maximum
)
Calculer le coût dans votre wrapper LLM¶
Vous êtes responsable du maintien d'une table de tarification et du calcul des coûts :
# Exemple de table de tarification (à mettre à jour selon les tarifs des fournisseurs)
MODEL_PRICING = {
"claude-sonnet-4-5": {"input": 3.00, "output": 15.00}, # par million de jetons
"gemini-1.5-pro": {"input": 3.50, "output": 10.50},
"gpt-4o": {"input": 5.00, "output": 15.00},
}
def calculate_cost_usd(model: str, prompt_tokens: int, completion_tokens: int) -> float:
pricing = MODEL_PRICING.get(model, {"input": 0.0, "output": 0.0})
return (
(prompt_tokens / 1_000_000) * pricing["input"] +
(completion_tokens / 1_000_000) * pricing["output"]
)
Signaler l'utilisation après chaque appel LLM¶
Via le service Python :
# Après avoir appelé votre LLM (Anthropic, Google, OpenAI, etc.)
prompt_tokens = response.usage.input_tokens # depuis la réponse du fournisseur
completion_tokens = response.usage.output_tokens
cost = calculate_cost_usd("claude-sonnet-4-5", prompt_tokens, completion_tokens)
success = service.report_usage(token, cost_usd=cost)
if not success:
# Budget dépassé → le jeton est désormais SUSPENDED
# L'agent recevra des erreurs 401/403 lors des requêtes suivantes
raise Exception("Budget de l'agent épuisé")
Via l'API REST (depuis l'agent lui-même) :
POST /ai/tokens/{id}/report-usage/
Authorization: AgentBearer <raw_token>
Content-Type: application/json
{
"cost_usd": 0.042,
"prompt_tokens": 1250,
"completion_tokens": 450
}
Réponse lorsque le budget est dépassé (403) :
Ce qui se passe en interne¶
report_usage(cost_usd=0.60, budget_limit=0.50)
↓
current_spend_usd += 0.60 → 0.60
current_spend_usd (0.60) >= budget_limit (0.50)
↓
token.status = SUSPENDED
token.suspended_reason = BUDGET_EXCEEDED
↓
return False (toutes les requêtes futures avec ce jeton → 403)
5. Audit Forensique¶
Chaque requête d'agent peut porter un en-tête X-Prompt-Trace-ID. Cet ID est :
- Stocké dans
AgentPendingAction.prompt_trace_id - Lié dans l'
AuditLog(Journal d'audit)
Cela permet une traçabilité précise : "quel prompt utilisateur a déclenché quelle action backend", facilitant les enquêtes après incident et les rapports de conformité.
POST /ai/tokens/{id}/some-action/
Authorization: AgentBearer <raw_token>
X-Prompt-Trace-ID: trace_7f3a2b9c-...
Référence de Configuration¶
Tous les paramètres sont définis dans settings.py. Les valeurs par défaut sont gérées via src/tenxyte/conf/airs.py.
| Paramètre | Par défaut | Description |
|---|---|---|
TENXYTE_AIRS_ENABLED |
True |
Interrupteur principal pour AIRS |
TENXYTE_AIRS_TOKEN_MAX_LIFETIME |
86400 |
Durée de vie maximale du jeton (secondes) |
TENXYTE_AIRS_DEFAULT_EXPIRY |
3600 |
Expiration par défaut du jeton si non spécifiée (secondes) |
TENXYTE_AIRS_REQUIRE_EXPLICIT_PERMISSIONS |
True |
Les jetons doivent déclarer des permissions explicites |
TENXYTE_AIRS_CIRCUIT_BREAKER_ENABLED |
True |
Activer/désactiver le disjoncteur |
TENXYTE_AIRS_DEFAULT_MAX_RPM |
60 |
RPM max par défaut |
TENXYTE_AIRS_DEFAULT_MAX_TOTAL |
1000 |
Plafond total de requêtes par défaut |
TENXYTE_AIRS_DEFAULT_MAX_FAILURES |
10 |
Max d'échecs par défaut avant suspension |
TENXYTE_AIRS_CONFIRMATION_REQUIRED |
[] |
Liste des codes de permission nécessitant toujours un HITL |
TENXYTE_AIRS_REDACT_PII |
False |
Activer le caviardage des PII pour les réponses aux agents |
TENXYTE_AIRS_BUDGET_TRACKING_ENABLED |
False |
Activer le suivi budgétaire LLM |