---
title: "Cadence plutôt que volume — orchestrer plusieurs projets avec des agents IA"
description: "Architecture concrète pour maintenir une cadence sur plusieurs projets parallèles : automations.json, mémoire d'agent et capitalisation cross-projet."
created: 2026-05-11T23:00:00+02:00
updated: 2026-05-13T12:00:00+02:00
tags: ["IA", "KittyClaw", "Tooling", "Coulisses"]
image: /images/blog/cadence-agents-5-projets-cover.webp
card: /images/blog/cadence-agents-5-projets-card.webp
---

Gérer plusieurs projets en parallèle avec des agents IA produit un effet contre-intuitif : sans infrastructure de capitalisation, chaque run repart à zéro. La mémoire reste locale au projet, les patterns découverts ne migrent pas, et la cadence dépend entièrement de la disponibilité humaine. Ce qui suit décrit l'infrastructure qui résout ce problème — et pourquoi la régularité en est la condition première.

## Anatomie d'un projet orchestré

Chaque projet héberge un dossier `.agents/` avec quatre éléments :

```
.agents/
├── preamble.md          # contexte injecté à chaque run d'agent
├── automations.json     # pipelines de déclenchement
├── {agent}/
│   ├── SKILL.md         # instructions métier stables
│   └── memory.md        # apprentissages accumulés run après run
```

**`preamble.md`** est le vecteur de cohérence. Il contient les règles partagées — workflow git, conventions de commit, accès API — injectées dans le contexte de tout agent au démarrage. Ce qui est dans `preamble.md` n'a pas besoin d'être répété dans chaque `SKILL.md`.

**`automations.json`** définit les pipelines. L'automation centrale, `assignee-dispatch`, déroule trois actions dès qu'un ticket passe en Todo avec un assignee :

```json
{
  "id": "assignee-dispatch",
  "trigger": { "type": "ticketInColumn", "columns": ["Todo"] },
  "conditions": [
    { "type": "assignedTo", "slugs": ["programmer", "content-writer", "qa-tester", "..."] },
    { "type": "ticketCountInColumn", "columns": ["InProgress"],
      "sameAssignee": true, "operator": "==", "value": 0 }
  ],
  "actions": [
    { "type": "moveTicketStatus", "to": "InProgress" },
    { "type": "runAgent", "agent": "{assignee}", "model": "claude-sonnet-4-6" },
    { "type": "commitAgentMemory", "agent": "{assignee}" }
  ]
}
```

La condition `ticketCountInColumn == 0` garantit l'absence de parallélisme non contrôlé : un agent ne démarre pas un nouveau ticket tant qu'il en a un en cours. La dernière action, `commitAgentMemory`, persiste automatiquement la mémoire de l'agent après chaque run — c'est la clé de la capitalisation.

## La mémoire comme outil de progression

Là où la plupart des setups d'agents IA restent stateless, `memory.md` introduit un état persistant structuré. Chaque agent maintient un fichier de leçons avec un compteur `[+N]` qui trace le nombre de fois où chaque leçon a été réappliquée :

```markdown
## API / tooling [+5]
- curl on Windows mangles UTF-8 in JSON bodies.
  Use python3 urllib.request instead. [+2]
- PR creation: gh not available;
  az repos pr create has permission errors. [+2]

## SVG inline in Markdown [+3]
- NEVER use <marker> + marker-end="url(#id)" in inline SVGs. [+3]
- Draw arrowheads as explicit <polygon> elements.
```

Le compteur remplit deux fonctions : il indique quelles leçons ont de la valeur (elles reviennent), et il guide la consolidation — quand une entrée atteint `[5+]`, elle migre vers `SKILL.md` comme règle stable. Les entrées à `[0]` sont supprimées.

Cette distinction entre `SKILL.md` (règles stables, rarement modifiées) et `memory.md` (apprentissages actifs, mis à jour à chaque run) est structurelle. Elle empêche la mémoire de devenir un fourre-tout et force une discipline sur ce qui mérite d'être retenu.

## Capitalisation cross-projet

Les agents apprennent de leurs erreurs — un agent qui bute sur un problème ne le rencontre plus jamais grâce à `memory.md`. Mais le vrai changement d'échelle, c'est quand les projets commencent à partager des capacités entières.

### Génération d'images mutualisée

Un content-writer sur Bloomii a besoin d'une illustration. Un content-writer sur Ekioo a besoin d'une cover. Aucun des deux ne sait comment fonctionne gpt-image-2, aucun ne gère de clé API, aucun ne se soucie du rate limiting.

Un seul processeur tourne en cron toutes les 10 minutes dans le Workspace central. Les agents de n'importe quel projet soumettent une requête via `image-enqueue.mjs`, reçoivent un ID, et passent à autre chose. Le processeur gère la file, les pauses quand le quota est atteint, la reprise automatique. L'agent est notifié quand l'image est prête.

```bash
node C:/IA/Workspace/.agents/tools/image-enqueue.mjs \
  --prompt "..." --output path/to/cover.webp \
  --project bloomii --ticket 189
```

Un outil, un processeur, N projets consommateurs. L'ajout d'un sixième projet ne nécessite aucune configuration — juste un appel à `image-enqueue.mjs`.

<svg viewBox="0 0 700 200" xmlns="http://www.w3.org/2000/svg" style="width:100%;max-width:700px;background:#0d1117;border-radius:8px;display:block;margin:2rem auto">
<defs>
<pattern id="cav-img-dots" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="1" fill="#1c2128"/>
</pattern>
<filter id="cav-img-gg" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur in="SourceGraphic" stdDeviation="3" result="b"/>
<feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="cav-img-gp" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur in="SourceGraphic" stdDeviation="4" result="b"/>
<feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
</defs>
<rect width="700" height="200" fill="#0d1117"/>
<rect width="700" height="200" fill="url(#cav-img-dots)"/>
<rect x="20" y="20" width="130" height="44" rx="6" fill="#0d2818" stroke="#3fb950" stroke-width="1.5" filter="url(#cav-img-gg)"/>
<rect x="20" y="20" width="4" height="44" rx="2" fill="#3fb950"/>
<text x="88" y="47" text-anchor="middle" fill="#e6edf3" font-family="monospace" font-size="12">Bloomii</text>
<rect x="20" y="78" width="130" height="44" rx="6" fill="#0d2818" stroke="#3fb950" stroke-width="1.5" filter="url(#cav-img-gg)"/>
<rect x="20" y="78" width="4" height="44" rx="2" fill="#3fb950"/>
<text x="88" y="105" text-anchor="middle" fill="#e6edf3" font-family="monospace" font-size="12">Ekioo</text>
<rect x="20" y="136" width="130" height="44" rx="6" fill="#0d2818" stroke="#3fb950" stroke-width="1.5" filter="url(#cav-img-gg)"/>
<rect x="20" y="136" width="4" height="44" rx="2" fill="#3fb950"/>
<text x="88" y="163" text-anchor="middle" fill="#e6edf3" font-family="monospace" font-size="12">Kalceo</text>
<text x="88" y="13" text-anchor="middle" fill="#8b949e" font-family="monospace" font-size="10">agents</text>
<line x1="150" y1="42" x2="240" y2="80" stroke="#3fb950" stroke-width="1.5" opacity="0.6"/>
<polygon points="234,75 242,80 234,85" fill="#3fb950" opacity="0.6"/>
<line x1="150" y1="100" x2="240" y2="100" stroke="#3fb950" stroke-width="1.5" opacity="0.6"/>
<polygon points="234,96 242,100 234,104" fill="#3fb950" opacity="0.6"/>
<line x1="150" y1="158" x2="240" y2="120" stroke="#3fb950" stroke-width="1.5" opacity="0.6"/>
<polygon points="234,115 242,120 234,125" fill="#3fb950" opacity="0.6"/>
<rect x="244" y="60" width="160" height="80" rx="8" fill="#150d2a" stroke="#a371f7" stroke-width="2" filter="url(#cav-img-gp)"/>
<rect x="244" y="60" width="160" height="4" rx="2" fill="#a371f7"/>
<text x="324" y="90" text-anchor="middle" fill="#a371f7" font-family="monospace" font-size="13" font-weight="bold">image-queue.json</text>
<text x="324" y="110" text-anchor="middle" fill="#a371f7" font-family="monospace" font-size="10">file unique · cron /10min</text>
<text x="324" y="126" text-anchor="middle" fill="#a371f7" font-family="monospace" font-size="10">rate limit auto</text>
<line x1="404" y1="100" x2="470" y2="100" stroke="#a371f7" stroke-width="1.5" opacity="0.7"/>
<polygon points="464,96 472,100 464,104" fill="#a371f7" opacity="0.7"/>
<rect x="474" y="70" width="120" height="60" rx="8" fill="#1a1a0d" stroke="#d29922" stroke-width="1.5" filter="url(#cav-img-gg)"/>
<rect x="474" y="70" width="4" height="60" rx="2" fill="#d29922"/>
<text x="537" y="96" text-anchor="middle" fill="#d29922" font-family="monospace" font-size="12" font-weight="bold">gpt-image-2</text>
<text x="537" y="114" text-anchor="middle" fill="#8b949e" font-family="monospace" font-size="10">CDP processor</text>
<line x1="594" y1="100" x2="630" y2="100" stroke="#d29922" stroke-width="1.5" opacity="0.7"/>
<polygon points="624,96 632,100 624,104" fill="#d29922" opacity="0.7"/>
<text x="665" y="104" text-anchor="middle" fill="#e6edf3" font-family="monospace" font-size="11">.webp</text>
</svg>

### Boîte mail centralisée — dispatch automatique

Tous les projets partagent une seule boîte mail, exposée via VizMail (serveur HTTP local, 40+ endpoints REST). Quand un mail arrive — retour client Kalceo, feedback lecteur Bloomii, contact Ekioo — il est automatiquement dispatché vers le projet concerné sous forme de ticket KittyClaw. L'agent approprié le traite sans intervention humaine.

Le résultat : une seule boîte mail à surveiller, zéro tri manuel, et chaque projet reçoit ses mails pertinents sous forme de tâches exploitables par les agents.

<svg viewBox="0 0 700 200" xmlns="http://www.w3.org/2000/svg" style="width:100%;max-width:700px;background:#0d1117;border-radius:8px;display:block;margin:2rem auto">
<defs>
<pattern id="cav-mail-dots" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="1" fill="#1c2128"/>
</pattern>
<filter id="cav-mail-gb" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur in="SourceGraphic" stdDeviation="3" result="b"/>
<feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="cav-mail-gp" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur in="SourceGraphic" stdDeviation="4" result="b"/>
<feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="cav-mail-gg" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur in="SourceGraphic" stdDeviation="3" result="b"/>
<feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
</defs>
<rect width="700" height="200" fill="#0d1117"/>
<rect width="700" height="200" fill="url(#cav-mail-dots)"/>
<rect x="20" y="60" width="120" height="80" rx="8" fill="#0d1a2a" stroke="#58a6ff" stroke-width="2" filter="url(#cav-mail-gb)"/>
<rect x="20" y="60" width="4" height="80" rx="2" fill="#58a6ff"/>
<text x="82" y="93" text-anchor="middle" fill="#58a6ff" font-family="monospace" font-size="13" font-weight="bold">IMAP</text>
<text x="82" y="113" text-anchor="middle" fill="#8b949e" font-family="monospace" font-size="10">boîte unique</text>
<text x="82" y="128" text-anchor="middle" fill="#8b949e" font-family="monospace" font-size="10">lain@ekioo.com</text>
<line x1="140" y1="100" x2="218" y2="100" stroke="#58a6ff" stroke-width="1.5" opacity="0.7"/>
<polygon points="212,96 220,100 212,104" fill="#58a6ff" opacity="0.7"/>
<rect x="222" y="50" width="190" height="100" rx="8" fill="#150d2a" stroke="#a371f7" stroke-width="2" filter="url(#cav-mail-gp)"/>
<rect x="222" y="50" width="190" height="4" rx="2" fill="#a371f7"/>
<text x="317" y="82" text-anchor="middle" fill="#a371f7" font-family="monospace" font-size="13" font-weight="bold">VizMail</text>
<text x="317" y="100" text-anchor="middle" fill="#a371f7" font-family="monospace" font-size="10">classifie + dispatch</text>
<text x="317" y="118" text-anchor="middle" fill="#a371f7" font-family="monospace" font-size="10">→ ticket KittyClaw</text>
<text x="317" y="136" text-anchor="middle" fill="#a371f7" font-family="monospace" font-size="10">par projet</text>
<line x1="412" y1="75" x2="490" y2="48" stroke="#3fb950" stroke-width="1.5" opacity="0.6"/>
<polygon points="484,43 492,48 484,53" fill="#3fb950" opacity="0.6"/>
<line x1="412" y1="100" x2="490" y2="100" stroke="#3fb950" stroke-width="1.5" opacity="0.6"/>
<polygon points="484,96 492,100 484,104" fill="#3fb950" opacity="0.6"/>
<line x1="412" y1="125" x2="490" y2="152" stroke="#3fb950" stroke-width="1.5" opacity="0.6"/>
<polygon points="484,147 492,152 484,157" fill="#3fb950" opacity="0.6"/>
<rect x="494" y="24" width="180" height="44" rx="6" fill="#0d2818" stroke="#3fb950" stroke-width="1.5" filter="url(#cav-mail-gg)"/>
<rect x="494" y="24" width="4" height="44" rx="2" fill="#3fb950"/>
<text x="587" y="42" text-anchor="middle" fill="#e6edf3" font-family="monospace" font-size="11">Kalceo</text>
<text x="587" y="58" text-anchor="middle" fill="#8b949e" font-family="monospace" font-size="9">retour client → ticket</text>
<rect x="494" y="78" width="180" height="44" rx="6" fill="#0d2818" stroke="#3fb950" stroke-width="1.5" filter="url(#cav-mail-gg)"/>
<rect x="494" y="78" width="4" height="44" rx="2" fill="#3fb950"/>
<text x="587" y="96" text-anchor="middle" fill="#e6edf3" font-family="monospace" font-size="11">Bloomii</text>
<text x="587" y="112" text-anchor="middle" fill="#8b949e" font-family="monospace" font-size="9">feedback lecteur → ticket</text>
<rect x="494" y="132" width="180" height="44" rx="6" fill="#0d2818" stroke="#3fb950" stroke-width="1.5" filter="url(#cav-mail-gg)"/>
<rect x="494" y="132" width="4" height="44" rx="2" fill="#3fb950"/>
<text x="587" y="150" text-anchor="middle" fill="#e6edf3" font-family="monospace" font-size="11">Ekioo</text>
<text x="587" y="166" text-anchor="middle" fill="#8b949e" font-family="monospace" font-size="9">contact form → ticket</text>
</svg>

### Branding X centralisé

Quatre projets alimentent un seul compte X (`@LainAgent_AI`). Chaque projet a son propre outil de publication (`x-post-tweet.mjs`), mais la stratégie éditoriale vit dans un fichier unique — `x-strategy.md` — dans le Workspace central : piliers de contenu, voix, règles d'engagement.

Un community-manager rédige, lain valide. Pas de fragmentation d'audience entre quatre comptes fantômes. Un seul compte qui accumule de l'autorité, alimenté par quatre sources de contenu différentes.

<svg viewBox="0 0 700 200" xmlns="http://www.w3.org/2000/svg" style="width:100%;max-width:700px;background:#0d1117;border-radius:8px;display:block;margin:2rem auto">
<defs>
<pattern id="cav-x-dots" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="1" fill="#1c2128"/>
</pattern>
<filter id="cav-x-gg" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur in="SourceGraphic" stdDeviation="3" result="b"/>
<feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="cav-x-gp" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur in="SourceGraphic" stdDeviation="4" result="b"/>
<feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
</defs>
<rect width="700" height="200" fill="#0d1117"/>
<rect width="700" height="200" fill="url(#cav-x-dots)"/>
<rect x="20" y="20" width="150" height="40" rx="6" fill="#0d2818" stroke="#3fb950" stroke-width="1.5" filter="url(#cav-x-gg)"/>
<rect x="20" y="20" width="4" height="40" rx="2" fill="#3fb950"/>
<text x="98" y="45" text-anchor="middle" fill="#e6edf3" font-family="monospace" font-size="11">Ekioo · IA/Craft</text>
<rect x="20" y="70" width="150" height="40" rx="6" fill="#0d2818" stroke="#3fb950" stroke-width="1.5" filter="url(#cav-x-gg)"/>
<rect x="20" y="70" width="4" height="40" rx="2" fill="#3fb950"/>
<text x="98" y="95" text-anchor="middle" fill="#e6edf3" font-family="monospace" font-size="11">Kalceo · BTP</text>
<rect x="20" y="120" width="150" height="40" rx="6" fill="#0d2818" stroke="#3fb950" stroke-width="1.5" filter="url(#cav-x-gg)"/>
<rect x="20" y="120" width="4" height="40" rx="2" fill="#3fb950"/>
<text x="98" y="145" text-anchor="middle" fill="#e6edf3" font-family="monospace" font-size="11">Bloomii · Green</text>
<text x="98" y="13" text-anchor="middle" fill="#8b949e" font-family="monospace" font-size="10">piliers de contenu</text>
<line x1="170" y1="40" x2="260" y2="86" stroke="#3fb950" stroke-width="1.5" opacity="0.6"/>
<polygon points="254,81 262,86 254,91" fill="#3fb950" opacity="0.6"/>
<line x1="170" y1="90" x2="260" y2="94" stroke="#3fb950" stroke-width="1.5" opacity="0.6"/>
<polygon points="254,90 262,94 254,98" fill="#3fb950" opacity="0.6"/>
<line x1="170" y1="140" x2="260" y2="104" stroke="#3fb950" stroke-width="1.5" opacity="0.6"/>
<polygon points="254,99 262,104 254,109" fill="#3fb950" opacity="0.6"/>
<rect x="264" y="60" width="180" height="80" rx="8" fill="#150d2a" stroke="#a371f7" stroke-width="2" filter="url(#cav-x-gp)"/>
<rect x="264" y="60" width="180" height="4" rx="2" fill="#a371f7"/>
<text x="354" y="90" text-anchor="middle" fill="#a371f7" font-family="monospace" font-size="12" font-weight="bold">x-strategy.md</text>
<text x="354" y="108" text-anchor="middle" fill="#a371f7" font-family="monospace" font-size="10">voix unique · validation</text>
<text x="354" y="126" text-anchor="middle" fill="#a371f7" font-family="monospace" font-size="10">community-manager + lain</text>
<line x1="444" y1="100" x2="510" y2="100" stroke="#a371f7" stroke-width="1.5" opacity="0.7"/>
<polygon points="504,96 512,100 504,104" fill="#a371f7" opacity="0.7"/>
<rect x="514" y="66" width="166" height="68" rx="8" fill="#1a1a0d" stroke="#d29922" stroke-width="1.5" filter="url(#cav-x-gg)"/>
<rect x="514" y="66" width="4" height="68" rx="2" fill="#d29922"/>
<text x="600" y="94" text-anchor="middle" fill="#d29922" font-family="monospace" font-size="14" font-weight="bold">@LainAgent_AI</text>
<text x="600" y="114" text-anchor="middle" fill="#8b949e" font-family="monospace" font-size="10">compte unique · autorité</text>
<rect x="20" y="170" width="150" height="22" rx="4" fill="#1c1c2a" stroke="#58a6ff" stroke-width="1" opacity="0.6"/>
<text x="98" y="185" text-anchor="middle" fill="#58a6ff" font-family="monospace" font-size="9">Vizmail · Tooling</text>
<line x1="170" y1="181" x2="260" y2="114" stroke="#58a6ff" stroke-width="1" opacity="0.4"/>
<polygon points="254,109 262,114 254,119" fill="#58a6ff" opacity="0.4"/>
</svg>

### Knowledge base hub-and-spoke

Le Workspace central fournit l'infrastructure partagée : documentation des API (KittyClaw, Brevo, Chrome CDP), credentials centralisées, outils CLI. Chaque projet maintient sa propre base de connaissance domaine — réglementation BTP et douleurs artisan pour Kalceo, recherche par pilier éditorial et packs de distribution pour Bloomii.

Un agent Kalceo qui envoie une newsletter et un agent Bloomii qui programme un post LinkedIn utilisent le même token Brevo, la même documentation, les mêmes patterns d'appel — sans savoir que l'autre existe. La connaissance infrastructure est écrite une fois, consommée partout.

<svg viewBox="0 0 700 240" xmlns="http://www.w3.org/2000/svg" style="width:100%;max-width:700px;background:#0d1117;border-radius:8px;display:block;margin:2rem auto">
<defs>
<pattern id="cav-kb-dots" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="1" fill="#1c2128"/>
</pattern>
<filter id="cav-kb-gp" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur in="SourceGraphic" stdDeviation="4" result="b"/>
<feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="cav-kb-gg" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur in="SourceGraphic" stdDeviation="3" result="b"/>
<feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="cav-kb-gb" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur in="SourceGraphic" stdDeviation="3" result="b"/>
<feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
</defs>
<rect width="700" height="240" fill="#0d1117"/>
<rect width="700" height="240" fill="url(#cav-kb-dots)"/>
<text x="350" y="22" text-anchor="middle" fill="#8b949e" font-family="monospace" font-size="10">hub central — Workspace</text>
<rect x="200" y="32" width="300" height="80" rx="8" fill="#150d2a" stroke="#a371f7" stroke-width="2" filter="url(#cav-kb-gp)"/>
<rect x="200" y="32" width="300" height="4" rx="2" fill="#a371f7"/>
<text x="350" y="58" text-anchor="middle" fill="#a371f7" font-family="monospace" font-size="12" font-weight="bold">knowledge/ · tools/ · credentials</text>
<rect x="218" y="68" width="84" height="20" rx="10" fill="#1c1c2a" stroke="#a371f7" stroke-width="1"/>
<text x="260" y="82" text-anchor="middle" fill="#a371f7" font-family="monospace" font-size="9">KittyClaw API</text>
<rect x="308" y="68" width="84" height="20" rx="10" fill="#1c1c2a" stroke="#a371f7" stroke-width="1"/>
<text x="350" y="82" text-anchor="middle" fill="#a371f7" font-family="monospace" font-size="9">Brevo API</text>
<rect x="398" y="68" width="84" height="20" rx="10" fill="#1c1c2a" stroke="#a371f7" stroke-width="1"/>
<text x="440" y="82" text-anchor="middle" fill="#a371f7" font-family="monospace" font-size="9">Chrome CDP</text>
<line x1="280" y1="112" x2="140" y2="148" stroke="#a371f7" stroke-width="1.5" opacity="0.5"/>
<polygon points="134,143 142,148 134,153" fill="#a371f7" opacity="0.5"/>
<line x1="350" y1="112" x2="350" y2="148" stroke="#a371f7" stroke-width="1.5" opacity="0.5"/>
<polygon points="346,142 350,150 354,142" fill="#a371f7" opacity="0.5"/>
<line x1="420" y1="112" x2="560" y2="148" stroke="#a371f7" stroke-width="1.5" opacity="0.5"/>
<polygon points="554,143 562,148 554,153" fill="#a371f7" opacity="0.5"/>
<text x="350" y="140" text-anchor="middle" fill="#8b949e" font-family="monospace" font-size="10">spoke — domaine projet</text>
<rect x="20" y="152" width="200" height="70" rx="6" fill="#0d2818" stroke="#3fb950" stroke-width="1.5" filter="url(#cav-kb-gg)"/>
<rect x="20" y="152" width="4" height="70" rx="2" fill="#3fb950"/>
<text x="122" y="174" text-anchor="middle" fill="#e6edf3" font-family="monospace" font-size="12" font-weight="bold">Kalceo</text>
<text x="122" y="192" text-anchor="middle" fill="#8b949e" font-family="monospace" font-size="9">réglementation BTP</text>
<text x="122" y="206" text-anchor="middle" fill="#8b949e" font-family="monospace" font-size="9">douleurs artisan · devis</text>
<rect x="250" y="152" width="200" height="70" rx="6" fill="#0d2818" stroke="#3fb950" stroke-width="1.5" filter="url(#cav-kb-gg)"/>
<rect x="250" y="152" width="4" height="70" rx="2" fill="#3fb950"/>
<text x="352" y="174" text-anchor="middle" fill="#e6edf3" font-family="monospace" font-size="12" font-weight="bold">Bloomii</text>
<text x="352" y="192" text-anchor="middle" fill="#8b949e" font-family="monospace" font-size="9">piliers éditoriaux · sources</text>
<text x="352" y="206" text-anchor="middle" fill="#8b949e" font-family="monospace" font-size="9">packs de distribution</text>
<rect x="480" y="152" width="200" height="70" rx="6" fill="#0d1a2a" stroke="#58a6ff" stroke-width="1.5" filter="url(#cav-kb-gb)"/>
<rect x="480" y="152" width="4" height="70" rx="2" fill="#58a6ff"/>
<text x="582" y="174" text-anchor="middle" fill="#e6edf3" font-family="monospace" font-size="12" font-weight="bold">Ekioo · Vizmail</text>
<text x="582" y="192" text-anchor="middle" fill="#8b949e" font-family="monospace" font-size="9">pas de KB domaine</text>
<text x="582" y="206" text-anchor="middle" fill="#58a6ff" font-family="monospace" font-size="9">consomment le hub</text>
</svg>

## Cadence comme signal de santé

Trente à cinquante tickets traités par semaine sur l'ensemble des projets. Ce chiffre n'est pas un objectif de productivité — c'est un indicateur de santé du système.

Quand la colonne Todo d'un projet accumule sans être drainée, le signal est clair : le backlog est mal priorisé, ou le projet manque d'agents adaptés pour les tâches en attente. La cadence hebdomadaire rend ce déséquilibre visible immédiatement.

L'agent `evaluator` calcule des scores après chaque ticket fermé : first-pass success rate, feedback compliance, delivery quality. Ces métriques mesurent si la capitalisation fonctionne — un taux de first-pass success en hausse indique que les agents s'améliorent run après run. Un taux qui stagne signale une mémoire qui ne s'alimente plus.

Un agent qui ne tourne pas régulièrement n'accumule pas de mémoire exploitable : il repart à zéro, refait les mêmes erreurs, redemande les mêmes clarifications. La régularité n'est pas une discipline de publication — c'est la condition pour que le système apprenne.

## Conclusion

L'infrastructure tient en quatre fichiers par agent : `preamble.md`, `automations.json`, `SKILL.md`, `memory.md`. Ce qui la rend efficace, c'est la discipline d'alimentation : committer la mémoire après chaque run (l'action `commitAgentMemory` le fait automatiquement), supprimer les entrées à `[0]`, promouvoir les leçons à `[5+]` vers `SKILL.md`.

La seule règle qui compte : ne jamais rater deux semaines de suite. Une semaine calme ne brise pas la cadence. Deux semaines brisent la mémoire des agents, la cohérence des projets, et le signal SEO.

Régularité d'abord. Volume ensuite.
