roxabi-factory

Le moteur d'agents qui fait tourner les bots Roxabi — un cœur hexagonal, hub-and-spoke sur un bus de messages NATS, des pools d'agents isolés par scope, et une flotte de workers de capacité. Il tourne 24/7 sur un matériel que tu possèdes et relie tes plateformes de chat à des agents IA que tu maîtrises. Aucun verrouillage cloud, aucun abonnement, tes données restent sur tes machines.

PythonNATSAGPL-3.0
01

Ce que c'est

La plupart des assistants IA personnels sont hébergés dans le cloud : tes données quittent ta machine, tes conversations dorment sur les serveurs d'un autre, et le service disparaît dès qu'une entreprise pivote. roxabi-factory inverse ça. C'est un moteur d'agents que tu exécutes toi-même — un serveur maison, une machine toujours allumée, n'importe quoi — qui câble tes plateformes de chat préférées à des agents IA que tu possèdes de bout en bout.

La forme est délibérée : un cœur hexagonal (ports & adaptateurs) pour que le domaine ne dépende jamais d'une plateforme, d'un transport ou d'un modèle ; une topologie hub-and-spoke pour que canaux, agents et workers soient des processus indépendants qui ne se rencontrent que sur un bus. Change de modèle en TOML, ajoute un canal comme adaptateur, branche un worker sur le fil — le cœur ne bouge pas.

Les contrats durables, ce sont le cœur et le bus, pas le modèle ni la plateforme. Tout ce qui est hors de l'hexagone est un adaptateur remplaçable.

02

Hub and spoke

Les adaptateurs de canaux tournent comme des processus séparés. Ils normalisent un message entrant et le publient sur NATS ; le hub souscrit, route chaque message vers le bon agent via une RoutingKey(platform, bot_id, scope_id) typée, et la réponse de l'agent repart sur le bus vers l'adaptateur qui la délivre. Quatre processus indépendants en production — hub, Telegram, Discord, pool de workers — un seul processus avec bus embarqué en développement.

factory-telegram aiogram · polling/webhook factory-discord discord.py · gateway factory-hub RoutingKey typée (platform, bot, scope) bus de messages NATS pools d'agents un par scope de conversation entrant sortant
Les adaptateurs publient l'entrant, le hub route par clé typée vers un pool par scope, les réponses repartent — chaque saut est un sujet NATS, donc chaque boîte est un processus indépendant et remplaçable.

Le routage est concurrent à l'image des conversations : séquentiel par scope (une asyncio.Task par chat, thread ou canal), parallèle entre scopes, avec une file bornée pour la contre-pression. Plusieurs bots peuvent partager une plateforme, chacun lié à son propre agent.

03

Agents & mémoire

Un agent est piloté par config — persona, voix, modèle et passthroughs vivent dans un seed TOML, puis dans un store SQLite une fois initialisé. Chaque scope de conversation reçoit son propre pool isolé, deux chats ne partagent donc jamais d'état. La sélection de modèle peut router selon la complexité, envoyant les tours simples à un petit modèle et les durs à un grand.

La mémoire est en couches, pas une transcription unique :

NiveauCe qu'il garde
WorkingLa fenêtre de tours en cours, compactée à mesure qu'elle se remplit.
SessionLa conversation courante.
ÉpisodiqueLes conversations passées, rappelées à la référence.
SémantiqueLes faits durables — SQLite FTS5 + embeddings.
ProcéduraleLe savoir-faire appris : les gestes qui ont marché.

Les commandes de session bouclent la boucle entre conversation et connaissance — /vault-add, /explain, /summarize, /search récupèrent une source, la passent au modèle et réécrivent le résultat dans le vault. Un niveau de confiance par adaptateur (owner, trusted, public, blocked) et un garde anti-injection contrôlent ce que chaque expéditeur peut atteindre.

04

Une flotte de workers

Les capacités que le moteur ne compile pas en dur arrivent comme des workers sur le bus. Un worker est un service longue durée qui expose un ou plusieurs outils ; il s'enregistre par heartbeat, et pour la boucle de raisonnement de l'agent un outil distant et un outil intégré sont identiques — même forme, même type de résultat, le transport invisible en dessous.

C'est exactement ainsi que voiceCLI se branche : il tourne comme worker voix exposant voice.tts et voice.stt, le modèle se charge donc une fois sur une machine GPU et n'importe quel agent de la factory peut parler ou écouter en publiant une requête — sans GPU sur la machine appelante. Génération d'images, routage LLM et d'autres satellites de capacité s'attachent de la même manière.

Un worker est un service qui expose des outils — pas un paquet d'outils. Un worker, plusieurs outils ; le bus rend un appel distant indiscernable d'un appel intégré.

05

Où ça va

Le substrat — le bus, les contrats typés, le pool de workers, le scheduler — tourne déjà en production. La couche suivante, ce sont les jobs : transformer l'activité en contenu, le publier, et faire tourner la boucle autour, sous garde humaine jusqu'à ce que la portée soit mesurée. La valeur avant le framework ; des primitives, pas une machine générale plantée devant sa première unité de travail.

Le raisonnement complet — pourquoi un worker n'est pas un outil, les cinq couches d'outil, l'ordre de construction — est détaillé à part.

06

Lance-le

Prérequis : Python 3.12 et le gestionnaire de paquets uv. En développement, une seule commande lance chaque processus dans un seul, avec un serveur NATS embarqué ; en production, le hub, les adaptateurs de canaux et le pool de workers tournent chacun dans leur propre conteneur.

uv sync              # installation
factory start        # dev : tous les processus + NATS embarqué, un seul process
factory agent init   # seed un agent depuis son TOML vers le store

Le cœur, les adaptateurs, le SDK de transport et les schémas de contrats sont tous en accès ouvert.