Skip to main content

The Industrial-Grade Resilience & Efficiency Layer for AI Agent Tools

Project description


ToolOps Logo

ToolOps

The Industrial-Grade Resilience & Efficiency Layer for AI Agent Tools

PyPI version Python Tests Coverage PyPI Downloads License GitHub Stars

Build production-ready AI agents. Stop writing infrastructure boilerplate.

Website · Documentation · Quickstart · Changelog


⚡ 30-Second Pitch

"ToolOps is to AI Tools what a Service Mesh is to Microservices."

When you build AI agents, external calls (LLMs, APIs, DBs) are expensive, unreliable, and slow. ToolOps eliminates the boilerplate. It is a framework-agnostic middleware SDK that wraps any Python function in a single decorator, instantly upgrading it with caching, resilience, observability, and concurrency control.

# BEFORE ToolOps: 80+ lines of cache managers, retry logic, circuit breakers...

# AFTER ToolOps:
@readonly(cache_backend="semantic", cache_ttl=3600, retry_count=3)
async def ask_llm(query: str) -> str:
    return await llm.complete(query)  # Automatically cached, retried, and traced

🚀 Benchmarks & Impact

  • 90% reduction in LLM calls via Semantic Caching.
  • <5ms overhead per tool call execution.
  • 0 code changes to your core business logic.

⚖️ Why ToolOps?

Every agent developer hits a wall when moving from demo to production. Here is how ToolOps compares to standard alternatives:

Feature Standard @lru_cache Framework-Native 🚀 ToolOps v1.0.0
Async / await support ✅ Native
Semantic (meaning-aware) cache ⚠️ Basic ✅ Advanced Embeddings
Distributed / Persistent cache ⚠️ Varies ✅ Postgres, SQLite, MySQL, Valkey/Redis
Circuit Breaker ✅ Native
Automatic Retries w/ Backoff ⚠️ Plugin required ✅ Native
Request Coalescing (Anti-Thundering Herd) ✅ Native
Stale-if-error Fallback ✅ Native
Security (SHA-256 keys, Auto-masking) ✅ Native
OpenTelemetry & Prometheus ⚠️ Callbacks needed ✅ Native
Framework Agnostic ❌ Locked-in ✅ 100% Universal

📦 Installation

ToolOps is fully batteries-included. Installing it installs all cache backends (Memory, File, SQLite, Valkey, Redis, MySQL/MariaDB, Postgres, and Semantic), resilience features, and OpenTelemetry/Prometheus observability tooling by default.

pip install toolops

💻 OS-Specific Guides

We strongly recommend isolating your project in a virtual environment.

🐧 Linux & 🍎 macOS

# 1. Create and activate a virtual environment
python -m venv .venv
source .venv/bin/activate

# 2. Install ToolOps
pip install toolops

# 3. Verify installation
toolops doctor

🪟 Windows (PowerShell)

# 1. Create and activate a virtual environment
python -m venv .venv
.venv\Scripts\Activate.ps1

# 2. Install ToolOps
pip install toolops

# 3. Verify installation
toolops doctor

🪟 Windows (Command Prompt)

:: 1. Create and activate a virtual environment
python -m venv .venv
.venv\Scripts\activate.bat

:: 2. Install ToolOps
pip install toolops

:: 3. Verify installation
toolops doctor

🚀 Quickstart

This minimal example gets you from install to a working, cached, resilient tool in under 2 minutes.

# Imports
import asyncio

from toolops.cache import MemoryCache
from toolops import readonly, sideeffect, cache_manager


# Step 1: Register a cache backend (do this once at startup)
cache_manager.register("memory", MemoryCache(), is_default=True)


# Step 2: Decorate any async function with @readonly for read operations
@readonly(cache_backend="memory", cache_ttl=3600, retry_count=3)
async def fetch_weather(city: str) -> dict:
    # Simulate an external API call
    return {"city": city, "temp": 22, "condition": "sunny"}


# Step 3: Decorate write operations with @sideeffect (no caching, but protected)
@sideeffect(circuit_breaker=True, timeout=5.0, retry_count=2)
async def send_alert(message: str) -> bool:
    # Simulate sending a notification
    print(f"Alert sent: {message}")
    return True


async def main():
    # First call hits the API
    result = await fetch_weather("Paris")
    print(f"First call (live): {result}")

    # Second call is served from cache — <5ms latency, 0 API calls
    result = await fetch_weather("Paris")
    print(f"Second call (cached): {result}")

    # Write operation with circuit breaker protection
    await send_alert("Agent completed successfully.")

asyncio.run(main())

🧠 Core Concepts

1. Cache Backends

Register backends once at application startup, then reference them by name. ToolOps supports multiple backends simultaneously.

from toolops import cache_manager
from toolops.cache import (
    MemoryCache,
    FileCache,
    PostgresCache,
    SQLiteCache,
    ValkeyCache,
    RedisCache,
    MySQLCache,
    SemanticCache,
    SentenceTransformerEmbedder,
)


# In-memory: fastest, cleared on restart, no extra dependencies
cache_manager.register("memory", MemoryCache(), is_default=True)


# File: zero-dependency persistent cache, ideal for single-process apps
cache_manager.register("file", FileCache("/tmp/toolops-cache"))


# SQLite: lightweight persistent cache, single-file, no server required
cache_manager.register("sqlite", SQLiteCache("toolops_cache.db"))


# Postgres: persistent across restarts, shareable across processes
cache_manager.register("db", PostgresCache("postgresql://user:pass@localhost:5432/mydb"))


# Valkey / Redis: distributed in-memory cache with async pooling
cache_manager.register("valkey", ValkeyCache(host="localhost", port=6379))
cache_manager.register("redis", RedisCache(url="redis://localhost:6379/0"))


# MySQL / MariaDB: persistent relational cache
cache_manager.register("mysql", MySQLCache(host="localhost", db="myapp", user="root", password="secret"))
# — or via DSN —
cache_manager.register("mysql", MySQLCache(dsn="mysql://root:secret@localhost:3306/myapp"))


# Semantic: vector embeddings to match by meaning, not string equality
# Reduces LLM calls up to 90%
embedder = SentenceTransformerEmbedder("all-MiniLM-L6-v2")
cache_manager.register("semantic", SemanticCache(embedder=embedder, threshold=0.92))

2. Resilience Patterns

ToolOps provides robust, battle-tested resilience out of the box.

  • Circuit Breaker: Prevents hammering a failing service and causing cascading failures.
  • Stale-if-Error: Serves the last known good cached value if the live API call fails.
  • Request Coalescing: If 50 agents call the same endpoint simultaneously, ToolOps executes the real API call once and multicasts the result.
@readonly(
    cache_backend   = "db",
    cache_ttl       = 3600,
    retry_count     = 3,
    timeout         = 10.0,
    stale_if_error  = True,     # Fallback on API failure
    circuit_breaker = True      # Protect the underlying service
)
async def get_market_data(ticker: str) -> dict:
    return await api.fetch(ticker)

3. Architecture & Security (v1.0.0)

ToolOps v1.0.0 introduces an enterprise-grade architecture:

  • Middleware Pipeline: The monolithic decorator has been refactored into a composable pipeline (Logging, Cache, CircuitBreaker, Retry, Coalescing, Fallback).
  • SHA-256 Cache Key Hashing: All cache keys are strictly hashed. No sensitive data (tokens, PII) is exposed in cache stores.
  • Automatic Parameter Masking: Tool arguments containing sensitive keywords (token, password, secret, etc.) are automatically masked as ***MASKED*** in structured logs.

📊 Observability

ToolOps instruments every tool call automatically.

OpenTelemetry (OTEL) & Prometheus

from toolops import configure_opentelemetry, prometheus_metrics

# 1. Configure OpenTelemetry tracing (accepts any standard tracer instance)
configure_opentelemetry(tracer)


# 2. Expose Prometheus metrics (returns a raw Prometheus text string)
metrics_string = prometheus_metrics()

Key metrics exposed include toolops_cache_hits_total, toolops_tool_latency_seconds, and toolops_circuit_opens_total.


🔌 Framework Integration

ToolOps decorates plain Python async functions, making it 100% compatible with your favorite agent frameworks.

LangChain / LangGraph

from langchain.tools import tool

@tool
@readonly(cache_backend="memory", cache_ttl=600)
async def search_web(query: str) -> str:
    """Search the web and return a summary."""
    return await web_search_api.run(query)

CrewAI

from crewai.tools import BaseTool

class ResearchTool(BaseTool):
    name: str = "Research Tool"
    description: str = "Fetches and caches research data."

    @readonly(cache_backend="db", cache_ttl=3600)
    async def _run(self, query: str) -> str:
        return await research_api.fetch(query)

Model Context Protocol (MCP)

from toolops.integrations.mcp import MCPIntegration

# Generate a fully typed MCP tool definition automatically
mcp_definition = MCPIntegration.to_mcp_definition(get_weather)
mcp_server.register_tool(mcp_definition)

🛠️ CLI Reference

ToolOps ships with a command-line tool for managing your cache infrastructure.

# Check the health of all registered backends
toolops doctor

# View live cache statistics for an app
toolops stats --app my_app:setup_toolops

# Clear a specific backend's cache
toolops clear memory --app my_app:setup_toolops

🤝 Contributing

ToolOps is built for the community, by the community.


💬 Community & Contact

We are actively building the future of AI Agent infrastructure. Join the discussion!


ToolOps — Built for Production.
Licensed under Apache 2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

toolops-1.0.0.tar.gz (54.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

toolops-1.0.0-py3-none-any.whl (55.5 kB view details)

Uploaded Python 3

File details

Details for the file toolops-1.0.0.tar.gz.

File metadata

  • Download URL: toolops-1.0.0.tar.gz
  • Upload date:
  • Size: 54.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for toolops-1.0.0.tar.gz
Algorithm Hash digest
SHA256 5d9542c68d7f567b7f13d6a83285b634590909925126abf42b46f5b7044931fe
MD5 d21fc1705efc52ea5bb9b0e1f4a475b4
BLAKE2b-256 31a2f014244dd08f679cdd16707de12247062e941cf0d5282fec1a0f6aa6e2f7

See more details on using hashes here.

File details

Details for the file toolops-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: toolops-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 55.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for toolops-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ddfdf17e147bb75d0e1cdcc337482140acc48ad895119c5a86aec8420b1d477b
MD5 05840931e0cb2ea566739785162ecd0b
BLAKE2b-256 c74dc2f197b9efdc9b39805954e068daf6a9adb4bcaf0894034311c2598c1305

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page