BundleFabric — OS Cognitif BundleFabric — Cognitive OS
BundleFabric est un système d'exploitation cognitif self-hosted qui traduit des intentions en langage naturel en actions IA spécialisées grâce à un système de bundles — des contextes cognitifs portables et versionnables.
La philosophie centrale : une intention humaine ne doit jamais être mappée à un outil rigide, mais à un contexte cognitif dynamique chargé à la demande dans un moteur d'exécution LLM.
BundleFabric is a self-hosted Cognitive OS that translates natural language intentions into specialized AI actions through a system of bundles — portable, versioned cognitive contexts.
Core philosophy: a human intention should never be mapped to a rigid tool, but to a dynamic cognitive context loaded on-demand into an LLM execution engine.
Fonctionnalités clés Key Features
- Intent extraction — extraction par mots-clés (instantanée) + enrichissement Ollama (async) + Claude Haiku (Tailscale uniquement)
- Intent extraction — keyword extraction (instant) + Ollama enrichment (async) + Claude Haiku (Tailscale only)
- RAG bundle resolution — recherche vectorielle Qdrant, classement par score TPS
- RAG bundle resolution — Qdrant vector search, ranked by TPS score
- SSE streaming — tokens en temps réel via Claude Haiku ou DeerFlow LangGraph
- SSE streaming — real-time token streaming via Claude Haiku or DeerFlow LangGraph
- Historique d'exécution — persistance SQLite, replay depuis le WebUI
- Execution history — SQLite persistence, replay from WebUI
- Score TPS — classement automatique des bundles par pertinence temporelle
- TPS scoring — automatic bundle ranking by temporal pertinence
- CRUD bundles — créer, modifier, supprimer depuis le WebUI
- Bundle CRUD — create, edit, delete from WebUI
- Multi-utilisateurs — auth JWT, comptes gérés par admin
- Multi-user — JWT auth, admin-managed accounts
- GitHub OAuth — connexion via GitHub, provisioning automatique
- GitHub OAuth — login via GitHub, auto-provision users
- Friend Mesh — réseau P2P pour partager bundles entre nœuds
- Friend Mesh — P2P network to share bundles across nodes
- Meta-Agent — suggère et crée automatiquement de nouveaux bundles
- Meta-Agent — suggests and auto-creates new bundles
URLs publiques Public URLs
- API —
https://api.bundlefabric.org - WebUI —
https://app.bundlefabric.org - Swagger —
https://api.bundlefabric.org/docs - Registry —
https://bundlefabric.org
Architecture
BundleFabric est organisé en couches. L'orchestrateur central traduit l'intention en bundle, puis délègue l'exécution à DeerFlow (LangGraph multi-agents).
BundleFabric is organized in layers. The central orchestrator translates intent into bundles, then delegates execution to DeerFlow (LangGraph multi-agents).
Intention humaine (langage naturel)
│
▼
┌─────────────────────────────────────────┐
│ IntentEngine │
│ keywords (0ms) → Ollama (async) → │
│ Claude Haiku (Tailscale, si dispo) │
└─────────────────┬───────────────────────┘
│ Intent {goal, domains, tools, complexity}
▼
┌─────────────────────────────────────────┐
│ RAG Resolver (Qdrant) │
│ Recherche vectorielle → Top-K bundles │
│ classés par score TPS │
└─────────────────┬───────────────────────┘
│ BundleManifest sélectionné
▼
┌─────────────────────────────────────────┐
│ DeerFlow LangGraph │
│ deer-flow-langgraph:2024 │
│ Planner → Agents → Tools → Sandbox │
│ + Fallback Claude Haiku si timeout │
└─────────────────┬───────────────────────┘
│ ExecutionResult
▼
Réponse (JSON ou SSE)
Human intention (natural language)
│
▼
┌─────────────────────────────────────────┐
│ IntentEngine │
│ keywords (0ms) → Ollama (async) → │
│ Claude Haiku (Tailscale, if available) │
└─────────────────┬───────────────────────┘
│ Intent {goal, domains, tools, complexity}
▼
┌─────────────────────────────────────────┐
│ RAG Resolver (Qdrant) │
│ Vector search → Top-K bundles │
│ ranked by TPS score │
└─────────────────┬───────────────────────┘
│ Selected BundleManifest
▼
┌─────────────────────────────────────────┐
│ DeerFlow LangGraph │
│ deer-flow-langgraph:2024 │
│ Planner → Agents → Tools → Sandbox │
│ + Claude Haiku fallback on timeout │
└─────────────────┬───────────────────────┘
│ ExecutionResult
▼
Response (JSON or SSE)
Stack technique Tech stack
| Service | Container | Port | Rôle | Role |
|---|---|---|---|---|
| bundlefabric-api | bundlefabric-api:2.0 | 19100 | Orchestrateur FastAPI principal | Main FastAPI orchestrator |
| DeerFlow LangGraph | deer-flow-langgraph | 2024 | Moteur d'exécution multi-agents LangGraph | LangGraph multi-agent execution engine |
| DeerFlow Gateway | deer-flow-gateway | 8001 | API models/MCP/skills DeerFlow | DeerFlow models/MCP/skills API |
| Qdrant | qdrant | 6333 | Vector DB — RAG bundles | Vector DB — bundle RAG |
| Ollama | ollama | 11434 | LLMs locaux (qwen2.5, nomic-embed-text) | Local LLMs (qwen2.5, nomic-embed-text) |
| Prometheus | bundlefabric-prometheus | 19190 | Métriques système | System metrics |
Quickstart
1. Obtenir un token 1. Get a token
Échangez votre clé API contre un JWT valable 24h :
Exchange your API key for a 24h JWT:
curlcurl -X POST https://api.bundlefabric.org/auth/token \
-H "Content-Type: application/json" \
-d '{"api_key": "bf_yourname_xxxxxxxxxxxx"}'
response{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"username": "yourname",
"role": "user",
"expires_in": 86400
}
2. Lister les bundles 2. List bundles
curlcurl https://api.bundlefabric.org/bundles \
-H "Authorization: Bearer $TOKEN"
3. Exécuter un bundle 3. Execute a bundle
curlcurl -X POST https://api.bundlefabric.org/execute \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"bundle_id": "bundle-linux-ops",
"intent_text": "How do I check disk usage on Linux?"
}'
response{
"status": "success",
"bundle_id": "bundle-linux-ops",
"intent_goal": "Check disk usage on Linux",
"output": "Use `df -h` to display disk usage...",
"deerflow_thread_id": "7f0db0e7-cf28-4e84-815b-6f083178679b",
"metadata": {
"engine": "langgraph",
"bundle_name": "Linux Operations Expert"
}
}
4. Streaming SSE en temps réel 4. Real-time SSE streaming
curlcurl -N -X POST http://<YOUR_TAILSCALE_IP>:19102/execute/deerflow/stream \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"bundle_id": "bundle-linux-ops",
"intent_text": "Optimize nginx configuration for performance"
}'
SSE streamdata: {"type":"status","msg":"🦌 Connexion DeerFlow LangGraph…","engine":"langgraph"}
data: {"type":"status","msg":"Thread LangGraph créé: 4ec53372…"}
data: {"type":"heartbeat","msg":"LangGraph traite… (38s)"}
data: {"type":"status","msg":"⚡ Fallback Claude Haiku…","engine":"claude_haiku"}
data: {"type":"token","content":"To optimize nginx for performance,"}
data: {"type":"token","content":" start by enabling gzip compression..."}
event: done
data: {}
Authentification Authentication
BundleFabric utilise des clés API (obtenues via l'admin) pour générer des tokens JWT valables 24h. Tous les endpoints protégés requièrent le header Authorization: Bearer <token>.
BundleFabric uses API keys (obtained via admin) to generate JWT tokens valid for 24h. All protected endpoints require the Authorization: Bearer <token> header.
Body
| Field | Type | Description | Description |
|---|---|---|---|
| api_keyrequired | string | Clé API au format bf_name_hex | API key in bf_name_hex format |
RéponseResponse
{
"token": "eyJ...",
"username": "string",
"role": "user | admin",
"expires_in": 86400
}
GitHub OAuth
Les utilisateurs peuvent aussi s'authentifier via GitHub OAuth. Le compte est auto-provisionné avec le rôle user à la première connexion.
Users can also authenticate via GitHub OAuth. The account is auto-provisioned with the user role on first login.
GET /auth/oauth/github → redirect vers GitHub
GET /auth/oauth/github/callback → callback, retourne JWT
GET /auth/oauth/providers → liste des providers configurés
Système System
{"status": "ok", "version": "2.1.0", "uptime_seconds": 3600}
{
"status": "ok",
"version": "2.1.0",
"bundles_loaded": 2,
"deerflow": {
"status": "online",
"data": {
"langgraph": {"status": "online", "url": "http://deer-flow-langgraph:2024"},
"gateway": {"status": "online"}
}
},
"qdrant_available": true,
"qdrant_indexed_count": 2,
"claude_available": true
}
Bundles
{"bundles": [{"id": "bundle-linux-ops", "name": "Linux Operations Expert", ...}]}
Path params
| Param | Type | Description | Description |
|---|---|---|---|
| bundle_idreq | string | Identifiant du bundle | Bundle identifier |
{"bundles": [...], "count": 2, "registry": "bundlefabric.org"}
Le body contient le manifest YAML complet. Voir la section Bundle Format.
The body contains the full YAML manifest. See the Bundle Format section.
Remplace le manifest du bundle. Les champs id et temporal sont préservés.
Replaces the bundle manifest. The id and temporal fields are preserved.
Body
{
"bundle_id_a": "bundle-linux-ops",
"bundle_id_b": "bundle-gtm-debug",
"strategy": "union" // "union" | "intersection" | "weighted"
}
Orchestration
Body
{"text": "How do I configure nginx reverse proxy?"}
Response
{
"raw_text": "How do I configure nginx reverse proxy?",
"goal": "Configure nginx as reverse proxy",
"domains": ["linux", "nginx", "devops"],
"tools": ["nginx", "bash"],
"complexity": "intermediate",
"user_level": "developer"
}
Body
{
"intent": {
"raw_text": "nginx reverse proxy",
"goal": "Configure nginx reverse proxy",
"domains": ["nginx"],
"tools": [],
"complexity": "basic",
"user_level": "developer"
},
"top_k": 3,
"filter_archival": true
}
Response
{
"intent_goal": "Configure nginx reverse proxy",
"matches_count": 1,
"matches": [
{
"bundle_id": "bundle-linux-ops",
"bundle_name": "Linux Operations Expert",
"tps_score": 0.885,
"match_score": 0.92
}
]
}
Body
| Field | Type | Description | Description |
|---|---|---|---|
| bundle_idreq | string | ID du bundle | Bundle ID |
| intent_textreq | string | Texte de l'intention | Intent text |
| workflow_idopt | string | Workflow DeerFlow spécifique | Specific DeerFlow workflow |
Response
{
"status": "success | error | timeout",
"bundle_id": "bundle-linux-ops",
"intent_goal": "string",
"output": "string",
"deerflow_thread_id": "uuid",
"error_message": null,
"metadata": {
"engine": "langgraph",
"bundle_name": "string",
"system_prompt_injected": true
}
}
DEERFLOW_TIMEOUT (défaut : 120s).DEERFLOW_TIMEOUT (default: 120s).Streaming SSE
/execute/stream et /execute/deerflow/stream requièrent un accès Tailscale (header X-Tailscale-Access: 1 injecté par nginx). Non accessible depuis internet public./execute/stream and /execute/deerflow/stream endpoints require Tailscale access (header X-Tailscale-Access: 1 injected by nginx). Not accessible from the public internet.Tente d'exécuter via DeerFlow LangGraph. En cas de timeout (90s premier token), bascule automatiquement sur Claude Haiku.
Attempts execution via DeerFlow LangGraph. On first-token timeout (90s), automatically falls back to Claude Haiku.
Événements SSE SSE Events
| Event type | Description | Description |
|---|---|---|
type: meta | Métadonnées du run (bundle, engine…) | Run metadata (bundle, engine…) |
type: status | Message de statut | Status message |
type: token | Token de réponse LLM | LLM response token |
type: heartbeat | Keepalive pendant l'inférence | Keepalive during inference |
type: complete | Fin normale du stream DeerFlow | Normal DeerFlow stream end |
event: error | Erreur — déclenche le fallback | Error — triggers fallback |
event: done | Fin du stream (tous moteurs) | End of stream (all engines) |
Streaming direct via Claude Haiku, sans passer par DeerFlow. Plus rapide, moins de capacités d'agents.
Direct streaming via Claude Haiku, bypassing DeerFlow. Faster, fewer agent capabilities.
History
Query params
| Param | Type | Description | Description |
|---|---|---|---|
| limitopt | int | Nombre max (défaut: 50) | Max items (default: 50) |
| bundle_idopt | string | Filtrer par bundle | Filter by bundle |
{
"id": "uuid",
"bundle_id": "bundle-linux-ops",
"intent_text": "...",
"output": "...",
"status": "success",
"duration_ms": 1200,
"created_at": "2026-03-18T20:00:00Z"
}
DeerFlow
{
"status": "online",
"url": "http://deer-flow-gateway:8001",
"data": {
"langgraph": {"status": "online", "url": "http://deer-flow-langgraph:2024"},
"gateway": {"status": "online"}
}
}
Architecture LangGraph LangGraph Architecture
BundleFabric communique avec DeerFlow via l'API threads/runs de LangGraph :
BundleFabric communicates with DeerFlow via the LangGraph threads/runs API:
POST /threads → Créer un thread (contexte)
POST /threads/{id}/runs/wait → Exécuter (bloquant)
POST /threads/{id}/runs/stream → Exécuter (SSE streaming)
Payload requis :
{
"assistant_id": "bee7d354-...",
"input": {"messages": [...]},
"context": {"thread_id": "<thread_id>"}, ← REQUIS par ThreadDataMiddleware
"stream_mode": ["messages"],
"config": {"recursion_limit": 25}
}
POST /threads → Create a thread (context)
POST /threads/{id}/runs/wait → Execute (blocking)
POST /threads/{id}/runs/stream → Execute (SSE streaming)
Required payload:
{
"assistant_id": "bee7d354-...",
"input": {"messages": [...]},
"context": {"thread_id": "<thread_id>"}, ← REQUIRED by ThreadDataMiddleware
"stream_mode": ["messages"],
"config": {"recursion_limit": 25}
}
context.thread_id est obligatoire. Sans lui, le ThreadDataMiddleware de DeerFlow lève une AttributeError.context.thread_id field is mandatory. Without it, DeerFlow's ThreadDataMiddleware raises an AttributeError.Admin
{"users": [{"username": "alice", "role": "admin", "api_key_masked": "bf_alice_xxxx****"}]}
{"username": "alice", "role": "user"} // Retourne la clé API en clair
Invalide tous les tokens existants. Les utilisateurs devront se réauthentifier.
Invalidates all existing tokens. Users will need to re-authenticate.
Concept Bundle Bundle Concept
Un bundle est un contexte cognitif exécutable, portable et versionnable. Il n'est pas un modèle IA — c'est un contexte chargeable dynamiquement dans DeerFlow.
Bundle IA = modèle_préféré + RAG_contextualisé + agents/outils
+ prompts_système + schémas_cognitifs
A bundle is an executable, portable, versioned cognitive context. It is not an AI model — it is a dynamically loadable context for DeerFlow.
AI Bundle = preferred_model + contextualized_RAG + agents/tools
+ system_prompts + cognitive_schemas
Format Bundle Bundle Format
Arborescence File tree
Manifest YAML complet Full YAML manifest
manifest.yamlid: bundle-linux-ops # unique, kebab-case
name: Linux Operations Expert # display name
version: 1.0.0 # semver
description: Expert Linux/nginx/Docker
author: bundlefabric
license: MIT
public: true # appears in public registry
domains:
- linux
- devops
- docker
- nginx
keywords:
- bash
- shell
- nginx
- docker
- systemd
capabilities:
- bash-scripting
- linux-sysadmin
- process-management
- nginx-configuration
- docker-operations
deerflow_workflow: linux-ops-agent # DeerFlow graph ID (optional)
temporal:
last_updated: "2026-03-17"
freshness_score: 0.9 # 0.0–1.0, auto-computed
usage_count: 10
usage_frequency: 0.52 # auto-incremented on execute
ecosystem_alignment: 0.9
tps_score: 0.885 # computed: see TPS section
status: active # active | archived
TPS Score
Le Temporal Pertinence Score classe automatiquement les bundles lors de la résolution d'une intention. Plus le score est élevé, plus le bundle est sélectionné en priorité.
The Temporal Pertinence Score automatically ranks bundles during intent resolution. Higher score = higher priority selection.
TPS = freshness_score × 0.4 + usage_frequency × 0.3 + ecosystem_alignment × 0.3
Un bundle archivé (status: archived) est exclu de la résolution par défaut. Il peut être réactivé en passant filter_archival: false dans /resolve.
An archived bundle (status: archived) is excluded from resolution by default. It can be re-included by passing filter_archival: false in /resolve.
Friend Mesh
Le Friend Mesh permet de partager des bundles entre plusieurs nœuds BundleFabric via un protocole HTTP gossip. Chaque nœud maintient un registry distribué des bundles disponibles chez ses pairs.
The Friend Mesh enables sharing bundles between multiple BundleFabric nodes via an HTTP gossip protocol. Each node maintains a distributed registry of bundles available at its peers.
# Configuration dans friends.yaml
friends:
- name: "node-paris"
url: "https://api.bundlefabric.org"
api_key: "bf_paris_xxxx"
# Endpoints mesh
GET /mesh/status → statut des pairs
GET /mesh/peers → liste des nœuds connectés
GET /mesh/bundles → tous les bundles du mesh
POST /mesh/bundles/{id}/request → télécharger un bundle pair
# Configuration in friends.yaml
friends:
- name: "node-paris"
url: "https://api.bundlefabric.org"
api_key: "bf_paris_xxxx"
# Mesh endpoints
GET /mesh/status → peer status
GET /mesh/peers → connected nodes
GET /mesh/bundles → all mesh bundles
POST /mesh/bundles/{id}/request → download a peer bundle
Déploiement Deployment
Prérequis Prerequisites
- Docker 24+ & Docker Compose v2
- Python 3.12 (image Docker incluse)
- Python 3.12 (included in Docker image)
- 16 GB RAM minimum recommandés pour Ollama CPU
- 16 GB RAM minimum recommended for Ollama CPU
- Domaine + DNS configurés si accès public
- Domain + DNS configured for public access
Lancement Launch
bash# Cloner et lancer
git clone https://github.com/fbailleux2/bundlefabric
cd bundlefabric
# Configurer les secrets
echo "JWT_SECRET=$(openssl rand -hex 32)" > .env
# Lancer Phase 2 complète (API + Prometheus)
docker compose --profile phase2 up -d
# Vérifier
curl http://localhost:19100/health
Variables d'environnement clés Key environment variables
| Variable | Défaut | Default | Description | Description |
|---|---|---|---|---|
| JWT_SECRET | auto | Secret JWT (rotation via API) | JWT secret (rotatable via API) | |
| DEERFLOW_URL | http://deer-flow-gateway:8001 | URL gateway DeerFlow | DeerFlow gateway URL | |
| LANGGRAPH_URL | http://deer-flow-langgraph:2024 | URL serveur LangGraph | LangGraph server URL | |
| DEERFLOW_TIMEOUT | 120 | Timeout global (secondes) | Global timeout (seconds) | |
| LANGGRAPH_FIRST_TOKEN_TIMEOUT | 90 | Timeout premier token SSE | First SSE token timeout | |
| OLLAMA_URL | http://ollama:11434 | URL Ollama | Ollama URL | |
| BUNDLES_DIR | /app/bundles | Répertoire des bundles | Bundles directory | |
| GITHUB_CLIENT_ID | — | OAuth GitHub (optionnel) | GitHub OAuth (optional) | |
Sécurité Security
Modèle d'accès Access model
| CoucheLayer | Protection | Protection | |
|---|---|---|---|
| Internet public | Public internet | JWT requis, HTTPS only, headers sécurité | JWT required, HTTPS only, security headers |
| Tailscale | X-Tailscale-Access: 1 — streaming SSE activé | ||
| Endpoints admin | Admin endpoints | JWT + rôle admin requis | JWT + admin role required |
| Bundles publics | Public bundles | /bundles/public sans auth | /bundles/public without auth |
Signature des bundles Bundle signing
Chaque bundle peut être signé via ed25519 (identity/bundle.sig). L'endpoint /bundles/{id}/hash expose le hash SHA-256 du contenu pour vérification externe.
Each bundle can be signed via ed25519 (identity/bundle.sig). The /bundles/{id}/hash endpoint exposes the SHA-256 content hash for external verification.
Strict-Transport-Security, X-Content-Type-Options, X-Frame-Options.Strict-Transport-Security, X-Content-Type-Options, X-Frame-Options.