Sur cette page
- 1. Philosophie
- 2. Le mur de la production
- 3. Installation
- 4. Architecture centrale
- 4.1 Décorateurs
- 4.2 Backends de cache
- 5. Modèles de résilience
- 5.1 Disjoncteur
- 5.2 Stale-if-error
- 5.3 Coalescence de requêtes
- 6. Cache sémantique
- 7. Observabilité
- 8. Écosystème et MCP
- 9. CLI et opérations
- 10. Feuille de route
- FAQ
Lorsque vous construisez des agents IA, chaque appel externe — vers un LLM, une API, une base de données — est un appel d'outil. En production, ces appels sont coûteux, peu fiables et lents. ToolOps est aux outils IA ce qu'un Service MeshUne couche d'infrastructure qui gère la communication, la résilience et l'observabilité entre services. est aux microservices : un SDK middleware agnostique qui améliore n'importe quelle fonction Python avec mise en cache, résilience et observabilité — sans aucun changement de logique métier.
1. Philosophie
L'analogie qui décrit le mieux ToolOps est le Service Mesh. Tout comme un Service Mesh — pensez à Istio ou Linkerd — se place entre les microservices pour gérer les tentatives, les délais d'attente et les disjoncteurs de manière transparente, ToolOps se place entre votre agent IA et ses outils. Le code de l'application ne sait rien de la couche d'infrastructure sous-jacente.
"ToolOps est aux outils IA ce qu'un Service Mesh est aux microservices."
Cette séparation des préoccupations est intentionnelle. Les auteurs d'outils doivent se concentrer sur ce que fait un outil, pas sur la gestion de la complexité des systèmes distribués pour l'appeler de manière fiable à l'échelle. ToolOps absorbe cette complexité via une interface de décorateur — un design délibérément choisi pour être la surface d'intégration la plus fine possible.
| Fonctionnalité | Standard @lru_cache |
SDK ToolOps |
|---|---|---|
Support Async / await |
❌ Non supporté | ✅ Natif async |
| Cache sémantiqueMéthode de cache utilisant des embeddings vectoriels pour faire correspondre l'intention d'une requête.En savoir plus → | ❌ Correspondance exacte | ✅ Embeddings vectoriels |
| Cache distribué / persistant | ❌ Mémoire uniquement | ✅ Postgres, Fichier, Mémoire |
| DisjoncteurPatron de conception qui interrompt les requêtes vers un service défaillant pour éviter les pannes en cascade.En savoir plus → & Retries | ❌ Aucun | ✅ Intégré avec backoff |
| Coalescence de requêtesTechnique combinant plusieurs requêtes concurrentes identiques en un seul appel réel.En savoir plus → | ❌ "Thundering herd" | ✅ Diffusion du résultat |
| Repli Stale-if-error | ❌ Lève une exception | ✅ Sert la dernière valeur |
| ObservabilitéCapacité à mesurer l'état interne d'un système via ses sorties (logs, métriques, traces).En savoir plus → (OTELOpenTelemetry. Framework open-source pour générer et collecter des données de télémétrie./Prom) | ❌ Aucune | ✅ Télémétrie structurée |
| Natif IA (MCPModel Context Protocol. Standard ouvert pour connecter les modèles d'IA aux outils et données.En savoir plus →/Frameworks) | ❌ Générique | ✅ Intégrations natives |
2. Le mur de la production
Chaque développeur d'agent frappe le même mur lors du passage de la démo à la production. Les symptômes sont prévisibles : des factures d'API qui augmentent plus vite que l'utilisation, des agents qui plantent à la troisième tentative, des files d'attente de requêtes qui saturent, et des workflows complètement opaques en cas d'échec. ToolOps traite chaque goulot d'étranglement au niveau de la couche infrastructure.
| Problème | Impact Métier | Avec ToolOps |
|---|---|---|
| Appels API redondants | 💸 Pics de coûts x10 | 100 appels → 1 réel + 99 cache hits |
| Requêtes similaires | 💸 Gaspillage de tokens | Match sémantique → même résultat |
| Instabilité des API | 💥 Crashs & boucles d'agents | Disjoncteur + auto-retry |
| Pics de concurrence | 🐢 Surcharge serveur | Coalescence → 1 appel réel |
| Visibilité zéro | 🌑 Opérations aveugles | JSON structuré + traces OTEL |
3. Installation
ToolOps est disponible sur PyPI. Le paquet principal est sans dépendance et s'installe en quelques secondes. Des options supplémentaires débloquent la persistance Postgres, les embeddings sémantiques et OpenTelemetry.
# La syntaxe [extras] nécessite des guillemets sous zsh/bash
pip install "toolops[all]"
# Extras modulaires
pip install "toolops[postgres,semantic,otel]"
:: Utilisez des doubles guillemets pour les extras
pip install "toolops[all]"
:: Utilisation du launcher
py -m pip install "toolops[all]"
Note sur les terminaux
Les terminaux comme zsh traitent les crochets comme des motifs de globbing. Enveloppez toujours le nom du paquet entre guillemets : "toolops[all]" pour éviter les erreurs no matches found.
Il est fortement recommandé d'installer ToolOps dans un environnement virtuel pour éviter les conflits de dépendances :
# Créer et activer (.venv)
python -m venv .venv
source .venv/bin/activate # Linux/macOS
# .venv\Scripts\activate # Windows
# Installer et vérifier
pip install "toolops[all]"
toolops doctor
L'installation minimale est intentionnelle : ne récupérez que ce dont votre environnement a besoin. L'option
[all] est recommandée pour les déploiements en production où vous avez besoin d'un cache
persistant et du traçage distribué dès le premier jour.
4. Architecture centrale
L'architecture comporte deux couches : une interface de décorateur qui se place sur vos fonctions d'outils, et un système de backend interchangeable qui gère le stockage et les embeddings. Les deux couches sont entièrement découplées — vous pouvez changer de backend sans modifier une seule ligne de code de l'outil.
4.1 Décorateurs
ToolOps fournit deux décorateurs qui correspondent aux deux catégories d'opérations d'outils :
@readonly — opérations de lecture avec cache
recommandé pour lectures
from toolops import readonly, cache_manager
from toolops.cache import MemoryCache
cache_manager.register("memory", MemoryCache(), is_default=True)
@readonly(cache_backend="memory", cache_ttl=3600, retry_count=3)
async def get_market_data(ticker: str) -> dict:
return await api.fetch(ticker) # Mis en cache, réessayé et tracé automatiquement.
# Mise en cache automatique et tentative en cas d'échec.
@sideeffect — opérations d'écriture avec résilience
pour écritures
@sideeffect(circuit_breaker=True, timeout=5.0, retry_count=2)
async def execute_trade(order: dict) -> bool:
return await broker.submit(order) # Protégé par le disjoncteur et le timeout.
# Pas de cache — mais protégé par le disjoncteur et le timeout.
La distinction entre lecture et écriture est un concept de premier rang dans ToolOps. Les lectures sont idempotentes et sûres à mettre en cache et à réessayer. Les écritures ne le sont pas — elles reçoivent uniquement des modèles de résilience, jamais de tentatives automatiques qui pourraient causer des doubles soumissions.
4.2 Backends de cache
Enregistrez les backends une seule fois au démarrage de l'application, puis référencez-les par leur nom dans tous vos décorateurs. Plusieurs backends peuvent coexister — une couche rapide en mémoire pour les données chaudes, Postgres pour les pistes d'audit persistantes, et une couche sémantique pour les charges de travail NLP.
| Backend | Option d'installation | Idéal pour |
|---|---|---|
MemoryCache |
— (coeur) | Développement, test, déploiements à processus unique |
PostgresCache |
[postgres] |
Cache persistant avec piste d'audit complète entre les redémarrages |
FileCache |
— (coeur) | Persistance locale légère sans base de données |
SemanticCache |
[semantic] |
Pipelines NLP et RAG — intention matching via embeddings |
from toolops import cache_manager
from toolops.cache import MemoryCache, PostgresCache
# Couche par défaut rapide
cache_manager.register("memory", MemoryCache(), is_default=True)
# Couche persistante pour les opérations sensibles
cache_manager.register("postgres", PostgresCache(dsn=DATABASE_URL))
5. Modèles de résilience
Au-delà des simples blocs try/except, ToolOps implémente trois modèles déterministes tirés de l'ingénierie des systèmes distribués. Ensemble, ils garantissent qu'un agent n'est jamais piégé dans une boucle d'échec, n'épuise jamais son budget API sur un service dégradé, et ne sert jamais de données périmées quand l'amont est sain.
5.1 Disjoncteur
Le modèle du disjoncteur arrête tous les appels vers un service défaillant après un seuil d'échec configurable. Une fois ouvert, le disjoncteur échoue rapidement — renvoyant une erreur immédiatement plutôt que d'attendre un délai d'attente — et entre dans une fenêtre de récupération avant de tenter de rétablir la connexion. Cela empêche un seul outil défaillant de provoquer l'échec complet de l'agent.
@readonly(
circuit_breaker=True,
circuit_failure_threshold=5, # s'ouvre après 5 échecs consécutifs
circuit_recovery_timeout=60 # réessaie après 60 secondes
)
async def get_exchange_rates() -> dict:
return await forex_api.fetch()
5.2 Stale-if-error
Lorsqu'un service amont échoue et qu'aucune donnée en direct ne peut être récupérée, ToolOps peut automatiquement revenir à la dernière bonne valeur connue du cache — même si cette valeur a dépassé son TTL normal. C'est l'équivalent production de "servir quelque chose d'utile plutôt que de planter".
@readonly(
cache_ttl=3600,
stale_if_error=True,
stale_ttl=86400 # sert des données périmées jusqu'à 24h en cas d'échec
)
async def get_exchange_rates() -> dict:
return await forex_api.fetch()
5.3 Coalescence de requêtes
Lorsque plusieurs instances d'agents appellent le même outil simultanément — un modèle courant dans les pipelines multi-agents — ToolOps détecte la requête en cours et retient les appelants suivants jusqu'à ce que la première se termine. Le résultat unique est ensuite diffusé à tous les appelants en attente. Sous une forte concurrence, cela réduit N appels en amont à exactement un.
Impact
Dans un benchmark avec 50 appels d'agents concurrents au même outil météo, la coalescence de requêtes a réduit les appels d'API amont de 50 à 1 — une réduction de 98% de la consommation de crédits sans aucun changement pour les agents appelants.
6. Cache sémantique
Les caches traditionnels fonctionnent sur l'égalité exacte des clés. Cela fonctionne pour les systèmes déterministes, mas les agents ne sont pas des systèmes déterministes — la même intention de l'utilisateur apparaît sous des dizaines de formulations différentes. ToolOps utilise des embeddings vectoriels pour comprendre le sens d'un appel d'outil, pas seulement ses arguments littéraux. Deux requêtes qui expriment la même intention retournent le même résultat mis en cache.
— Appel 1 (échec de cache → appel API réel)
query: "Quel est le statut de la facture #442 ?"
— Appel 2 (similarité sémantique : 0.97 → hit de cache)
query: "Vérifie le statut actuel pour la facture 442"
— Appel 3 (similarité sémantique : 0.94 → hit de cache)
query: "Facture 442 — est-elle payée ?"
from toolops.cache import SemanticCache, SentenceTransformerEmbedder
embedder = SentenceTransformerEmbedder("all-MiniLM-L6-v2")
semantic = SemanticCache(embedder=embedder, threshold=0.92)
cache_manager.register("semantic", semantic)
@readonly(cache_backend="semantic")
async def ask_agent(query: str) -> str:
return await llm.complete(query)
# Réduit la latence LLM jusqu'à 90% sur les modèles d'intention répétés.
Le seuil de similarité (0.92 dans l'exemple ci-dessus) est le principal levier de réglage. Des
valeurs plus élevées nécessitent un alignement sémantique plus étroit ; des valeurs plus basses sont plus
agressives. La bonne valeur dépend de la variation acceptable dans le domaine d'entrée de votre outil — une
recherche factuelle tolère un seuil plus élevé qu'une tâche de génération créative.
7. Observabilité
Le débogage de workflows d'agents non déterministes nécessite une instrumentation plus profonde que le simple logging au niveau applicatif. ToolOps émet une télémétrie structurée à chaque étape du cycle de vie de l'outil — hits, misses, retries, transitions d'état du disjoncteur — vous offrant une piste d'audit complète sans aucune instrumentation manuelle.
8. Écosystème et MCP
Les outils ToolOps sont de simples fonctions Python. Ce choix de conception n'est pas accidentel — cela signifie qu'ils fonctionnent nativement avec chaque framework d'agent qui accepte des callables Python, sans code adaptateur et sans configuration spécifique au framework.
| Framework | Type d'intégration | Statut |
|---|---|---|
| LangChain / LangGraph | Helper intégré | Disponible |
| CrewAI | Helper intégré | Disponible |
| LlamaIndex | Helper intégré | Disponible |
| Model Context Protocol (MCP) | Helper intégré | Disponible |
| PydanticAI | Compatibilité générale | Disponible |
| AutoGPT et frameworks personnalisés | N'importe quel callable Python | Disponible |
L'intégration MCP mérite une mention particulière. ToolOps inclut un adaptateur intégré qui expose n'importe quel outil décoré comme une définition compatible MCP — sans écrire une seule ligne de JSON Schema. Cela signifie que vos outils résilients et de qualité production sont disponibles instantanément pour Claude Desktop, Cursor ou tout hôte compatible MCP.
from toolops.integrations.mcp import MCPIntegration
# get_weather est déjà décoré avec @readonly
definition = MCPIntegration.to_mcp_definition(get_weather)
# → Définition d'outil compatible MCP, prête pour Claude Desktop ou Cursor.
9. CLI et opérations
ToolOps est livré avec un outil en ligne de commande pour inspecter et gérer votre infrastructure d'outils en production. Le CLI est conçu pour les opérateurs et les pipelines CI — pas seulement pour les développeurs.
# Lister toutes les commandes disponibles
toolops --help
# Vérifier la santé du système et la disponibilité des backends
toolops doctor
# Voir les statistiques de cache en temps réel
toolops stats --app my_app:setup_toolops
# Effacer un backend de cache spécifique
toolops clear postgres --app my_app:setup_toolops
La commande toolops doctor est particulièrement utile dans les pipelines de déploiement : elle
valide la connectivité du backend, vérifie la disponibilité du modèle d'embedding et rapporte l'état du
disjoncteur — un test de préparation que vous pouvez brancher directement sur votre endpoint de santé.
10. Feuille de route
ToolOps est en développement actif. Les capacités suivantes sont prévues pour les prochaines versions, classées par livraison prévue. Les contributions et retours sur la priorisation sont les bienvenus via GitHub.
- Tableau de bord Web. Métriques en temps réel, attribution des coûts et taux de hit du cache dans une interface web — aucune configuration Prometheus ou Grafana requise.
- Contrôle du budget. Limites strictes sur les coûts d'API induits par les outils par heure ou par jour, configurables par outil et par backend.
- Serveur MCP natif. Déploiement en un clic des outils ToolOps en tant qu'hôte MCP autonome — aucune configuration Claude Desktop requise.
- Middleware de streaming. Support complet pour le streaming des sorties d'outils, permettant la génération de réponses en temps réel dans les pipelines d'agents.
- Nouveaux Backends. Support pour MariaDB, ChromaDB et Pinecone — étendant les options de cache persistant et natif vecteur.
Participez
ToolOps est open source sous licence Apache 2.0. Mettez une étoile au dépôt, ouvrez un ticket ou soumettez une pull request sur GitHub. Le projet est construit publiquement — les priorités de la feuille de route sont façonnées par les cas d'utilisation réels de la communauté.
Questions fréquemment posées
Pourquoi utiliser ToolOps plutôt que les outils intégrés des frameworks ?
ToolOps est agnostique au framework. Alors que LangChain ou CrewAI ont une logique de tentative de base, ToolOps fournit des modèles industriels comme les Disjoncteurs, la Coalescence de requêtes et le Cache Sémantique qui fonctionnent avec n'importe quel outil Python sans coût de migration.
Que se passe-t-il si mon API est hors service ?
ToolOps protège votre système de trois manières : les Disjoncteurs arrêtent le bombardement de requêtes, les Tentatives Automatiques gèrent les pannes temporaires, et le repli Stale-if-Error peut servir la dernière valeur connue du cache pour que votre agent continue de fonctionner.
Comment la coalescence de requêtes empêche-t-elle les "Thundering Herds" ?
Si 50 agents appellent le même outil simultanément lors d'un échec de cache, ToolOps exécute l'appel API réel une seule fois et diffuse le résultat aux 50 appelants. Cela évite de saturer les limites de débit de votre API amont.
Pourquoi j'obtiens "zsh: no matches found" lors de l'installation ?
Les terminaux comme zsh et bash traitent les crochets [] comme des
caractères de globbing. Vous devez envelopper la commande d'installation entre guillemets : pip install "toolops[all]".
Est-ce que cela fonctionne avec LangGraph et MCP ?
Oui. ToolOps est conçu comme une base pour les serveurs Model Context Protocol (MCP) et les agents stateful LangGraph. Il fournit l'infrastructure industrielle qui manque nativement à ces frameworks.