Pièges courants
Anti-patrons qui défont discrètement le scale-to-zero et la sûreté des agents — et comment les éviter.
Ces patrons ne produisent pas d'erreur. Ils passent la CI, ils paraissent raisonnables dans un diff, et ils annulent discrètement une garantie que vous payez — les économies du scale-to-zero ou la sûreté des agents. Chacun ci-dessous : ce qui se passe, pourquoi ça fait mal, et le correctif.
Le code keep-alive défait le scale-to-zero
Un agent ajoute « obligeamment » du code qui touche la base de données sur un minuteur. Chaque requête périodique compte comme de l'activité et réinitialise le minuteur de suspension, de sorte qu'un point de terminaison que vous avez conçu pour descendre à zéro ne dort jamais — et l'inactivité cesse d'être gratuite.
Cela arrive sous plusieurs formes. Un heartbeat frontend ou backend :
// runs forever, holds the compute awake forever
setInterval(async () => {
await pool.query("SELECT 1"); // "health check"
}, 30_000);Un moniteur de disponibilité externe pointé vers un point de terminaison dont le gestionnaire se trouve interroger la BD — donc chaque sonde réveille le calcul :
app.get("/health", async (_req, res) => {
await pool.query("SELECT 1"); // monitored every 60s → never idle
res.send("ok");
});Ou des réglages de pool de connexions qui maintiennent une connexion vivante avec des requêtes de
validation — un min au-dessus de zéro, ou un « warmer » serverless :
const pool = new Pool({
min: 2, // keeps ≥2 connections open + validated
// a validation/keep-alive query on each idle connection resets the timer
});Correctif : auditez les diffs écrits par l'agent pour tout accès périodique à la base de données. Gardez les vérifications
de vivacité à la couche HTTP — sondez l'application, pas la BD — et laissez le pool se vider
jusqu'à zéro (min: 0). La vue de calcul de la console montre pourquoi un point de terminaison ne
descend pas à zéro, ce qui fait vite surgir un heartbeat égaré.
Confier à l'agent les identifications de main court-circuite ASCC
Donner à un agent la chaîne de connexion de la branche main — ou le laisser exécuter keon
connecté en tant que votre propre utilisateur — contourne tout ce qu'ASCC applique : isolation de
sandbox, budgets LEASH, vérifications LINT et BLAST, portes de promotion, attribution,
et ancres d'annulation. L'agent écrit désormais directement en production, et rien de la
boucle qui rend les changements d'agent sûrs ne s'exécute jamais.
L'agent ne devrait jamais détenir d'identification capable d'écrire sur main. La promotion est
côté serveur par conception — cp est le seul rédacteur en production.
Correctif : forgez une clé API à portée d'agent (capability = agent, scope = un
projet, expiration courte) dans Settings → API keys, remettez à l'agent uniquement des chaînes de
connexion de sandbox, et retirez les identifications plus puissantes de son environnement
(pas de DATABASE_URL complet, pas de ~/.pgpass, pas de session keon connectée dans le même
shell). Voir Confier à un agent une identification à portée limitée et la
section SCOPE de Guardrails.
Tempêtes de réessais autour du réveil
La première connexion après une suspension doit réveiller le calcul, elle est donc plus lente qu'une connexion chaude. Un agent qui voit une seule connexion lente peut la « corriger » — avec des délais d'attente client agressifs et des boucles de réessai qui martèlent le point de terminaison, ou en ajoutant un keep-alive (piège #1) pour ne jamais avoir à se réveiller du tout. Les deux échangent les économies pour masquer un coût ponctuel.
Correctif : fixez un connect_timeout client autour de 10s et soyez patient à la première
connexion. Le démarrage à froid est inférieur à la seconde en même région une fois les chemins chauds en jeu — une
connexion légèrement lente est attendue, pas un défaut à contourner par de l'ingénierie.
postgresql://…?connect_timeout=10Identifications validées dans le code
Les agents codent en dur des chaînes de connexion et des clés API dans les sources et les fichiers .env
qui atteignent ensuite git. Les clés fuitées sont récoltées en quelques heures après avoir atteint un dépôt public
(ou ultérieurement public) — la fenêtre se mesure en heures, pas en jours.
Correctif : injectez les secrets via l'environnement, ne les validez jamais. Gardez les fichiers .env
hors de git. À toute fuite, effectuez une rotation immédiate depuis Settings → API keys
— révoquez la clé exposée et forgez-en une neuve.
Le DDL direct sur main contourne la boucle de promotion
Exécuter une migration directement contre main saute la capture qui rend un
changement réversible et auditable. Vous perdez la migration up/down émise (EMIT),
l'entrée de registre signée (LEDGER), et l'ancre d'annulation (UNDO). Le schéma a
changé, mais il n'existe aucun enregistrement que la plateforme puisse rejouer ou annuler.
Correctif : sandbox → promote, même pour un changement de schéma « trivial ». La boucle de promotion
est ce qui produit la migration, l'entrée de registre et l'ancre ; un ALTER direct
n'en produit aucun.
Les écritures dans une transaction annulée atterrissent quand même
La capture enregistre les instructions que l'agent exécute — elle n'a aucune
conscience des frontières de transaction. Les instructions exécutées dans un BEGIN … ROLLBACK
sont toujours capturées, et si ce sandbox est promu, elles sont rejouées et
appliquées. Un ROLLBACK dans le sandbox ne les dé-capture pas.
BEGIN;
UPDATE users SET plan = 'pro'; -- captured
ROLLBACK; -- does NOT remove it from the captureCorrectif : ne comptez pas sur ROLLBACK dans un sandbox pour « annuler » un travail exploratoire.
Si vous voulez que le travail disparaisse, jetez le sandbox — c'est le chemin d'élimination que la capture
respecte.
Garer du travail dans un sandbox au-delà de son budget ou de son TTL
Les sandboxes sont éphémères. Quand un sandbox épuise son budget LEASH, il est
auto-jeté (status=discarded), et tout travail non promu en son sein est perdu.
Traiter un sandbox comme une branche à longue durée de vie que vous « reprendrez » est la façon dont les
changements d'une journée disparaissent.
Correctif : promouvez-le, ou re-capturez le travail dans un sandbox neuf. Traitez les sandboxes comme jetables par défaut — l'artefact durable est la promotion, pas le sandbox.
Mal interpréter les garanties
Trois pièges spécifiques dans ce que les vérifications promettent réellement :
-
L'essai à blanc du rayon d'explosion est consultatif. Il mesure ce qu'une promotion ferait — verrous, durées, nombres de lignes réels — mais il ne garde jamais la promotion. Un essai à blanc propre est une information, pas un feu vert ; et le fait qu'un essai à blanc soit requis avant la promotion est la décision de POLICY, pas celle de l'essai à blanc.
-
Approve ne peut pas outrepasser un blocage de politique. Un Approve humain ne peut jamais faire passer un
blockde politique ou une instruction hors couloir. La seule façon de dépasser un blocage est un changement de politique audité — il n'y a pas d'interrupteur de contournement manuel, par conception. -
Un fork masqué masque les valeurs, pas la forme. Sur un fork masqué, les valeurs sont masquées, donc le DML dépendant des données que l'agent écrit contre ces valeurs masquées ne correspondra pas aux vraies lignes sur le parent au rejeu. Le travail de couloir de schéma est indépendant des valeurs et se rejoue fidèlement ; le DML dépendant des valeurs développé contre des données masquées, non.
Forks masqués
Donnez à un agent (ou à un humain) la forme de la prod et rien de ses PII — politiques de masquage, la bibliothèque de fonctions intégrées, et comment les branches et sandboxes masqués restent scellés jusqu'à ce que le masque soit validé.
Confier à un agent une identification à portée limitée
Provisionnez une clé API limitée par capacité, projet et expiration, puis exécutez un agent IA sur votre base de données en toute sécurité.