Skip to content

Architecture du système

Le framework APEX v2 repose sur un modèle à 4 niveaux qui sépare clairement les responsabilités : quand exécuter, qui exécute (avec quelle identité et quelles connaissances), et quoi faire.

Vue d'ensemble

Step    (QUAND)   — phases séquentielles du pipeline
  └─ Agent  (QUI + COMMENT)  — identité, contraintes, model, tools
       └─ Profile (SAIT QUOI) — conventions, patterns, toolchain
            └─ Prompt  (FAIT QUOI) — tâche spécifique + artifacts

Chaque niveau a une responsabilité unique et peut être réutilisé indépendamment des autres. Un même agent executor peut être instancié avec des profiles différents (Rust, Vue, Python).

Principe de conception

La séparation en niveaux évite le problème classique des prompts monolithiques qui mélangent identité, connaissances techniques et tâche concrète. Chaque niveau est composable et remplaçable.


Step — Phase du pipeline

Rôle : définir QUAND quelque chose se passe dans le pipeline.

Un step est un fichier dans skills/{skill}/steps/, nommé step-{NN}-{name}.md (numéro à deux chiffres avec zéro de padding). Chaque step correspond à une phase séquentielle nommée. Les steps se succèdent dans l'ordre et peuvent être conditionnels (ex. : step-05-examine.md n'est activé qu'avec le flag -x, step-07-tests.md qu'avec le flag -t).

Chaque fichier step contient des sections XML qui définissent son comportement :

SectionRôle
<objective>Ce que ce step accomplit globalement
<delegation>Agent à invoquer, tier, mode, exception
<process>Étapes détaillées d'exécution
<rules>Contraintes à respecter pendant ce step
<output_template>Format attendu du fichier produit
<save>Nom du fichier à écrire (artifact de sortie)
<next>Step suivant à enchaîner

Granularité recommandée

Un step = une phase cohérente du travail. La frontière naturelle est le changement de mode de travail : analyse, implémentation, review sont trois modes distincts.


Agent — Identité et mécanisme d'exécution

Rôle : définir QUI exécute le travail et COMMENT.

Un agent combine l'identité (rôle, contraintes, style) et le mécanisme d'exécution (modèle, outils). Les agents sont définis dans framework/agents/{name}.md et contiennent :

  • Identité : qui est cet agent, comment il pense, quel est son objectif
  • Contraintes : ce qu'il ne fait pas (ex. : l'architecte ne touche pas au code)
  • Menu d'actions : codes courts pour invoquer des actions spécifiques
  • Agent_Prompt : instructions d'exécution détaillées (responsabilités, format de sortie)
  • Modèle : tier (haiku, sonnet, opus) ou ID concret configuré dans framework/models.md

Un même agent est réutilisable dans des contextes différents. L'agent executor est identique que le travail porte sur du Rust backend ou du Vue frontend — c'est le profile qui change ce qu'il sait, pas qui il est.

Les agents sont instanciés à l'intérieur des steps via un bloc <delegation>.

Exemple : agent executor

markdown
# Executor

Tu es un développeur senior qui implémente du code de production.
Tu privilégies la lisibilité, la maintenabilité et la correction.
Tu ne modifies pas l'architecture — tu l'implémentes.

## Contraintes
- Pas de refactoring non demandé
- Pas de changement d'architecture
- Commit atomiques et cohérents

Isolation

Chaque agent travaille dans son propre contexte. Les artifacts (fichiers produits) constituent le seul canal de communication entre agents.


Délégation obligatoire

Rôle : garantir que chaque step non-trivial est exécuté par l'agent spécialisé prévu.

Tout step qui a un agent dédié s'ouvre sur un bloc <delegation>. Ce bloc force la délégation et prévient toute rationalisation inline.

xml
<delegation>
agent: architect
tier: opus
mode: mandatory
exception: economy mode (`-e`) → work inline, no subagents

STOP — You MUST delegate this step to the agent above using the Agent tool.
DO NOT use Edit, Write, or other file-modification tools directly.
DO NOT rationalize skipping delegation ("it's simpler", "it's faster", "just a few edits").
The ONLY exception is economy mode (`-e`). If `-e` is not active, delegation is not optional.

Resolve the model from the "Models" section in 00-context.md (loaded from models.md at init).
Dispatch:
  Claude Code: Agent(subagent_type="oh-my-claudecode:architect", model="{resolved-model}", prompt="...")
  Other runtimes: delegate to the architect agent with the resolved model using the runtime's native dispatch.
</delegation>

Règles clés :

  • mode: mandatory — la délégation n'est jamais optionnelle
  • Exception unique : le flag -e (economy mode) autorise le travail inline sans sous-agents
  • Les instructions anti-rationalisation empêchent l'IA de décider de court-circuiter
  • Le modèle est résolu depuis 00-context.md, écrit par step-00 après lecture de models.md

Correspondance agent/step dans Kensho :

StepAgentTier
01-analyzearchitectopus
01b-specanalystopus
02-planarchitectopus
03-executeexecutorsonnet
05-examinecode-revieweropus
07-teststest-engineersonnet

Les steps 00, 04, 06, 08, 09 s'exécutent dans le contexte principal sans délégation.

Anti-pattern à éviter

Ne jamais ignorer un bloc <delegation> sous prétexte que la tâche "semble simple" ou "serait plus rapide en direct". La délégation obligatoire existe précisément pour les cas où l'IA serait tentée de rationaliser le raccourci.


Profile — Connaissance technique

Rôle : définir ce que l'agent SAIT sur la stack technique.

Les profiles sont définis dans framework/profiles/{name}.md. Un profile injecte dans l'agent les conventions, patterns et spécificités de la toolchain concernée.

Un profile ne change pas QUI est l'agent — il change QUOI il connaît.

Les agents supportent les multi-profiles : un agent peut recevoir plusieurs profiles simultanément.

Exemple : profile rust

markdown
# Rust Profile

## Conventions
- Nommage snake_case pour fonctions et variables
- Types explicites dans les signatures publiques
- Gestion d'erreur via `Result<T, E>`, pas de `unwrap()` en production
- Modules organisés par domaine fonctionnel

## Patterns
- Builder pattern pour les structs complexes
- Newtype pattern pour la type safety
- `thiserror` pour les erreurs custom, `anyhow` pour le propagation

## Toolchain
- `cargo fmt` avant chaque commit
- `cargo clippy -- -D warnings` en CI
- Tests unitaires dans le même fichier avec `#[cfg(test)]`

Multi-profiles

yaml
profile: [rust, tauri]

Les profiles sont concaténés dans l'ordre. En cas de conflit, le dernier profile l'emporte.


Prompt — Tâche spécifique

Rôle : définir ce que l'agent FAIT concrètement.

Le prompt est transmis à l'agent lors de sa délégation (champ prompt de l'appel Agent()). Il spécifie :

  • La tâche précise à accomplir
  • Les artifacts en entrée (fichiers à lire)
  • Les artifacts à produire en sortie

Le prompt est le niveau le plus spécifique — il change à chaque step et chaque agent. Les autres niveaux (agent, profile) sont réutilisables.


Comment ça s'assemble

Quand un step délègue à un agent, le contexte final est construit en concaténant les niveaux dans l'ordre :

[Agent: framework/agents/executor.md]          ← QUI tu es + contraintes
[Profile: framework/profiles/rust.md]          ← SAIT : conventions Rust
[Artifacts: spec.md, plan.md, tasks.md]        ← CONTEXTE partagé
[Prompt: "Implémente les tâches backend..."]   ← FAIT : la tâche concrète

L'ordre est fixe et intentionnel : l'identité et les contraintes de l'agent sont établies en premier, avant d'injecter les connaissances techniques et le contexte de travail.

Priorité en cas de conflit

Si le profile contredit l'agent sur un point, le profile l'emporte pour les conventions techniques. Si le prompt contredit l'agent sur les contraintes (ex. : "refactorise tout"), l'agent l'emporte.


Orchestration multi-agents

L'architecture prévoit la capacité de dispatcher plusieurs agents simultanément depuis un même step :

  • parallel : les agents s'exécutent en simultané (ex. : backend-dev + frontend-dev)
  • sequential : les agents s'exécutent l'un après l'autre (ex. : analyse → plan)

Dans l'implémentation actuelle, chaque step délègue à un seul agent via son bloc <delegation>. Le dispatch parallèle est une capacité architecturale disponible pour des pipelines avancés.

Exemple de step d'exécution avec bloc de délégation réel :

xml
<delegation>
agent: executor
tier: sonnet
mode: mandatory
exception: economy mode (`-e`) → work inline, no subagents

STOP — You MUST delegate this step to the agent above using the Agent tool.
DO NOT use Edit, Write, or other file-modification tools directly.
DO NOT rationalize skipping delegation ("it's simpler", "it's faster", "just a few edits").
The ONLY exception is economy mode (`-e`). If `-e` is not active, delegation is not optional.

Resolve the model from the "Models" section in 00-context.md (loaded from models.md at init).
Dispatch:
  Claude Code: Agent(subagent_type="oh-my-claudecode:executor", model="{resolved-model}", prompt="...")
  Other runtimes: delegate to the executor agent with the resolved model using the runtime's native dispatch.
</delegation>

Les artifacts produits par un agent (fichiers écrits) constituent le seul canal de communication avec le step suivant.


Boucle de feedback

Kensho implémente une boucle de feedback entre les steps 05 et 06 :

  1. step-05-examine (conditionnel, flag -x) délègue à code-reviewer (opus) qui produit un rapport de findings
  2. Si des findings sont détectés, step-06-resolve prend le relai dans le contexte principal et applique les corrections
  3. step-04-validate peut être ré-exécuté après résolution pour confirmer que le build et les tests passent toujours

Le fichier de findings produit par step-05 est l'artifact d'entrée de step-06. La transition est conditionnelle : step-06 n'est pertinent que si step-05 a signalé des findings.

Conditions de déclenchement

Step-06 résout les findings issus de step-05. En l'absence de findings, on passe directement à step-07 (si -t est actif) ou à step-09.


Pipeline Kensho (vue simplifiée)

00-init
  └─ Initialise le contexte, lit les flags, charge models.md et profiles

01-analyze
  └─ Delegation: architect (opus) → exploration lecture seule du codebase

01b-spec  [gate obligatoire, même en -a]
  └─ Delegation: analyst (opus) → spec formelle avec requirements SHALL

02-plan
  └─ Delegation: architect (opus) → plan fichier par fichier

03-execute
  └─ Delegation: executor (sonnet) → implémentation todo-driven

04-validate
  └─ Vérification build + tests + spec (contexte principal)

05-examine  [flag -x requis]
  └─ Delegation: code-reviewer (opus) → review adversariale

06-resolve  [si findings au step 05]
  └─ Corrections (contexte principal)

07-tests  [flag -t requis]
  └─ Delegation: test-engineer (sonnet) → création de tests

08-run-tests  [flag -t requis]
  └─ Exécution des tests en boucle (contexte principal)

09-finish
  └─ Commit conventionnel + résumé (contexte principal)

Tableau récapitulatif

NiveauFichierRôleExemple
Stepskills/kensho/steps/step-03-execute.mdQUAND — phase séquentielle du pipeline03-execute, 05-examine
Agentframework/agents/executor.mdQUI + COMMENT — identité, contraintes, model, toolsexecutor, code-reviewer, analyst
Profileframework/profiles/rust.mdSAIT QUOI — conventions, toolchainrust, vue-typescript, tauri
Prompt(transmis lors de la délégation)FAIT QUOI — tâche + artifacts"Implémente les tâches backend..."

Réutilisabilité

Les agents et profiles sont les niveaux les plus réutilisables. Un profile rust est partagé entre tous les agents qui travaillent sur du code Rust, qu'ils soient executors, reviewers ou analyzers.

Shingan (心眼) — Linagora