Vue d’ensemble de l’architecture
- Serveur : service HTTP Rust qui reçoit les lots d’événements, les écrit dans ClickHouse et maintient l’état relationnel dans PostgreSQL.
- Tableau de bord : application web Next.js qui lit et écrit exclusivement via l’API du serveur.
- agenteye-collector : déployé sur les machines des agents, pas sur l’hôte du serveur.
- Postgres 15+ : OBLIGATOIRE. (Relevé de la version 14 lors de la mise à jour multi-tenant ; le schéma org-membership utilise une clé étrangère
ON DELETE SET NULLavec liste de colonnes, fonctionnalité propre à Postgres 15+. Mettez à niveau Postgres avant de déployer cette version.) Stocke l’état OLTP :api_keys,users,sessions,evaluation_jobs(queue),dashboards,saved_queries,otp_codes, ainsi que les tables multi-tenantorgs,org_memberships,org_settings. - ClickHouse 24+ : OBLIGATOIRE. Le store analytique pour chaque événement ingéré. Moteur :
ReplacingMergeTree, partitionné par mois, ordonné par(session_id, ts, dedup_key). Le serveur se connecte viaCLICKHOUSE_URL; le répertoiredeploy/base/clickhouse/fourni embarque une configuration mono-nœud optimisée pour les performances. Exigence multi-tenant : la configuration fournie active la gestion des accès SQL +users_without_row_policies_can_read_rows=falseafin que le serveur puisse créer un utilisateur ClickHouse en lecture seule et une politique de lignes par organisation (la frontière d’isolation appliquée par le moteur pour l’éditeur SQL et l’agent IA). Si vous fournissez votre propre configuration ClickHouse, reportez ces paramètres (voirdeploy/base/clickhouse/configmap.yaml). - Redis 7+ : cache partagé et backend de limitation de débit optionnels. Le serveur et le tableau de bord se connectent tous deux via
REDIS_URL. En l’absence de Redis, les deux dégradent gracieusement vers des chemins Postgres uniquement. Voir Redis (cache optionnel) ci-dessous.
Serveur
Récupérer l’image
Les builds actuels sont publiés sousbeta-latest;latestest réservé aux versions stables. En production, épinglez un tag:v<version>spécifique ; voir Tags d’images disponibles.
Variables d’environnement
| Variable | Requise | Défaut | Description |
|---|---|---|---|
DATABASE_URL | Oui | aucun | DSN Postgres. Format de chaîne de connexion libpq standard avec le schéma postgres://. Supporte ?sslmode=require et d’autres paramètres libpq. Le mot de passe ne doit pas contenir /, + ou = ; utilisez openssl rand -hex pour générer des mots de passe sûrs pour les URL. |
ADMIN_KEY | Non | aucun | Clé API d’administration de démarrage. Mise à jour avec toutes les permissions à chaque démarrage. Faites pivoter en changeant la valeur et en redémarrant. |
LISTEN_ADDR | Non | 0.0.0.0:8080 | Adresse TCP à écouter |
MAX_BODY_BYTES | Non | 134217728 (128 Mo) | Taille maximale du corps de la requête |
ADMIN_EMAIL | Non | aucun | Email de l’utilisateur administrateur de démarrage. Mis à jour avec toutes les permissions à chaque démarrage et marqué comme protégé : ne peut pas être désactivé ni voir ses permissions modifiées via le tableau de bord/l’API. Pour faire pivoter l’administrateur de démarrage, changez ADMIN_EMAIL et redémarrez ; le nouvel email est mis à jour comme protégé, et l’ancien conserve sa protection jusqu’à ce qu’elle soit manuellement supprimée en base de données. |
ALLOWED_EMAILS | Non | aucun (tout bloqué) | Liste d’emails autorisés séparés par des virgules pour la création d’utilisateurs et la connexion. Supporte les adresses exactes (user@example.com) et les jokers de domaine (*@example.com). Si non défini, aucun utilisateur ne peut être créé ni se connecter. Initialisation au premier démarrage uniquement : alimente la liste blanche de l’organisation par défaut au premier démarrage ; ensuite, la page /<org>/settings de chaque organisation fait foi et toute modification de cette variable d’environnement n’a aucun effet. |
SMTP_HOST | Non | aucun | Nom d’hôte du serveur SMTP pour l’envoi des emails OTP. Si non défini, les codes OTP sont enregistrés sur stdout. |
SMTP_PORT | Non | 587 | Port du serveur SMTP |
SMTP_USERNAME | Non | aucun | Nom d’utilisateur pour l’authentification SMTP |
SMTP_PASSWORD | Non | aucun | Mot de passe pour l’authentification SMTP |
SMTP_FROM | Non | aucun | Adresse email expéditeur pour les emails OTP |
SMTP_TLS | Non | STARTTLS | STARTTLS est utilisé sauf si vous le désactivez explicitement : false ou 0 envoie en texte clair (sans TLS) ; toute autre valeur — y compris l’absence de définition — active STARTTLS. |
DASHBOARD_URL | Non | valeur par défaut intégrée | Origine du tableau de bord utilisée pour construire à la fois le lien magique de l’email OTP et les liens magiques d’incidents dans les notifications d’alerte. Si non défini, il revient à une valeur par défaut intégrée (et, pour les OTP uniquement, à l’origine de la requête dérivée du tableau de bord en premier). Définissez-le pour les configurations à domaines séparés afin que les liens email et Slack/incident pointent vers votre tableau de bord. Voir URL du lien magique email ci-dessous ; la plupart des opérateurs n’ont pas besoin de le définir. |
SESSION_TTL_SECS | Non | 86400 (24 h) | Durée de session du tableau de bord en secondes. Initialisation au premier démarrage uniquement : modifiable par organisation via /<org>/settings après le premier déploiement. |
OTP_TTL_SECS | Non | 600 (10 min) | Durée de validité du code OTP en secondes. Initialisation au premier démarrage uniquement : modifiable par organisation via /<org>/settings après le premier déploiement. |
REDIS_URL | Non | aucun | Backend de cache partagé et de limitation de débit optionnel, ex. redis://redis:6379/0. Lorsqu’il est défini, le serveur met en cache les lookups de clés API authentifiées, l’agrégat /models du tableau de bord, la liste des sessions, et la facette de liste des environnements ; il déplace également la limitation de débit des requêtes OTP de Postgres COUNT vers Redis INCR. Si non défini ou inaccessible, le serveur fonctionne sans cache (la limite OTP revient à Postgres, tous les autres appels au cache passent à la source de vérité). Voir Redis (cache optionnel) ci-dessous. |
CLICKHOUSE_URL | Oui | aucun | URL de base de l’instance ClickHouse, ex. http://clickhouse:8123. Le serveur applique son schéma d’événements à cette base de données à chaque démarrage et refuse de démarrer s’il ne peut pas atteindre ClickHouse. Voir ClickHouse (store analytique requis) ci-dessous. |
CLICKHOUSE_DATABASE | Non | agenteye | Nom de la base de données (schéma) ClickHouse. Le serveur la crée au démarrage si elle n’existe pas. |
ORG_CH_SECRET | Non (mono-tenant) / Oui (multi-org) | valeur dev par défaut | Clé HMAC à partir de laquelle le mot de passe ClickHouse par tenant de chaque organisation est dérivé. L’éditeur SQL et le run_query de l’agent IA s’exécutent en tant qu’utilisateur ClickHouse en lecture seule propre à l’organisation, dont la politique de lignes applique l’isolation des tenants dans le moteur. Les déploiements mono-tenant démarrent correctement avec la valeur dev intégrée ; avant de provisionner une seconde organisation, vous DEVEZ définir une valeur forte et stable, car la CLI agenteye-orgctl org create refuse de s’exécuter avec la valeur dev intégrée. La faire pivoter orpheline l’utilisateur ClickHouse de chaque organisation jusqu’au prochain démarrage qui les re-provisionne automatiquement. Gardez-la secrète et inchangée entre les réplicas. Le provisionnement des organisations est réservé aux opérateurs ; voir Organisations (multi-tenancy) ci-dessous. |
DEFAULT_ORG_NAME | Non | Default | Nom d’affichage initialisé pour l’organisation par défaut intégrée. Initialisation au premier démarrage uniquement, et uniquement tant que l’organisation conserve son identité générique fraîchement migrée, appliquée au démarrage, puis ignorée. Une fois que vous renommez l’organisation (agenteye-orgctl org rename), le renommage fait autorité et cette variable d’environnement n’a plus aucun effet. |
DEFAULT_ORG_SLUG | Non | default | Slug d’URL pour l’organisation par défaut intégrée, le chemin du tableau de bord où elle réside (/<slug>/…). Mêmes sémantiques de premier démarrage uniquement / état initial que DEFAULT_ORG_NAME. Doit comporter 1 à 40 caractères alphanumériques minuscules avec des tirets internes simples et ne pas être un mot réservé ; une valeur invalide est ignorée (l’organisation conserve default). Permet à une installation mono-tenant de se présenter par ex. comme /acme au lieu de /default sans aucune étape CLI post-déploiement. |
RUST_LOG | Non | info | Verbosité des logs (debug, warn, error, agenteye_server=trace) |
EVALUATOR_ENDPOINT | Non | aucun | URL de base de votre service d’évaluation (ex. http://evaluator:9000). Si non défini, l’intégralité du pipeline d’évaluation est sans effet ; aucune ligne de queue n’est écrite, aucun worker ne s’exécute. Voir Suite d’évaluation. |
EVALUATOR_TOKEN | Non | aucun | Envoyé en tant que Authorization: Bearer <token> à l’évaluateur. Doit être égal à la valeur avec laquelle le service d’évaluation est configuré. Optionnel uniquement si votre évaluateur est configuré sans token. |
EVALUATOR_WORKERS | Non | 2 | Concurrence : nombre de tâches worker par instance de serveur qui dispatche les évaluations. Sûr à exécuter sur plusieurs serveurs à mise à l’échelle horizontale. |
EVALUATOR_CLAIM_BATCH | Non | 4 | Nombre maximum d’évaluations qu’un seul worker revendique par tick. Les lots sont dispatchés de façon concurrente, donc la concurrence totale sur votre endpoint d’évaluation est EVALUATOR_WORKERS × EVALUATOR_CLAIM_BATCH. |
EVALUATOR_POLL_IDLE_SECS | Non | 2 | Durée de sommeil d’un worker entre les tentatives de dispatch lorsqu’aucune évaluation n’est en attente. |
EVALUATOR_POLLING_INTERVAL_SECS | Non | 10 | Cadence de repli finale (en secondes) pour les sondages GET /evaluate/{id} lorsque l’évaluateur ne retourne pas de next_poll_secs par réponse et n’annonce pas de default_poll_interval_secs via GET /config. |
EVALUATOR_REQUEST_TIMEOUT_MS | Non | 30000 | Timeout par requête HTTP vers l’évaluateur (en millisecondes). |
EVALUATOR_MAX_ATTEMPTS | Non | 5 | Après autant de tentatives échouées, une évaluation est enregistrée comme error terminal (ou timeout si les échecs étaient des timeouts de requête). |
EVALUATOR_CONFIG_REFRESH_SECS | Non | 300 (5 min) | Fréquence à laquelle le serveur re-récupère GET /config depuis l’évaluateur. |
EVALUATOR_MAX_POLL_DURATION_SECS | Non | 3600 (1 h) | Temps d’horloge murale maximum pendant lequel une session peut rester dans la queue de sondage avant qu’AgentEye la termine en timeout. Protège contre un évaluateur qui retourne indéfiniment pending. |
ALERT_WORKERS | Non | 1 | Concurrence : nombre de tâches worker par instance de serveur qui évaluent les règles d’alerte. Voir Alertes. |
ALERT_CLAIM_BATCH | Non | 16 | Nombre maximum d’alertes qu’un seul worker revendique par tick. |
ALERT_POLL_IDLE_SECS | Non | 5 | Durée de sommeil d’un worker d’alertes lorsque la queue est vide. |
ALERT_REQUEST_TIMEOUT_MS | Non | 15000 | Timeout d’évaluation par déclenchement (requêtes ClickHouse + HTTP de canal sortant). |
ALERT_MAX_ATTEMPTS | Non | 5 | Nombre d’échecs transitoires consécutifs avant qu’une alerte soit replanifiée à sa cadence normale plutôt qu’avec un backoff exponentiel. |
AUDIT_WORKERS | Non | 1 | Concurrence : nombre de tâches worker par instance de serveur qui exécutent des audits. Voir Audits. |
AUDIT_CLAIM_BATCH | Non | 1 | Nombre maximum d’audits dus qu’un seul worker revendique par tick. Une investigation agentique est une longue boucle, d’où le défaut à 1. |
AUDIT_POLL_IDLE_SECS | Non | 30 | Durée de sommeil d’un worker d’audits lorsqu’aucun audit n’est dû. |
AUDIT_REQUEST_TIMEOUT_MS | Non | 30000 | Timeout par requête de politique vers ClickHouse (en millisecondes). |
AUDIT_LLM_TIMEOUT_MS | Non | 1440000 | Timeout pour l’appel d’investigation agentique au service d’assistant IA. Une boucle d’agent complète s’exécute pendant plusieurs minutes ; gardez-le AU-DESSUS du propre AGENTEYE_AUDIT_TIMEOUT_MS de l’agent pour que l’agent retourne ses conclusions partielles avant que le serveur abandonne. |
AUDIT_MAX_ATTEMPTS | Non | 5 | Nombre d’échecs transitoires consécutifs avant qu’un audit soit replanifié à sa cadence normale plutôt qu’avec un backoff exponentiel. |
AGENTEYE_AGENT_URL / AGENTEYE_AGENT_TOKEN | Non | — | L’investigation agentique de l’audit appelle le service agent d’assistant IA, réutilisant la même connexion que l’assistant — définissez donc ces deux variables sur le serveur également (les manifestes/compose fournis le font). Les deux définis ⇒ les audits exécutent l’investigation IA ; l’un ou l’autre non défini ⇒ les audits s’exécutent en mode politique uniquement (la passe de politique SQL déterministe s’exécute quand même), quel que soit le flag llm_enabled par audit. L’agent doit également avoir un LLM configuré — voir assistant.md. |
AGENTEYE_AUDIT_* et tous optionnels :
| Variable | Défaut | Signification |
|---|---|---|
AGENTEYE_AUDIT_MAX_STEPS | 200 | Nombre maximum de tours d’agent par investigation. |
AGENTEYE_AUDIT_TIMEOUT_MS | 1200000 | Temps d’horloge murale pour une investigation (20 min). Doit rester en dessous du AUDIT_LLM_TIMEOUT_MS du serveur. |
AGENTEYE_AUDIT_MAX_CONCURRENCY | 1 | Investigations concurrentes par pod agent (séparé du budget de l’assistant de chat). |
AGENTEYE_AUDIT_SANDBOX_TIMEOUT_MS / _MEM_MB / _CPU_SECS / _OUTPUT_MAX_BYTES / _SCRIPT_MAX_BYTES | 20000 / 768 / 10 / 64000 / 64000 | Limites par script pour le sandbox bubblewrap. |
clone() — définissez seccompProfile: Unconfined (k8s) ou security_opt: [seccomp:unconfined] (compose) sur l’agent. Lorsque le noyau du nœud désactive les espaces de noms utilisateurs non privilégiés (ex. certaines images GKE COS), le preflight du sandbox échoue et l’auditeur se dégrade automatiquement en mode SQL uniquement — pas d’erreur, juste un sandbox_available: false sur le /health de l’agent.
Démarrer
DéfinissezDATABASE_URL dans votre environnement, puis transmettez-le au conteneur :
Vérification de l’état
/health pour les sondes de liveness et /ready pour les sondes de readiness / d’équilibreur de charge. /ready vérifie les dépendances essentielles sans lesquelles le serveur ne peut pas fonctionner (Postgres + ClickHouse), donc un serveur en cours d’exécution mais incapable d’atteindre sa base de données est retiré de la rotation et apparaît comme NotReady ; Redis est rapporté mais ne fait jamais échouer la readiness. Sur les manifestes Kubernetes fournis, la sonde de readiness pointe déjà sur /ready et la liveness reste sur /health. Voir enterprise-docs/health-monitoring.md pour l’image complète, y compris les alertes Slack optionnelles pour les défaillances de pods Kubernetes.
URL du lien magique email
Les emails de connexion OTP contiennent un bouton ouvrir le tableau de bord en un clic. En cliquant dessus, l’utilisateur atterrit sur/login?token=<code>&email=<address> ; le tableau de bord échange cette paire contre une session et redirige vers l’application, sans ressaisie manuelle du code. Le serveur résout l’origine du tableau de bord utilisée pour construire le lien en trois niveaux :
- En-tête
X-AgentEye-Dashboard-Url: défini automatiquement par le proxy/api/auth/otp/requestdu tableau de bord depuis sa propre origine publique. Dans un déploiement à même origine (serveur et tableau de bord partagent un hôte derrière un seul ingress qui transmet les en-têtes proxy), aucune configuration n’est requise. - Variable d’environnement
DASHBOARD_URL: définissez-la si votre tableau de bord est accessible sur une origine différente de celle que voit l’endpoint de requête OTP du serveur (séparationapi.example.com/app.example.com), ou si votre ingress ne propage pas l’hôte public dans le pod tableau de bord (de sorte querequest.nextUrl.originrésoudrait sinon vers une adresse générique comme0.0.0.0:3000). Exemple :DASHBOARD_URL=https://app.example.com. - Par défaut :
https://app.befailproof.ai, utilisé uniquement si aucun des cas ci-dessus n’est présent.
https://* et de loopback (http://localhost*, http://127.0.0.1*) sont acceptées, et les adresses de liaison génériques (0.0.0.0, [::]) sont rejetées même avec le schéma https://. Tout le reste passe au niveau 2.
Définissez-le sur un cluster en cours d’exécution en une seule commande ; pas de fichier, pas de reconstruction kustomize :
kustomize build | kubectl apply ultérieur contre l’overlay l’effacera sauf si vous ajoutez la même variable d’environnement au patch server-env.yaml de votre overlay.
Tableau de bord
Récupérer l’image
Variables d’environnement
| Variable | Requise | Défaut | Description |
|---|---|---|---|
AGENTEYE_SERVER_URL | Oui | aucun | URL de base du serveur, ex. http://localhost:8080 |
AGENTEYE_API_KEY | Oui | aucun | Clé API que le tableau de bord utilise pour s’authentifier auprès du serveur. Nécessite toutes les permissions (clé admin recommandée). |
AE_LOG_LEVEL | Non | info | Verbosité des logs côté serveur : debug, info, warn, error. Définissez sur debug pour voir les lignes de requête/réponse en amont et les traces de validation de session lors du diagnostic de problèmes. |
AE_LOG_JSON | Non | auto | 1 force la sortie JSON par ligne ; 0 force la sortie lisible par l’humain. Si non défini, JSON est activé automatiquement si NODE_ENV=production. JSON est recommandé en production pour que les logs soient analysés proprement avec jq ou un agrégateur de logs. |
AE_ANALYTICS_DISABLED | Non | aucun | Définissez sur 1/true pour désactiver la télémétrie anonyme d’utilisation du produit du tableau de bord. Voir Télémétrie et confidentialité ci-dessous. |
REDIS_URL | Non | aucun | Backend de cache partagé optionnel, ex. redis://redis:6379/0. Lorsqu’il est défini, le tableau de bord met en cache les résultats de validateSession() entre les réplicas et partage le cache de récupération Next.js pour les routes proxy d’agrégat de latence et de liste d’environnements. Les limites de débit des requêtes et vérifications OTP côté edge utilisent également Redis lorsqu’il est présent (échouant ouvertes si Redis est inaccessible ; la limite côté serveur est le garde-fou de sécurité). Voir Redis (cache optionnel) ci-dessous. |
AGENTEYE_AGENT_URL | Non | aucun | URL de base du service agent d’assistant IA optionnel, ex. http://agent:9100. Laissez-le non défini pour masquer entièrement l’assistant : aucune bulle d’assistant n’apparaît dans le tableau de bord. Voir enterprise-docs/assistant.md. |
AGENTEYE_AGENT_TOKEN | Non | aucun | Secret partagé que le tableau de bord présente au service agent. Doit correspondre à l’AGENTEYE_AGENT_TOKEN configuré sur l’agent. Voir enterprise-docs/assistant.md. |
Démarrer
Télémétrie et confidentialité
Le tableau de bord envoie des analyses d’utilisation anonymes du produit au service d’analyse d’Exosphere (PostHog) : les pages du tableau de bord consultées et quelques actions de l’interface utilisateur comme la création d’une clé API ou la réévaluation d’une session. Ce signal d’utilisation informe la priorisation des fonctionnalités.- Aucune donnée d’agent, de session ou d’événement ne quitte jamais votre infrastructure. Seule l’utilisation de l’interface du tableau de bord est rapportée. Les URL des pages sont dépouillées de leurs identifiants avant l’envoi, et les opérateurs ne sont identifiés que par un identifiant interne opaque, jamais par email.
- La télémétrie est activée par défaut. Pour la désactiver complètement, définissez
AE_ANALYTICS_DISABLED=1sur le conteneur du tableau de bord et redémarrez. - Les analyses sont envoyées vers le propre chemin
/ingestdu tableau de bord, que le tableau de bord relaie en proxy inverse vers PostHog (https://us.i.posthog.com). Garder les requêtes en first-party signifie que les bloqueurs de publicité des navigateurs ne les suppriment pas. Le conteneur du tableau de bord a besoin d’un accès sortant vers PostHog ; s’il est bloqué, la télémétrie ne fait silencieusement rien et le tableau de bord n’est pas affecté.
Assistant IA (optionnel)
Un assistant IA intégré au tableau de bord permet à votre équipe de poser des questions sur les données de leurs agents en langage naturel (résumer des sessions, rédiger du SQL pour l’éditeur/queries, et transformer des requêtes sauvegardées en tuiles de tableau de bord) sans quitter le tableau de bord. Il fonctionne comme un conteneur agent interne séparé (basé sur le Claude Agents SDK) que seul le tableau de bord peut atteindre, et reste désactivé jusqu’à ce que vous configuriez un endpoint LLM.
Pour l’activer, définissez sur le service agent une connexion LLM (Portkey via PORTKEY_API_KEY + un slug de catalogue de modèles AGENTEYE_AGENT_MODEL=@<slug>/<model>, Anthropic direct via ANTHROPIC_API_KEY, une autre passerelle via ANTHROPIC_BASE_URL, ou Bedrock/Vertex), une clé de données dédiée, et un AGENTEYE_AGENT_TOKEN partagé correspondant au tableau de bord. Les utilisateurs du tableau de bord ont également besoin de la permission agent:use.
Pour la clé de données de l’assistant, vous n’avez rien à créer manuellement : choisissez un secret aléatoire, définissez-le comme AGENTEYE_API_KEY sur l’agent et comme AGENT_API_KEY sur le server, et le serveur l’initialise au démarrage avec un ensemble de permissions fixes. Son accès aux données est en lecture seule (events:read, evaluations:read, dashboards:read, queries:read), et il détient en outre des portées d’authoring soumises à approbation (dashboards:write, queries:write, queries:run) pour qu’il puisse rédiger et valider des requêtes sauvegardées et construire des tuiles de tableau de bord au nom de l’utilisateur ; tout le SQL s’exécute quand même via le rôle ClickHouse en lecture seule de l’organisation, ce qui élargit ce que l’assistant peut créer, pas les données auxquelles il peut accéder. Les portées sont fixes dans le code et ne peuvent pas être élargies par configuration. Cette clé est protégée ; elle ne peut pas être désactivée ou régénérée via l’API, uniquement pivotée en changeant la valeur et en redémarrant. Ne réutilisez jamais la clé admin/tableau de bord pour cela.
La configuration complète, la référence complète des variables d’environnement, les options de télémétrie et le modèle de sécurité sont dans enterprise-docs/assistant.md.
ClickHouse (store analytique requis)
ClickHouse maintient la réactivité de vos tableaux de bord à des volumes d’événements élevés et permet à l’éditeur SQL/queries de joindre événements, évaluations et sessions dans un seul store. Il est le store canonique requis pour chaque événement ingéré, chaque résultat d’évaluation terminal, et les agrégats par session dérivés. PostgreSQL contient les tables d’état relationnel/mutable (api_keys, users, otp_codes, evaluation_jobs, dashboards, saved_queries) ; la surface analytique vit dans ClickHouse pour que les rollups du tableau de bord et vos propres requêtes SQL puissent l’analyser et la joindre nativement, sans allers-retours entre bases de données. Le serveur refuse de démarrer sans CLICKHOUSE_URL.
Schéma
Trois objets ClickHouse sont créés au démarrage du serveur, tous idempotents (CREATE IF NOT EXISTS) :
agenteye.events:ReplacingMergeTree(ingested_at), partitionné partoYYYYMM(ts), ordonné par(session_id, ts, dedup_key). Les insertions dupliquées (nouvelles tentatives du collecteur) se réduisent à une seule ligne lors de la fusion ; le serveur calcule undedup_keySHA-256 déterministe pour chaque événement afin que les nouvelles tentatives soient sûres.agenteye.evaluations:ReplacingMergeTree(ingested_at), partitionné partoYYYYMM(finished_at), ordonné par(session_id, finished_at, dedup_key). Écrit une fois par résultat d’évaluation terminal par le pipeline d’évaluation. Même modèle de clé de déduplication queevents.agenteye.agent_sessions: une VUE suragenteye.events, pas une table physique. Chaque colonne est dérivée (started_at = min(ts),last_event_at = max(ts),ended_at = max(if event_type='agent_end', ts, NULL),event_count = count(), etc.). Pas d’upsert par événement ni de backfill séparé ; la vue reflète automatiquement ce qui est dansevents.
analytics.evaluations / analytics.sessions, le serveur crée également une base de données ClickHouse analytics avec des vues sur les tables agenteye.* ; analytics.events, analytics.evaluations, analytics.agent_sessions, analytics.sessions se résolvent tous correctement.
Configuration
Le docker-compose fourni etdeploy/base/clickhouse/ embarquent un service ClickHouse optimisé pour la charge de travail d’AgentEye :
- 2 Gio demandés / 4 Gio limite de mémoire dans l’overlay de base fourni (dimensionné pour tenir dans de petits nœuds POC/staging) ; les clients en production devraient augmenter — le plancher recommandé est 2c / 4Gi demandé, 6c / 8Gi limite.
max_server_memory_usage_to_ram_ratio=0.9 - Cache de marques de 5 Gio + cache non compressé de 8 Gio
background_pool_size=16,background_merges_mutations_concurrency_ratio=2- MergeTree :
parts_to_throw_insert=3000,parts_to_delay_insert=1500,non_replicated_deduplication_window=1000 local_io_method=auto(io_uring sur les noyaux supportés)fsync_metadata=0: acceptable grâce à l’ingest au-moins-une-fois + déduplication ReplacingMergeTreequery_logactivé avec TTL de 30 jours ;query_thread_logsupprimé (coûteux à fort QPS)max_execution_time=30pour les requêtes côté utilisateur- PVC de 100 Gio au template StatefulSet (les overlays clients DEVRAIENT le remplacer par une classe de stockage SSD rapide pour la production)
Sauvegardes
Votre jeu de données complet est capturé chaque nuit dans une seule archive restaurable, de sorte qu’une perte de cluster ou de stockage est récupérable. ClickHouse est sauvegardé automatiquement par le CronJob quotidienagenteye-backup, qui dump à la fois PostgreSQL et ClickHouse en une seule passe. ClickHouse est lu via son API HTTP : agenteye.events et agenteye.evaluations sont dumpés au format natif ClickHouse (les vues et politiques de lignes sont recréées par le serveur au démarrage, donc les données des tables constituent le tableau complet) et regroupés avec le dump Postgres dans une seule archive compressée téléchargée vers votre stockage objet.
Le bucket de destination et les identifiants cloud sont configurés par overlay. Voir la section Sauvegardes de enterprise-docs/kubernetes-deployment.md pour la configuration de téléchargement et les étapes de restauration.
Redis (cache optionnel)
Redis est un backend de cache partagé et de limitation de débit optionnel utilisé par le serveur et le tableau de bord. Avec Redis déployé etREDIS_URL défini sur les deux services :
- Le serveur met en cache les lookups de clés API authentifiées, les listes
/events/environments+/evaluations/environments, le rollup/events/latency_aggregate(la requête la plus lourde que le tableau de bord interroge), la liste/sessions, et bascule la limitation de débit des requêtes OTP d’unCOUNT(*)Postgres vers unINCR + EXPIRERedis. - Le tableau de bord met en cache les résultats de
validateSession()pour que les 10 à 20 appels API authentifiés qu’un chargement de page typique émet partagent tous une seule vérification de session en amont. Il limite également le débit des requêtes OTP et des vérifications OTP au niveau edge du tableau de bord.
Err dans un timeout borné et l’appelant revient à la source de vérité (Postgres sur le serveur, le serveur Rust en amont sur le tableau de bord). La limitation de débit OTP revient au chemin COUNT(*) Postgres sur le serveur (la propriété de sécurité est préservée) ; la limite OTP edge du tableau de bord échoue ouverte tandis que la limite côté serveur tient toujours. L’indisponibilité de Redis dégrade la latence, pas la correction.
Configuration
Le bundle docker-compose inclut déjà un service Redis et câbleREDIS_URL=redis://redis:6379/0 dans le serveur et le tableau de bord. Pour utiliser un Redis externe, définissez REDIS_URL vers votre endpoint et retirez le service redis du fichier compose.
Mémoire et persistance
L’image Redis fournie s’exécute avec--appendonly yes --appendfsync everysec --maxmemory 256mb --maxmemory-policy allkeys-lru. La persistance AOF signifie que le cache survit aux redémarrages des conteneurs ; everysec est le bon équilibre durabilité/performances car perdre la dernière seconde d’écritures cache est sans conséquence. L’éviction LRU plafonne la croissance mémoire.
Quand NE PAS déployer Redis
- Développement/QA sur instance unique. Les caches en mémoire du serveur seul offrent la plupart des bénéfices par réplica ; Redis ajoute le partage inter-réplicas dont les configurations mono-instance n’ont pas besoin.
- Installations isolées (air-gapped) où le coût opérationnel de faire tourner un service supplémentaire dépasse le gain en latence.
Docker Compose (recommandé)
Undocker-compose.yml est disponible dans le dépôt agenteye-enterprise/releases. Il démarre Postgres, le serveur et le tableau de bord avec une seule commande.
.env :
Paramètres opérationnels
Un petit ensemble de réglages opérationnels qui étaient autrefois fixés par des variables d’environnement sont maintenant modifiables par organisation depuis la page/<org>/settings du tableau de bord ; chaque organisation configure les siens. Les modifications prennent effet en quelques secondes, sans redémarrage ni redéploiement.
| Paramètre | Variable d’environnement de démarrage | Ce qu’il contrôle |
|---|---|---|
| Connexions autorisées | ALLOWED_EMAILS | Emails (ou jokers *@domain.com) autorisés à recevoir un OTP et à être ajoutés comme utilisateurs |
| Permissions utilisateur par défaut | DEFAULT_USER_PERMISSIONS | Tokens de permission séparés par des virgules présélectionnés lorsqu’un administrateur ouvre + nouvel utilisateur. Chaque token doit être l’une des chaînes listées sous Permissions des clés API. Par défaut, le préréglage standard : accès en lecture seule plus les actions quotidiennes d’astreinte (déclencher des réévaluations, exécuter des requêtes, acquitter des incidents, utiliser l’assistant). |
| Durée de vie de la session | SESSION_TTL_SECS | Durée pendant laquelle une connexion au tableau de bord reste valide avant une nouvelle authentification. Le tableau de bord re-vérifie la session en amont toutes les 5 secondes, donc une mise à jour des permissions sur /<org>/users prend effet à la prochaine requête de l’utilisateur concerné, sans reconnexion. |
| Durée de vie du code à usage unique | OTP_TTL_SECS | Durée pendant laquelle un OTP / lien magique reste utilisable |
| Canaux de notification d’alerte | ALERTS_ENABLED_CHANNELS | Liste séparée par des virgules des types de canaux que le dispatcher d’alertes est autorisé à utiliser : email, slack, webhook. La configuration par alerte est toujours créée sur /<org>/alerts/<id>, mais le dispatcher filtre chaque livraison sortante à travers cet ensemble ; un canal désactivé ici court-circuite avec une ligne d’audit skipped_disabled. Le canal dashboard (l’insertion d’audit locale) est toujours autorisé. Par défaut, les trois sont activés. |
Fonctionnement du démarrage
Les paramètres sont stockés par organisation dansorg_settings. Au premier démarrage, le serveur alimente les lignes manquantes de l’organisation par défaut à partir de la variable d’environnement correspondante (ou d’une valeur par défaut raisonnable si la variable d’environnement n’est pas définie). Après cela, la valeur stockée est la source de vérité et la variable d’environnement est ignorée ; modifier la variable d’environnement lors d’un redémarrage ultérieur n’affectera pas la valeur d’une organisation active, et les organisations supplémentaires démarrent avec des valeurs par défaut et configurent les leurs.
Cela signifie :
- Pour un nouveau déploiement, définissez les variables d’environnement comme indiqué ci-dessus et l’organisation par défaut les lira au premier démarrage.
-
Pour modifier une valeur ultérieurement, connectez-vous au tableau de bord et modifiez-la sous
/<org>/settings. La modification s’applique en quelques secondes sur tous les réplicas du serveur ; aucun redémarrage n’est nécessaire. -
Une ligne de log au démarrage enregistre ce qui a été initialisé vs. ce qui était déjà présent, pour vous permettre de confirmer que le démarrage a pris effet :
Sémantiques de connexion entre organisations
Une session et un OTP sont globaux à l’utilisateur, pas à une seule organisation, donc deux règles conccilient les paramètres par organisation au moment de la connexion :- Durée de vie de la session / OTP : la durée de vie la plus stricte (la plus courte) parmi les organisations auxquelles l’utilisateur appartient l’emporte.
- Connexions autorisées : la porte fait un OU de la liste blanche de chaque organisation avec l’appartenance à l’organisation : un utilisateur peut demander un OTP si la liste blanche de n’importe quelle organisation admet son email ou s’il est déjà membre de n’importe quelle organisation.
Permissions
L’accès à une page/<org>/settings est conditionné par deux permissions :
settings:read: voir la page et les valeurs actuelles.settings:write: sauvegarder les modifications.
ADMIN_EMAIL) obtient les deux automatiquement avec toutes les autres permissions. Accordez-les à d’autres utilisateurs depuis /<org>/users selon les besoins.
Organisations (multi-tenancy)
Un seul déploiement peut servir plusieurs organisations (tenants) isolées ; chaque ligne de données appartient exactement à une organisation et l’isolation est appliquée dans le moteur de base de données. Une installation mono-tenant n’a rien à faire ici ; toutes les données vivent dans une organisationdefault intégrée. (Vous pouvez donner à cette organisation un nom plus convivial et un slug d’URL, pour qu’elle vive par ex. à /acme au lieu de /default, en définissant DEFAULT_ORG_NAME / DEFAULT_ORG_SLUG avant le premier démarrage, ou en la renommant à tout moment avec agenteye-orgctl org rename.)
Le provisionnement des tenants est réservé aux opérateurs. Les organisations et leurs membres sont créés et gérés avec la CLI agenteye-orgctl, qui est embarquée dans l’image du serveur (aux côtés de agenteye-server) et s’exécute dans le pod serveur existant ; il n’y a pas de pod/Job séparé, pas d’API HTTP, et pas de bouton dans le tableau de bord. Elle réutilise DATABASE_URL, CLICKHOUSE_URL et ORG_CH_SECRET du serveur.
org create | list | rename | delete | purge et member add | list | update | remove, avec les ensembles de permissions intégrés admin, standard et read-only. Les membres ajoutés reçoivent un OTP lors de leur première connexion au tableau de bord.
Avant de créer une deuxième organisation : définissez un ORG_CH_SECRET fort et stable (la commande org create refuse de s’exécuter avec la valeur dev intégrée par défaut) et assurez-vous que Postgres est en version 15+. Inchangé : les clés API par organisation sont toujours créées dans le tableau de bord/l’API par les membres de l’organisation ; seul le cycle de vie des organisations et des membres a été déplacé vers la CLI. Référence complète des commandes et exemple détaillé : enterprise-docs/tenant-management.md.
Remplissage de la fenêtre de contexte
Chaque événementmodel_response affiche une pastille de remplissage de contexte — les tokens d’entrée plus les tokens de sortie en pourcentage de la fenêtre de contexte de ce modèle. Les plages sont healthy (0–24 %), watch (25–49 %), compacting (50–74 %), et reset context (75–100 %). AgentEye résout automatiquement les identifiants de modèles courants, donc aucune configuration initiale n’est requise.
Chaque modèle qu’une organisation envoie apparaît sous Paramètres → fenêtres de contexte de modèle. Les utilisateurs avec settings:write peuvent remplacer sa fenêtre ou ajouter un modèle privé/proxy (0–1 000 000 tokens) ; 0 signifie « inconnu » et supprime la pastille. Les modifications s’appliquent aux événements nouvellement ingérés. Les utilisateurs avec settings:read peuvent consulter la liste.
Les nouveaux événements reçoivent le remplissage à partir du moment où vous effectuez la mise à niveau. Pour également renseigner les événements historiques (et la liste par modèle) pour un déploiement existant, exécutez le backfill ponctuel — il est embarqué dans l’image du serveur (comme agenteye-orgctl) et s’exécute dans le pod serveur existant :
DATABASE_URL / CLICKHOUSE_URL / REDIS_URL depuis le pod. Ré-exécutez-le après avoir modifié les fenêtres de modèles si vous souhaitez que les événements existants soient recalculés.
Considérations pour la production
- Postgres : Utilisez un service Postgres géré ou une instance dédiée avec des sauvegardes régulières. Le
DATABASE_URLsupporte tous les paramètres libpq standard, y comprissslmode=requirepour les connexions chiffrées. - TLS : Placez le serveur et le tableau de bord derrière un proxy inverse (nginx, Caddy, Traefik) qui termine TLS.
- Pare-feu : Le port du serveur (par défaut 8080) ne doit être accessible que depuis les machines collectrices et l’hôte du tableau de bord, pas depuis l’internet public.
- Clé admin : Définissez
ADMIN_KEYavec un secret aléatoire fort. Après l’initialisation, créez des clés dédiées à portée limitée pour les collecteurs et le tableau de bord plutôt que d’utiliser la clé admin partout. - Tags d’images : Épinglez à la version dans vos manifestes de release (par exemple,
server:v0.0.1-beta.48) en production plutôt qu’un tag flottant pour éviter les mises à niveau non intentionnelles. Les builds beta actuels sont publiés sousbeta-latest;latestest réservé aux versions stables. - Surveillance de l’état : Sur Kubernetes, la sonde de readiness utilise
/ready(accessibilité Postgres + ClickHouse) tandis que la liveness reste sur/health. Pour des alertes Slack à l’échelle de la flotte sur la disponibilité d’AgentEye lui-même, activez l’add-on Robusta opt-in ; voir enterprise-docs/health-monitoring.md.
Tags d’images disponibles
| Tag | Description |
|---|---|
latest | Dernière version stable |
beta-latest | Dernière version pré-release (bêta) |
v<version> | Version épinglée, ex. v0.0.1-beta.48 (recommandé pour la production) |

