{"status":"ok","timestamp":"2026-10-19T03:41:16.981920+00:00","architecture":"Multi-Agent System (MAS) with Separation of Cognitive and Executive Concerns","total_components":11,"cognitive_count":5,"deterministic_count":6,"cognitive_agents":[{"id":"remediation","name":"RemediationAgent","layer":"Coordination & Action Planning","type":"cognitive","type_label":"Cerveau Cognitif (LLM)","role":"remediation","status":"ONLINE","mission":"Évalue le rayon d'impact systémique (Blast Radius 0-5), analyse l'arbre de causalité et formule l'intention de remédiation (ActionIntent).","fsm_trigger":"Exécuté systématiquement lors de l'état FSM [PLANNED].","anti_bias_rule":"Principe Anti-Biais strict : les spécialistes se limitent aux faits, seul le RemediationAgent évalue la proportionnalité de l'action.","active_model":"openrouter/nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free","provider":"openrouter","fallback_models":["openrouter/google/gemma-4-31b-it:free","openrouter/google/gemma-4-26b-a4b-it:free","openrouter/nvidia/nemotron-3-super-120b-a12b:free","openrouter/openrouter/free","openrouter/liquid/lfm-2.5-2.6b:free"],"override_env":"LLM_MODEL_REMEDIATION","temperature":0.0,"max_tokens":1024,"timeout_seconds":30,"reasoning_mode":"Chain-of-Thought délibéré (<think> tags filtrés via regex)","selection_rationale":"Raisonnement délibéré pas-à-pas pour évaluer le rayon d'impact (Blast Radius 0-5), l'arbre des dépendances et la réversibilité avant toute mutation en production.","input_contract":"Diagnosis (issue, root_cause, confidence, evidence)","output_contract":"ActionIntent (action, target, rationale, declared_blast_radius)","dependencies":["Redis (:6379) semantic lock & quotas","PolicyEngine (OPA gate)","WORM Trust Ledger"],"allowed_tools":["Aucun (Isolation judiciaire : pas de Tool Calling direct)"],"blast_radius_limit":"0 à 5 (au-delà de 2 -> Veto PolicyEngine obligatoire)","worm_ledger":true,"promql_metric":"agentic_ops_llm_requests_total{role=\"remediation\"}","failure_fallback":"Bascule transparente sur FallbackLLMAdapter (5 modèles gratuits), puis repli CIRCUIT_BREAKER_FALLBACK si quota épuisé."},{"id":"infra","name":"InfraSpecialist","layer":"Diagnostic Infrastructure & SRE","type":"cognitive","type_label":"Cerveau Cognitif (LLM)","role":"infra","status":"ONLINE","mission":"Investigue les anomalies d'infrastructure, conteneurs Docker, saturation mémoire OOM et limites PostgreSQL.","fsm_trigger":"Activé quand \"INFRA\" est présent dans le risk_id (ex: INFRA_OOM_KILLED).","anti_bias_rule":"Se limite au constat factuel de diagnostic (Diagnosis). Ne propose aucune action de remédiation.","active_model":"openrouter/google/gemma-4-31b-it:free","provider":"openrouter","fallback_models":["openrouter/google/gemma-4-26b-a4b-it:free","openrouter/nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free","openrouter/nvidia/nemotron-3-super-120b-a12b:free","openrouter/openrouter/free","openrouter/liquid/lfm-2.5-2.6b:free"],"override_env":"LLM_MODEL_INFRA","temperature":0.0,"max_tokens":1024,"timeout_seconds":30,"reasoning_mode":"Ingestion de contexte brut (fenêtre massive 256k tokens)","selection_rationale":"Fenêtre de contexte massive de 256 000 tokens permettant d'ingérer des dumps complets de logs Loki, journaux systemd et traces noyau sans aucune troncature.","input_contract":"SignalEnvelope (risk_id, signal_id, value, threshold, source)","output_contract":"Diagnosis (issue, root_cause, confidence, evidence)","dependencies":["Grafana Loki (:3100)","Docker socket (/var/run/docker.sock)","PostgreSQL (:5432)"],"allowed_tools":["CheckDockerContainer","CheckDatabaseHealth","QueryLokiLogs"],"blast_radius_limit":"0 (Lecture seule d'investigation)","worm_ledger":false,"promql_metric":"agentic_ops_llm_requests_total{role=\"infra\"}","failure_fallback":"Bascule sur FallbackLLMAdapter (5 modèles) ou repli sur DataSpecialist."},{"id":"data","name":"DataSpecialist","layer":"Diagnostic Qualité Données & Repli Universel","type":"cognitive","type_label":"Cerveau Cognitif (LLM)","role":"data","status":"ONLINE (MAS DEFAULT)","mission":"Vérifie l'intégrité des données tabulaires, les mutations de schémas Pandera et les dérives Evidently.","fsm_trigger":"Repli MAS par défaut : capture toute alerte sans préfixe 'MODEL' ou 'INFRA'.","anti_bias_rule":"Se limite au constat factuel de diagnostic (Diagnosis). Ne propose aucune action de remédiation.","active_model":"openrouter/google/gemma-4-26b-a4b-it:free","provider":"openrouter","fallback_models":["openrouter/google/gemma-4-31b-it:free","openrouter/nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free","openrouter/nvidia/nemotron-3-super-120b-a12b:free","openrouter/openrouter/free","openrouter/liquid/lfm-2.5-2.6b:free"],"override_env":"LLM_MODEL_DATA","temperature":0.0,"max_tokens":1024,"timeout_seconds":30,"reasoning_mode":"Mixture-of-Experts à faible latence et extraction Pydantic stricte","selection_rationale":"Plus de 80% des pannes MLOps proviennent des données. L'architecture MoE garantit un typage JSON Pydantic strict et un coût nul à la sous-seconde.","input_contract":"SignalEnvelope (risk_id, signal_id, value, threshold, source)","output_contract":"Diagnosis (issue, root_cause, confidence, evidence)","dependencies":["Rapports de dérive Evidently","Schémas de validation Pandera","PostgreSQL DWH"],"allowed_tools":["ValidatePanderaSchema","CheckDriftMetrics","QueryDatabase"],"blast_radius_limit":"0 (Lecture seule d'investigation)","worm_ledger":false,"promql_metric":"agentic_ops_llm_requests_total{role=\"data\"}","failure_fallback":"Bascule sur FallbackLLMAdapter (5 modèles gratuits)."},{"id":"model","name":"ModelSpecialist","layer":"Diagnostic Performance ML & Dérive de Concept","type":"cognitive","type_label":"Cerveau Cognitif (LLM)","role":"model","status":"ONLINE","mission":"Analyse les dégradations de F1-Score, baisses de performance et dérives de concept sur les classes rares.","fsm_trigger":"Activé quand \"MODEL\" est présent dans le risk_id (ex: MODEL_PERF_DEGRADATION).","anti_bias_rule":"Se limite au constat factuel de diagnostic (Diagnosis). Ne propose aucune action de remédiation.","active_model":"openrouter/nvidia/nemotron-3-super-120b-a12b:free","provider":"openrouter","fallback_models":["openrouter/google/gemma-4-31b-it:free","openrouter/google/gemma-4-26b-a4b-it:free","openrouter/nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free","openrouter/openrouter/free","openrouter/liquid/lfm-2.5-2.6b:free"],"override_env":"LLM_MODEL_MODEL","temperature":0.0,"max_tokens":1024,"timeout_seconds":30,"reasoning_mode":"Modèle statistique lourd 70B paramètres","selection_rationale":"Puissance statistique de 70 milliards de paramètres pour différencier une dérive de concept réelle P(Y|X) d'un bruit ponctuel d'entrées P(X) sur les classes rares.","input_contract":"SignalEnvelope (risk_id, signal_id, value, threshold, source)","output_contract":"Diagnosis (issue, root_cause, confidence, evidence)","dependencies":["MLflow Model Registry (:5001)","Prometheus metrics","Matrice de confusion BAAC"],"allowed_tools":["CheckMLflowModel","InspectConfusionMatrix","QueryPrometheusMetrics"],"blast_radius_limit":"0 (Lecture seule d'investigation)","worm_ledger":false,"promql_metric":"agentic_ops_llm_requests_total{role=\"model\"}","failure_fallback":"Bascule sur FallbackLLMAdapter (5 modèles gratuits)."},{"id":"chat","name":"WebChatCopilot","layer":"Interface Conversationnelle Opérateur","type":"cognitive","type_label":"Cerveau Cognitif (LLM)","role":"chat","status":"ONLINE","mission":"Assistance conversationnelle de l'opérateur SRE, interrogation du Grand Livre WORM et exécution des prompts MCP.","fsm_trigger":"Déclenché par l'opérateur via l'interface Web Chat (/chat) ou l'API POST /api/chat.","anti_bias_rule":"Interface d'information et d'assistance. Ne peut pas déclencher de mutations sans validation PolicyEngine.","active_model":"openrouter/google/gemma-4-31b-it:free","provider":"openrouter","fallback_models":["openrouter/google/gemma-4-26b-a4b-it:free","openrouter/nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free","openrouter/nvidia/nemotron-3-super-120b-a12b:free","openrouter/openrouter/free","openrouter/liquid/lfm-2.5-2.6b:free"],"override_env":"LLM_MODEL_CHAT","temperature":0.0,"max_tokens":1024,"timeout_seconds":30,"reasoning_mode":"Streaming conversationnel à latence sub-seconde (sans balises think)","selection_rationale":"Fluidité conversationnelle maximale et temps de réponse immédiat (TTFT ultra-rapide) pour le dialogue avec l'opérateur SRE.","input_contract":"ChatPayload (message, history)","output_contract":"ChatResponse (response, provider, model, latency_ms)","dependencies":["FastAPI Web UI (/chat)","WORM Trust Ledger","Catalogue 20 Prompts MCP"],"allowed_tools":["Exécution des 20 Prompts Cognitifs MCP en lecture seule"],"blast_radius_limit":"0 (Lecture seule conversationnelle)","worm_ledger":false,"promql_metric":"agentic_ops_llm_requests_total{role=\"chat\"}","failure_fallback":"Bascule sur FallbackLLMAdapter (5 modèles gratuits alternatifs)."}],"deterministic_components":[{"id":"circuit_breaker","name":"CircuitBreakerFallback","layer":"Sécurité & Résilience Ultime","type":"deterministic","type_label":"Garde-Fou Déterministe (0 Tokens)","role":"circuit_breaker","status":"ARMED","mission":"Filet de sécurité ultime protégeant le cluster lors des pannes de fournisseurs LLM, tempêtes de requêtes ou rate limits 429.","trigger_condition":"Déclenché quand le taux dépasse 50 req/h ou en cas d'erreurs 429/503 répétées.","zero_llm_rationale":"Appeler un LLM secondaire quand les APIs LLM saturent violerait le principe même du coupe-circuit. Le repli déterministe garantit la stabilité.","engine":"Python Pur Hardcodé (0 Tokens consommés)","isolation":"Classe Python in-memory synchrone","timeout":"Immédiat (0 ms)","input_contract":"Exception LLM ou compteur de requêtes dépassé","output_contract":"Diagnosis(issue='CIRCUIT_BREAKER_ACTIVE') + ActionIntent(action=CREATE_ISSUE)","dependencies":["CircuitBreaker class","Orchestrator FSM"],"blast_radius_limit":"0 (Action passive sans mutation)","promql_metric":"agentic_ops_circuit_breaker_status","security_guard":"Force l'action CREATE_ISSUE pour réveiller l'humain et bloque toute remédiation autonome."},{"id":"executor","name":"ActionExecutor","layer":"Actionneur d'Exécution Système","type":"deterministic","type_label":"Actionneur Déterministe (0 Tokens)","role":"executor","status":"ACTIVE (SANDBOXED)","mission":"Applique les mutations physiques sur l'infrastructure (docker restart, rollback de modèle, relance de pipelines Prefect).","trigger_condition":"Uniquement sur ActionIntent validé avec statut ALLOW par le PolicyEngine ou après quorum Slack HITL.","zero_llm_rationale":"Zero-Trust absolu : aucun modèle probabiliste ne doit détenir d'accès direct au shell ou aux mutations d'infrastructure.","engine":"Worker Subprocess Python Pur (0 Tokens)","isolation":"multiprocessing.Process avec PID isolé du daemon principal","timeout":"30 secondes dures (SIGTERM puis SIGKILL à 35s)","input_contract":"ActionIntent validé par PolicyEngine","output_contract":"ExecutionResult (status, exit_code, stdout, stderr, duration_ms)","dependencies":["Docker daemon (/var/run/docker.sock)","MLflow Client","Prefect API"],"blast_radius_limit":"Coupé à 2 sans approbation Slack ; max 5 sous quorum 2-man rule","promql_metric":"agentic_ops_actions_executed_total","security_guard":"Vérification stricte de whitelist des arguments, PID sandboxing et isolation complète."},{"id":"cac_collector","name":"CacPullCollector","layer":"Ingestion Télémétrique Réseau","type":"deterministic","type_label":"Capteur Réseau Déterministe (0 Tokens)","role":"cac_collector","status":"ONLINE (SOCKS5 MESH)","mission":"Sonde de télémétrie continue qui interroge périodiquement les 5 endpoints de jakatt/cac_mlops via Tailscale WireGuard.","trigger_condition":"Collecte périodique ou déclenchement à la demande sur GET /api/cac/snapshot.","zero_llm_rationale":"Le scraping réseau, le parsing JSON et le calcul de métriques sont du pur Data Engineering. Un LLM n'apporterait que coût et latence.","engine":"Client Asynchrone HTTP Python Pur (0 Tokens)","isolation":"Transport httpx asynchrone routé via SOCKS5 (127.0.0.1:1055)","timeout":"20 secondes par service (défaut 3.5s sur Render)","input_contract":"Requêtes HTTP GET sur Loki, Prometheus, MLflow, Prefect, Evidently","output_contract":"CacCollectedSnapshot (schéma Pydantic immuable)","dependencies":["Tailscale WireGuard Mesh (:1055)","jakatt/cac_mlops (100.117.99.62)"],"blast_radius_limit":"0 (Strictement 100% lecture seule GET)","promql_metric":"cac_mlops_pull_duration_seconds","security_guard":"Toutes les méthodes de mutation POST/DELETE sont physiquement bloquées dans l'adapter."},{"id":"slack_webhook","name":"SlackWebhookAgent","layer":"Portier Cryptographique HITL","type":"deterministic","type_label":"Portier Cryptographique (0 Tokens)","role":"slack_webhook","status":"ACTIVE (HMAC ENFORCED)","mission":"Réceptionne et valide cryptographiquement les clics d'approbation humaine Slack Block Kit (Approve / Reject).","trigger_condition":"POST /slack/interactive émis par les serveurs officiels Slack.","zero_llm_rationale":"Une vérification de signature cryptographique (HMAC-SHA256) et d'anti-rejeu ne doit comporter aucune incertitude probabiliste.","engine":"Garde-fou Cryptographique Python Pur (0 Tokens)","isolation":"Verrouillage transactionnel SQLite BEGIN IMMEDIATE dans approvals.db","timeout":"Fenêtre de tolérance anti-rejeu de 300 secondes","input_contract":"Payload JSON Slack chiffré + En-têtes X-Slack-Signature & X-Slack-Request-Timestamp","output_contract":"ApprovalDecision (status='approved' | 'rejected', approver_id, timestamp)","dependencies":["SLACK_SIGNING_SECRET","SQLite WAL /tmp/state/approvals.db"],"blast_radius_limit":"0 (Portier de validation)","promql_metric":"agentic_ops_slack_interactions_total","security_guard":"Rejet immédiat HTTP 401 si signature invalide ou timestamp dépassé."},{"id":"agent_tools","name":"8 Governed AgentTools","layer":"Sondes & Outils d'Investigation","type":"deterministic","type_label":"Sondes Déterministes (0 Tokens)","role":"agent_tools","status":"GOVERNED","mission":"Outils spécialisés (Docker, SQL, Pandera, MLflow) appelés par les spécialistes pour inspecter l'environnement.","trigger_condition":"Appelés via Tool Calling par les agents cognitifs durant la phase INVESTIGATING.","zero_llm_rationale":"Les outils sont les organes sensoriels de diagnostic ; ils exécutent du code Python borné et retournent des faits bruts.","engine":"Sondes Python Pures Sandboxées (0 Tokens)","isolation":"Sandboxing strict avec timeout OS","timeout":"15 secondes maximum par sonde","input_contract":"Paramètres typés Pydantic (ex: container_name, table_name, model_name)","output_contract":"Dictionnaire de faits bruts d'exécution","dependencies":["psycopg2","docker SDK","pandera","mlflow client"],"blast_radius_limit":"0 (Outils de diagnostic sans mutation)","promql_metric":"agentic_ops_tools_invocations_total","security_guard":"Exécution confinée avec interdiction des commandes système non prévues."},{"id":"mcp_gateway","name":"MCPServerGateway","layer":"Passerelle Protocolaire Ouverte","type":"deterministic","type_label":"Passerelle JSON-RPC (Délégué)","role":"mcp_gateway","status":"RUNNING (/mcp)","mission":"Expose les 8 outils gouvernés, 5 ressources et 20 prompts cognitifs aux IDEs et clients IA externes.","trigger_condition":"Connexions entrantes sur /mcp (stdio ou Server-Sent Events / SSE).","zero_llm_rationale":"La passerelle MCP est un pont d'interopérabilité passif. Son cerveau cognitif est celui de l'IDE client connecté (Claude, Cursor, etc.).","engine":"Serveur Protocolaire JSON-RPC 2.0 (Délégué au Client)","isolation":"Validation de schéma JSON-RPC et contrôle d'accès sur les permissions d'outils","timeout":"Géré par le transport HTTP/stdio du client","input_contract":"Requêtes JSON-RPC 2.0 (tools/call, resources/read, prompts/get)","output_contract":"Réponses conformes au protocole Model Context Protocol (MCP)","dependencies":["FastAPI SSE","FastMCP / mcp SDK","agentic_ops tools"],"blast_radius_limit":"Géré par les politiques de sécurité du PolicyEngine","promql_metric":"agentic_ops_mcp_requests_total","security_guard":"Validation stricte des paramètres JSON-RPC et contrôle d'autorisation."}]}