MARKY MD

4,207 people have felt the vibration

◆ Output Preview

Guide d'Architecture et Prompt Engineering

0. État Actuel de Notre Système

Ce qui existe déjà

Architecture modulaire (déjà en place) :

  • 15+ fichiers .md dans shared/prompts/ (numérotés 01-99)
  • 6 prompts agent-spécifiques dans shared/prompts/agents/
  • Système de chargement dynamique : load_system_prompt(exclude_patterns=...)
  • Factory pattern : create_agent(name, instructions, model, tools)
  • Filtrage manuel des tools : get_mcp_tools_by_names(["snow", "grafana"])
  • Workflows séquentiels avec gates d'eligibilité

Problèmes actuels

1. Duplication massive de contexte

  • 12.sre.md (enrichment) vs 16.sre_resolution.md (resolution) : 80% de duplication
  • Contexte Michelin (01.instructions.md) répété dans plusieurs compositions
  • Pour changer un comportement → modifier 2-4 fichiers différents

2. Scalabilité limitée

  • Ajouter un nouveau scénario = créer de nouveaux fichiers
  • Pas de template réutilisable
  • Risque d'incohérence entre scénarios similaires

1. Vision Cible

Principes d'Architecture (inspirés de Semantic Kernel, AutoGen, Alpha Berkeley)

Les grandes entreprises convergent vers :

  • Composition déclarative : assembler le contexte via configuration, pas via code
  • Context as versioned artifacts : blocs de contexte versionnés et testables
  • Skill registry : registre centralisé des capacités avec métadonnées
  • Single source of truth : un bloc = un fichier, pas de duplication
  • Lazy loading : charger uniquement le contexte nécessaire
  • Observabilité : traçabilité de ce qui est injecté dans chaque requête

C. Skill Registry pour MCP Tools

Distinction Importante

Concept Définition Usage
MCP (Model Context Protocol) Protocole d'échange Couche technique
Skill Capacité métier documentée Couche sémantique

Problème actuel : Trop d'investissement dans le protocole, pas assez dans la documentation des capacités.

Créer un Registre de Skills

Fichier : mcp-servers/mcp_skills_registry.json

graph TB
    Registry["Skill Registry<br/>mcp_skills_registry.json"]
    
    subgraph SNOW["bibops_mcp_snow"]
        SNOW_Name["ServiceNow Operations"]
        SNOW_Desc["Query/update ServiceNow tables"]
        SNOW_Use["When: incidents, changes, CMDB"]
        SNOW_Limit["Limits: 5 results max, 30s timeout"]
        SNOW_Cost["Cost: medium"]
    end
    
    subgraph GRAFANA["bibops_mcp_grafana"]
        GRAF_Name["Grafana Monitoring"]
        GRAF_Desc["Query Prometheus, Loki, Azure Monitor"]
        GRAF_Use["When: metrics, logs, alerts"]
        GRAF_Limit["Limits: 7 days max, 60s timeout"]
        GRAF_Cost["Cost: high"]
    end
    
    subgraph SPLUNK["bibops_mcp_splunk"]
        SPL_Name["Splunk Logs"]
        SPL_Use["When: log analysis, search"]
        SPL_Limit["Limits: 10 results, indexing"]
    end
    
    Registry --> SNOW
    Registry --> GRAFANA
    Registry --> SPLUNK
    Registry -.-> Others["... 11 autres MCP servers"]
    
    style Registry fill:#e1f5ff
    style SNOW fill:#fff4e1
    style GRAFANA fill:#ffe1f5
    style SPLUNK fill:#e1ffe1

Sélection Dynamique des Tools

graph LR
    subgraph Phase1["Phase 1: Manuel (actuel)"]
        Code1["Code Python hardcodé"] --> Tools1["tools = [snow, grafana]"]
    end
    
    subgraph Phase2["Phase 2: Déclaratif (court terme)"]
        YAML["YAML Scénario"] --> Required["Required: [snow]"]
        YAML --> Optional["Optional: [grafana, splunk]"]
    end
    
    subgraph Phase3["Phase 3: Intelligent (long terme)"]
        Incident["Incident Description<br/>Database timeout"] --> Classifier["LLM Classifier"]
        Registry2["Skill Registry"] --> Classifier
        Classifier --> Selected["Selected: [snow, grafana, splunk]<br/>Rejected: [ldap, 4ip]"] 
    end
    
    Phase1 -.->|"Migration"| Phase2
    Phase2 -.->|"Évolution"| Phase3
    
    style Phase1 fill:#ffe1e1
    style Phase2 fill:#fff4e1
    style Phase3 fill:#e1ffe1

Bénéfices :

  • Documentation centralisée des capacités
  • Réduction du contexte (moins de tools injectés)
  • Moins d'hallucinations (descriptions claires)
  • Meilleure traçabilité (pourquoi ce tool ?)

Comment les Skills sont Introduits aux Agents

sequenceDiagram
    participant YAML as Scénario YAML
    participant Loader as Prompt Loader
    participant Registry as Skill Registry
    participant PromptParts as Prompt Builder
    participant MCPTools as MCP Tool Loader
    participant Agent as Agent Final
    
    YAML->>Loader: scenarios/incident_enrichment.yaml<br/>(composition + tools + skill_context:true)
    Loader->>PromptParts: Charger blocs de base<br/>(core/**, domain/**, roles/**)
    
    alt skill_context = true
        Loader->>Registry: load_skill_documentation([snow, grafana, splunk])
        Registry-->>Loader: Doc formatée des 3 skills
        Loader->>PromptParts: Ajouter doc skills au prompt
    end
    
    Loader->>MCPTools: get_mcp_tools_by_names([snow, grafana, splunk])
    MCPTools-->>Loader: 3 MCP Tool instances
    
    Loader->>Agent: Créer Agent<br/>Instructions: prompt complet<br/>Tools: 3 MCP tools
    
    Note over Agent: Agent avec contexte enrichi<br/>+ documentation des tools
    
    Agent->>MCPTools: Utilise tools avec meilleur contexte

Avantages de cette approche :

graph TB
    subgraph Avec_skill_context_true["skill_context: true"]
        Context1["Contexte dynamique<br/>Seuls 3/14 tools documentés"]
        Single1["Single source of truth<br/>Registry JSON unique"]
        Reduce1["Réduction contexte<br/>Doc ciblée"]
        Maintain1["Maintenabilité<br/>1 changement = 1 fichier"]
    end
    
    subgraph Avec_skill_context_false["skill_context: false (actuel)"]
        Context2["Pas de surcharge prompt"]
        Light2["Tools chargés sans doc"]
        Registry2["Registry pour sélection<br/>Phase 3 uniquement"]
    end
    
    Choice{"Besoin de guidance<br/>pour l'agent ?"}
    
    Choice -->|"Oui<br/>Agent complexe"| Avec_skill_context_true
    Choice -->|"Non<br/>Économie contexte"| Avec_skill_context_false
    
    style Avec_skill_context_true fill:#e1ffe1
    style Avec_skill_context_false fill:#ffe1e1

Recommandation :

  • Phase 1 : skill_context: false (pas de surcharge du prompt)
  • Phase 2 : skill_context: true pour les agents complexes qui ont besoin de guidance
  • Le registry sert d'abord à documenter pour les humains, puis éventuellement à enrichir le prompt

3. Scalabilité et Nouveaux Scénarios

Architecture Actuelle

Workflows existants :

  • Incident Enrichment : 3 agents (eligibility → solver → validator)
  • Incident Resolution : 3 agents (eligibility → resolution_solver → validator)
  • Change Impact : 3 agents (eligibility → analyzer → report_generator)

Total actuel : 3 workflows × 3 agents = 9 configurations d'agents

Problème de Scalabilité

graph TB
    subgraph Current["Approche Actuelle: Explosion Exponentielle"]
        direction LR
        W1["3 Workflows actuels"] --> A1["9 configurations d'agents"]
        
        Variations["Variations souhaitées:<br/>• Incident réseau<br/>• Incident database<br/>• Incident cloud<br/>• Change multi-user<br/>• Validation externe<br/>..."]
        
        W2["10 Workflows"] --> A2["30 agents à maintenir"]
        
        Problem["Problème:<br/>Duplication massive<br/>Maintenance impossible"]
        
        A2 --> Problem
    end
    
    subgraph Proposed["Approche Proposée: Composition"]
        direction LR
        
        Core["10 blocs core<br/>(réutilisés)"]
        Domain["15 blocs domain<br/>(combinables)"]
        Roles["8 blocs roles<br/>(réutilisables)"]
        Behaviors["6 blocs behaviors<br/>(modificateurs)"]
        
        YAML["10 fichiers YAML<br/>(scénarios)"]
        
        Core --> YAML
        Domain --> YAML
        Roles --> YAML
        Behaviors --> YAML
        
        Solution["Solution:<br/>Réutilisation maximale<br/>Maintenance simple"]
        
        YAML --> Solution
    end
    
    Current -.->|"Migration vers"| Proposed
    
    style Problem fill:#ffe1e1
    style Solution fill:#e1ffe1

Exemple : Ajouter un Nouveau Scénario

Besoin : Analyse d'incident réseau spécifique

graph TB
    subgraph Actuel["Approche Actuelle"]
        direction TB
        A1["1. network_eligibility_checker.py"]
        A2["2. network_incident_solver.py"]
        A3["3. network_validator.py"]
        A4["4. prompts/agents/network_solver.md<br/>(copie de 12.sre.md - DUPLICATION)"]
        A5["5. crews/network_incident_resolution.py"]
        
        A1 --> A2 --> A3 --> A4 --> A5
        
        Result1["Total: 5 fichiers<br/>Beaucoup de duplication<br/>Code Python + Prompts"]
        A5 --> Result1
    end
    
    subgraph Propose["Approche Proposée"]
        direction TB
        P1["1. domain/network/troubleshooting.md<br/>(nouvelles spécificités uniquement)"]
        P2["2. scenarios/network_incident.yaml<br/>(composition déclarative)"]
        
        P1 --> P2
        
        Reuse["Réutilise:<br/>✓ core/**<br/>✓ domain/servicenow/**<br/>✓ roles/sre_investigator.md<br/>✓ behaviors/with_resolution.md"]
        
        P2 --> Reuse
        
        Result2["Total: 2 fichiers<br/>Zéro duplication<br/>Réutilisation maximale"]
        Reuse --> Result2
    end
    
    Compare["Gain: 5 → 2 fichiers<br/>Maintenance -60%"]
    
    Actuel -.->|"vs"| Compare
    Propose -.->|"vs"| Compare
    
    style Actuel fill:#ffe1e1
    style Propose fill:#e1ffe1
    style Compare fill:#e1f5ff

4. Architecture Cible en Couches

Layer 1 : Contexte (Prompts)

  • Core : Blocs de base (Michelin, personality, tools best practices)
  • Domain : Contexte métier par domaine (ServiceNow, monitoring, infrastructure)
  • Roles : Rôles réutilisables (investigator, validator, analyzer)
  • Behaviors : Modificateurs (enrichment_only, with_resolution, conversational)
  • Scenarios : Assemblage déclaratif (YAML)

Layer 2 : Skills (MCP Tools)

  • Registry : Documentation centralisée (mcp_skills_registry.json)
  • MCP Servers : 14 serveurs existants (snow, grafana, splunk, etc.)
  • Dynamic Loading : Chargement selon scénario (via YAML)

Layer 3 : Orchestration (Workflows)

  • Sequential Execution : Workflows 3-agents existants (à conserver)
  • Gates : Eligibility checks entre agents
  • Error Handling : Classification et retry logic

Layer 4 : Observabilité

  • Structured Logging : Déjà en place via shared/observability.py
  • Context Snapshots : À améliorer (capturer le prompt final envoyé)
  • Metadata Tracking : Déjà en place via shared/metadata.py

Layer 5 : Interfaces

  • API REST : api_server.py (JSON structuré)
  • Teams Bot : teamsbot/ (conversationnel)
  • AG-UI : frontend/ (CopilotKit web)

5. Diagramme d'Architecture

flowchart TB

%% =========================
%% USER INPUT
%% =========================

User["User / Event Trigger"] --> Orchestrator

%% =========================
%% ORCHESTRATION LAYER
%% =========================

subgraph Orchestration_Layer
    Orchestrator["Central Orchestrator<br/>Plan-First Execution<br/>Checkpointing<br/>Error Handling"]
    Plan["Execution Plan - DAG"]
end

Orchestrator --> Plan

%% =========================
%% CONTEXT LAYER
%% =========================

subgraph Context_Layer
    ContextAssembler["Context Assembler<br/>Runtime Prompt Builder"]

    subgraph Context_Blocks
        CompanyContext["Company Base Context"]
        ToneContext["Tone and Style"]
        MissionContext["Mission Specific Context"]
        RoleTemplate["Role Template"]
        OutputTemplate["Output Format Template"]
    end

    VectorDB[("Vector Database<br/>Long-Term Memory")]
end

ContextAssembler --> CompanyContext
ContextAssembler --> ToneContext
ContextAssembler --> MissionContext
ContextAssembler --> RoleTemplate
ContextAssembler --> OutputTemplate
ContextAssembler --> VectorDB

%% =========================
%% AGENT LAYER
%% =========================

subgraph Agent_Layer
    Agent1["Agent 1 - Analysis"]
    Agent2["Agent 2 - Validation"]
    Agent3["Agent 3 - Formatting"]
end

Orchestrator --> Agent1
Agent1 --> Agent2
Agent2 --> Agent3

Agent1 --> ContextAssembler
Agent2 --> ContextAssembler
Agent3 --> ContextAssembler

%% =========================
%% SKILL LAYER
%% =========================

subgraph Skill_Layer
    SkillRegistry["Skill Registry<br/>JSON Schema + Versioning"]

    subgraph Business_APIs
        API1["Eligibility API"]
        API2["Search API"]
        API3["Database API"]
    end
end

Agent1 --> SkillRegistry
Agent2 --> SkillRegistry
Agent3 --> SkillRegistry

SkillRegistry --> API1
SkillRegistry --> API2
SkillRegistry --> API3

%% =========================
%% OBSERVABILITY
%% =========================

subgraph Observability
    Logs["Structured Logs"]
    Snapshots["Context Snapshots"]
    Metrics["Monitoring and Metrics"]
end

Orchestrator --> Logs
Orchestrator --> Snapshots
Orchestrator --> Metrics

6. Architecture de Dossiers Proposée

Structure Actuelle (à migrer)

shared/prompts/
├── 01.instructions.md
├── 02.personality.md
├── 03.tools_preamble.md
├── ...
├── 99.final_answer_formatting.md
└── agents/
    ├── eligibility_checker.md
    ├── validator.md
    └── ...

Structure Cible (alignée avec notre architecture)

shared/prompts/
│
├── core/                           
│   ├── 01.michelin_context.md     
│   ├── 02.personality.md          
│   ├── 03.tools_best_practices.md    
│   ├── 04.planning.md                
│   ├── 05.task_execution.md          
│   └── 06.output_formatting.md       
│
├── domain/                           
│   ├── servicenow/
│   │   ├── tables_reference.md       
│   │   ├── query_limits.md           
│   │   ├── kb_search.md              
│   │   └── service_matching.md       
│   │
│   ├── monitoring/
│   │   ├── splunk_indexes.md         
│   │   ├── grafana_datasources.md    
│   │   └── log_analysis_tips.md
│   │
│   ├── infrastructure/
│   │   ├── deploy_plans.md           
│   │   ├── environments.md           
│   │   ├── sites.md                  
│   │   └── networking.md
│   │
│   └── access_management/
│       ├── ldap_structure.md         
│       └── group_memberships.md
│
├── roles/                             
│   ├── eligibility_validator.md     
│   ├── output_validator.md          
│   ├── impact_analyzer.md           
│   └── report_generator.md           
│
├── behaviors/                         
│   ├── enrichment_only.md   
│   ├── with_resolution.md   
│   ├── user_scoped.md                
│   ├── conversational_mode.md        
│   ├── structured_output.md          
│   └── tool_preambles.md             
│
├── scenarios/                        
│   ├── incident_enrichment.yaml      
│   ├── incident_resolution.yaml      
│   ├── change_impact.yaml            
│   ├── sre_agent_interactive.yaml    
│   └── teams_bot.yaml
│
├── __init__.py
└── README.md

mcp-servers/
│
├── mcp_skills_registry.json         
│
├── skills/                            
│   ├── snow.md                        
│   ├── grafana.md                     
│   ├── splunk.md                      
│   ├── ldap.md                        
│   ├── 4ip.md                         
│   ├── abs.md                         
│   ├── d4x.md                         
│   ├── gitlab.md                      
│   ├── gravitee.md                    
│   ├── sli.md                         
│   ├── ad.md                          
│   ├── dgd.md                         
│   ├── inventory.md                   
│   └── networktools.md                
│
├── mcp-snow/
├── mcp-grafana/
├── mcp-splunk/
└── ...                                  

Exemple de Composition YAML

graph TB
    subgraph Scenario1["scenarios/incident_enrichment.yaml"]
        direction TB
        
        subgraph Agent1["0ps_Eligibility_Checker (mini)"]
            A1_Core1["core/01.michelin_context.md"]
            A1_Core2["core/02.personality.md"]
            A1_Domain["domain/servicenow/query_limits.md"]
            A1_Role["roles/eligibility_validator.md"]
            A1_Tools["Tools: [snow]"]
        end
        
        subgraph Agent2["0ps_Incident_Solver (premium)"]
            A2_Core1["core/01.michelin_context.md"]
            A2_Core2["core/02.personality.md"]
            A2_Core3["core/03.tools_best_practices.md"]
            A2_Domain["domain/servicenow/**<br/>domain/monitoring/**"]
            A2_Role["roles/sre_investigator.md"]
            A2_Behavior["behaviors/enrichment_only.md"]
            A2_Tools["Tools: [snow, grafana, splunk, ldap, 4ip]"]
        end
        
        subgraph Agent3["0ps_Validator (mini)"]
            A3_Core["core/02.personality.md"]
            A3_Role["roles/output_validator.md"]
            A3_Tools["Tools: [snow]"]
        end
    end
    
    subgraph Scenario2["scenarios/incident_resolution.yaml"]
        direction TB
        
        subgraph Agent4["0ps_Resolution_Solver (premium)"]
            A4_Core["core/** (identique)"]
            A4_Domain2["domain/** (identique)"]
            A4_Role2["roles/sre_investigator.md (identique)"]
            A4_Behavior["behaviors/with_resolution.md"]
            A4_Tools2["Tools: (identique)"]
        end
    end
    
    Diff["Différence clé:<br/>enrichment_only.md<br/>vs<br/>with_resolution.md"]
    
    A2_Behavior -.->|"Enrichment"| Diff
    A4_Behavior -.->|"Resolution"| Diff
    
    style A2_Behavior fill:#ffe1e1
    style A4_Behavior fill:#e1ffe1
    style Diff fill:#e1f5ff

Points clés :

  • Réutilisation maximale : core, domain, roles identiques entre scénarios
  • Différence minimale : 1 seul fichier behavior change (enrichment vs resolution)
  • Composition déclarative : YAML décrit l'assemblage, pas de code Python