DOCS v2.1.0
← Accueil ← Home

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

  • APIhttps://api.bundlefabric.org
  • WebUIhttps://app.bundlefabric.org
  • Swaggerhttps://api.bundlefabric.org/docs
  • Registryhttps://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

ServiceContainerPortRôleRole
bundlefabric-apibundlefabric-api:2.019100Orchestrateur FastAPI principalMain FastAPI orchestrator
DeerFlow LangGraphdeer-flow-langgraph2024Moteur d'exécution multi-agents LangGraphLangGraph multi-agent execution engine
DeerFlow Gatewaydeer-flow-gateway8001API models/MCP/skills DeerFlowDeerFlow models/MCP/skills API
Qdrantqdrant6333Vector DB — RAG bundlesVector DB — bundle RAG
Ollamaollama11434LLMs locaux (qwen2.5, nomic-embed-text)Local LLMs (qwen2.5, nomic-embed-text)
Prometheusbundlefabric-prometheus19190Métriques systèmeSystem 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

💡
Le streaming SSE est disponible uniquement via Tailscale (réseau privé). Il tente d'abord DeerFlow LangGraph, puis bascule sur Claude Haiku si timeout.
SSE streaming is available via Tailscale only (private network). It first tries DeerFlow LangGraph, then falls back to Claude Haiku on timeout.
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.

POST /auth/token public Échanger une clé API contre un JWT Exchange API key for JWT

Body

FieldTypeDescriptionDescription
api_keyrequiredstringClé API au format bf_name_hexAPI 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

GET /health public Vérification de santé Health check
{"status": "ok", "version": "2.1.0", "uptime_seconds": 3600}
GET /status public Statut complet du système Full system status
{
  "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

GET /bundles auth Lister tous les bundles List all bundles
{"bundles": [{"id": "bundle-linux-ops", "name": "Linux Operations Expert", ...}]}
GET /bundles/{bundle_id} auth Détails d'un bundle Bundle details

Path params

ParamTypeDescriptionDescription
bundle_idreqstringIdentifiant du bundleBundle identifier
GET /bundles/public public Registry public (bundles avec public: true) Public registry (bundles with public: true)
{"bundles": [...], "count": 2, "registry": "bundlefabric.org"}
POST /bundles/create auth Créer un nouveau bundle Create a new bundle

Le body contient le manifest YAML complet. Voir la section Bundle Format.

The body contains the full YAML manifest. See the Bundle Format section.

PUT /bundles/{bundle_id} auth Mettre à jour un bundle Update a bundle

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.

DELETE /bundles/{bundle_id} auth Supprimer un bundle Delete a bundle
⚠️
Supprime le répertoire du bundle et le désindexe de Qdrant. Irréversible.
Deletes the bundle directory and removes it from Qdrant. Irreversible.
POST /bundles/fuse admin Fusionner deux bundles Fuse two bundles

Body

{
  "bundle_id_a": "bundle-linux-ops",
  "bundle_id_b": "bundle-gtm-debug",
  "strategy": "union"   // "union" | "intersection" | "weighted"
}

Orchestration

POST /intent auth Extraire l'intention d'un texte Extract intent from text

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"
}
POST /resolve public Résoudre les bundles pour une intention Resolve bundles for an intent

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
    }
  ]
}
POST /execute auth Exécuter un bundle (synchrone) Execute a bundle (synchronous)

Body

FieldTypeDescriptionDescription
bundle_idreqstringID du bundleBundle ID
intent_textreqstringTexte de l'intentionIntent text
workflow_idoptstringWorkflow DeerFlow spécifiqueSpecific 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
  }
}
ℹ️
Timeout : L'inférence Ollama CPU peut prendre 60-120s. Le timeout global est configurable via DEERFLOW_TIMEOUT (défaut : 120s).
Timeout: Ollama CPU inference can take 60-120s. The global timeout is configurable via DEERFLOW_TIMEOUT (default: 120s).

Streaming SSE

🔒
Les endpoints /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.
The /execute/stream and /execute/deerflow/stream endpoints require Tailscale access (header X-Tailscale-Access: 1 injected by nginx). Not accessible from the public internet.
POST /execute/deerflow/stream auth + Tailscale Stream DeerFlow → fallback Claude Haiku Stream DeerFlow → Claude Haiku fallback

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 typeDescriptionDescription
type: metaMétadonnées du run (bundle, engine…)Run metadata (bundle, engine…)
type: statusMessage de statutStatus message
type: tokenToken de réponse LLMLLM response token
type: heartbeatKeepalive pendant l'inférenceKeepalive during inference
type: completeFin normale du stream DeerFlowNormal DeerFlow stream end
event: errorErreur — déclenche le fallbackError — triggers fallback
event: doneFin du stream (tous moteurs)End of stream (all engines)
POST /execute/stream auth + Tailscale Stream Claude Haiku uniquement Claude Haiku stream only

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

GET /history auth Historique des exécutions Execution history

Query params

ParamTypeDescriptionDescription
limitoptintNombre max (défaut: 50)Max items (default: 50)
bundle_idoptstringFiltrer par bundleFilter by bundle
GET /history/{exec_id} auth Détails d'une exécution Execution details
{
  "id": "uuid",
  "bundle_id": "bundle-linux-ops",
  "intent_text": "...",
  "output": "...",
  "status": "success",
  "duration_ms": 1200,
  "created_at": "2026-03-18T20:00:00Z"
}

DeerFlow

GET /deerflow/status auth Statut DeerFlow LangGraph DeerFlow LangGraph status
{
  "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}
}
⚠️
Important : Le champ context.thread_id est obligatoire. Sans lui, le ThreadDataMiddleware de DeerFlow lève une AttributeError.
Important: The context.thread_id field is mandatory. Without it, DeerFlow's ThreadDataMiddleware raises an AttributeError.

Admin

GET /admin/users admin Lister les utilisateurs List users
{"users": [{"username": "alice", "role": "admin", "api_key_masked": "bf_alice_xxxx****"}]}
POST /admin/users admin Créer un utilisateur Create user
{"username": "alice", "role": "user"}  // Retourne la clé API en clair
DELETE /admin/users/{username} admin Supprimer un utilisateur Delete user
POST /admin/jwt/rotate admin Rotation du secret JWT Rotate JWT secret

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

bundle-<name>-v<version>/ ├── manifest.yaml # REQUIRED — complete identity ├── identity/ │ ├── bundle.id # SHA-256 hash of content │ └── bundle.sig # ed25519 signature ├── prompts/ │ ├── system.md # REQUIRED — system prompt │ └── workflows.yaml # DeerFlow workflows └── rag/ ├── doctrine.md # Fundamental domain rules ├── cookbook.md # Operational recipes ├── incidents.md # Errors → causes → fixes └── reference.md # Filtered official docs

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.

×0.4
Freshness
Fraîcheur : date de dernière mise à jour vs. date actuelle
Recency: last update date vs. current date
×0.3
Usage
Fréquence d'utilisation : auto-incrémentée à chaque exécution
Usage frequency: auto-incremented on every execution
×0.3
Ecosystem
Alignement avec l'écosystème actuel des outils
Alignment with current tool ecosystem
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

VariableDéfautDefaultDescriptionDescription
JWT_SECRETautoSecret JWT (rotation via API)JWT secret (rotatable via API)
DEERFLOW_URLhttp://deer-flow-gateway:8001URL gateway DeerFlowDeerFlow gateway URL
LANGGRAPH_URLhttp://deer-flow-langgraph:2024URL serveur LangGraphLangGraph server URL
DEERFLOW_TIMEOUT120Timeout global (secondes)Global timeout (seconds)
LANGGRAPH_FIRST_TOKEN_TIMEOUT90Timeout premier token SSEFirst SSE token timeout
OLLAMA_URLhttp://ollama:11434URL OllamaOllama URL
BUNDLES_DIR/app/bundlesRépertoire des bundlesBundles directory
GITHUB_CLIENT_IDOAuth GitHub (optionnel)GitHub OAuth (optional)

Sécurité Security

Modèle d'accès Access model

CoucheLayerProtectionProtection
Internet publicPublic internetJWT requis, HTTPS only, headers sécuritéJWT required, HTTPS only, security headers
TailscaleX-Tailscale-Access: 1 — streaming SSE activé
Endpoints adminAdmin endpointsJWT + rôle admin requisJWT + admin role required
Bundles publicsPublic 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.

Les headers HTTP de sécurité sont configurés : Strict-Transport-Security, X-Content-Type-Options, X-Frame-Options.
HTTP security headers are configured: Strict-Transport-Security, X-Content-Type-Options, X-Frame-Options.