IPC et bus
Le système nerveux qui connecte les pods entre eux : Redis Streams pour le temps réel, bus JSONL pour l'audit trail, consumer groups pour la coordination.
Quatre couches de communication
Le sous-système IPC de Nika OS combine quatre couches, chacune avec un rôle distinct. Toutes sont fail-open : si Redis est down, les pods continuent de tourner en mode dégradé plutôt que d’échouer en cascade.
| Couche | Pattern Redis | TTL | Usage |
|---|---|---|---|
| Signaling | nika:ipc:{job_id} (STREAM) | 2 h | Events : result, signal, request, error |
| Working Memory | nika:wm:{job_id}:{artifact} (HASH) | 1 h | Résultats intermédiaires < 512 kB |
| Contracts | nika:contract:{job_id} (HASH) | 2 h | Pipeline multi-pod : steps, roles, I/O |
| Entity Feed | nika:feed:entities (STREAM) | 24 h | Tous les changements PROJ/JOB/TASK |
Consumer groups
Le stream nika:feed:entities est consommé par trois groups, qui se
partagent les événements selon leur rôle :
cg:orchestrator— le pod Alpha reçoit tous les événements. Il s’en sert pour observer l’essaim sans avoir à interroger chaque pod individuellement.cg:worker— les pods workers sont load-balanced dans ce group. Quand un nouveau job apparaît, un seul worker est notifié, ce qui évite les races.cg:monitor— le dashboard (Grafana, K3s pods de monitoring) reçoit aussi tous les événements pour les métriques temps réel.
Cette séparation est ce qui permet à Alpha de garder sa fenêtre de contexte propre. Alpha n’a pas à lire les logs de chaque pod : il s’abonne au feed entités et reçoit seulement les transitions significatives (created, completed, failed). Si Alpha veut un détail, il lit le bus JSONL ou interroge Qdrant.
Dual-write : Redis + Qdrant
Les événements significatifs (completed, failed, created pour les
hiérarchies racines) sont dual-written :
- en Redis Streams pour la latence temps réel ;
- en Qdrant pour la persistance long terme et le rappel sémantique.
L’événement en Qdrant porte l’enveloppe NIKA_META complète. Six mois plus
tard, on peut interroger « combien de jobs domain=hooks ont échoué avec
intent=refactor en avril 2026 ? » et obtenir une réponse instantanée.
Bus JSONL : l’audit trail
En parallèle de Redis, chaque message d’orchestration est append-only dans un fichier JSONL :
_bus/alpha_bus.jsonl— canal global d’Alpha._bus/channels/{entity_id}.jsonl— un fichier par entité PROJ/JOB/TASK.
Pourquoi un fichier plat alors que Redis fait le travail ? Trois raisons :
- Survie aux pannes Redis — les pods peuvent encore loguer.
- Audit hors-ligne — un opérateur peut
grepsix mois d’historique sans sortir le terminal. - Forensics — quand quelque chose va mal, le bus JSONL est la dernière source de vérité, indépendante des autres systèmes.
Les types de messages standards :
session_start — démarrage d'un pod ou d'Alpha
session_end_summary — fin avec résumé enrichi
subagent_completed — un pod a fini, summary ingéré en Qdrant
review_request — le pod parent doit valider un livrable
autonomous_dispatch — dispatch déclenché par autonomy_engine (3% probabiliste)
job_completed — entity hiérarchique terminée
Télémétrie Redis Streams
Chaque appel d’outil dans un pod déclenche un XADD sur le stream
agent:events:{session_id} (maxlen=5000, TTL 24 h). En parallèle, le hook
PostToolUse met à jour :
agent:state:{session_id}(HSET heartbeat, TTL 2 h) — le pod est-il encore vivant ?agent:metrics:{date}(HINCRBY, TTL 7 j) — compteurs journaliers par outil.nika:ipc:metrics:{date}(HINCRBY, TTL 7 j) — compteurs spécifiques IPC.
Le pod observe sans bloquer. Si la connexion Redis flanche, l’appel d’outil réussit quand même — la télémétrie est best-effort, pas critique pour l’exécution.
Le pattern fail-open
Tout le sous-système IPC suit un pattern strict : fail-open avec TTL partout. Un pod qui ne peut pas joindre Redis :
- continue son exécution locale ;
- log l’erreur en local (fichier dans
logs/) ; - n’écrit pas de message bus JSONL pendant la durée du downtime ;
- reprend les acks normaux quand Redis revient.
Aucun pod ne doit jamais se bloquer parce qu’un système annexe est lent ou indisponible. C’est une décision de design conservatrice, justifiée par le fait que les pods tournent souvent en boucle longue (heures), et que tout hang silencieux finit par coûter cher en débogage.
En une phrase
L’IPC de Nika OS est conçu pour que des dizaines de pods coexistent sans se marcher dessus, sans saturer la mémoire d’Alpha, et sans tomber en cascade si un composant flanche. Redis porte le temps réel ; Qdrant porte la mémoire ; JSONL porte la preuve.