Battle-hardened safety wrapper for AI agents
Project description
๐ก๏ธ agent_safety_box
Battle-hardened safety wrapper for AI agents โ zero external dependencies, production-grade, fully tested.
pip install agent-safety-box
##The Problem AI agents are powerful, but they fail unpredictably in production. They hallucinate, get stuck in loops, blow through budgets, and crash silently. As one developer put it, "we're spending 40% of our budget on garbage output." Debugging becomes guesswork. agent_safety_box is the answer .
Features
| Feature | AgentWrapper |
AgentWrapperV2 |
|---|---|---|
| Budget enforcement (thread-safe) | โ | โ |
| Per-run cost ceiling | โ | โ |
| Timeout (sync & async) | โ | โ |
| Retry + exponential backoff + jitter | โ | โ |
| Circuit Breaker | โ | โ |
| Rate Limiter (token-bucket) | โ | โ |
| Output validation | โ | โ |
| JSONL audit logging + rotation | โ | โ |
| Dry-run mode | โ | โ |
| Tags & metadata | โ | โ |
| Context manager | โ | โ |
| Lifecycle hooks (before/after/error) | โ | โ |
| Bulkhead (concurrency limiter) | โ | โ |
| Adaptive timeout (auto p95-tuned) | โ | โ |
| Rolling metrics (p50/p95/p99) | โ | โ |
| Cost forecaster | โ | โ |
| Plugin registry | โ | โ |
| Budget warning callback | โ | โ |
| Graceful shutdown | โ | โ |
| Fallback chain (multi-agent failover) | โ | โ |
Quick Start
from agent_safety_box import AgentWrapper, CircuitBreaker, RateLimiter
cb = CircuitBreaker(failure_threshold=3, reset_timeout=60)
rl = RateLimiter(rate=5.0)
wrapper = AgentWrapper(
agent=my_agent,
budget=100.0,
max_runtime=10.0,
max_cost_per_run=5.0,
max_retries=2,
retry_delay=1.0,
circuit_breaker=cb,
rate_limiter=rl,
output_validator=lambda o: isinstance(o, str) and len(o) > 0,
tags={"env": "prod", "model": "gpt-4o"},
log_path="logs/audit.jsonl",
)
with wrapper:
result = wrapper.run("Summarise this document", cost=1.5)
AgentWrapperV2 โ Advanced Pipeline
from agent_safety_box.wrapper_v2 import AgentWrapperV2
from agent_safety_box.middleware import HookManager, Bulkhead, AdaptiveTimeout
hooks = HookManager()
hooks.on_before(lambda ctx: print(f"โ {ctx['task']}"))
hooks.on_after(lambda ctx: print(f"โ done"))
hooks.on_error(lambda ctx, exc: print(f"โ {exc}"))
w = AgentWrapperV2(
agent=my_agent,
budget=500.0,
hooks=hooks,
bulkhead=Bulkhead(max_concurrent=10),
adaptive_timeout=AdaptiveTimeout(initial=5.0),
on_budget_warning=lambda rem, bud: print(f"โ Only {rem:.2f} left!"),
budget_warning_pct=0.20,
plugins={"logger": lambda ctx: my_logger.info(ctx)},
)
result = w.run("task", cost=1.0)
print(w.metrics)
# {
# 'total_runs': 1, 'successes': 1, 'errors': 0,
# 'spent': 1.0, 'remaining': 499.0,
# 'rolling': {'p50_s': 0.003, 'p95_s': 0.003, 'p99_s': 0.003,
# 'error_rate': 0.0, 'throughput_rps': 312.5, 'sample_size': 1},
# 'avg_cost_forecast': 1.0,
# 'bulkhead_active': 0, 'bulkhead_max': 10,
# 'adaptive_timeout_s': 5.0,
# }
Fallback Chain
from agent_safety_box.middleware import FallbackChain
chain = FallbackChain(
primary=gpt4_agent,
fallbacks=[gpt35_agent, local_llm_agent],
)
result = chain.run("task")
print(f"Used: {chain.last_used}")
print(chain.stats)
Async Support
from agent_safety_box import AsyncAgentWrapper
wrapper = AsyncAgentWrapper(agent=my_async_agent, budget=50.0)
async def main():
result = await wrapper.run("Classify this text", cost=0.5)
asyncio.run(main())
Exceptions
All exceptions inherit from AgentSafetyBoxError:
| Exception | When raised |
|---|---|
BudgetExceededError |
Total budget would be breached |
MaxCostExceededError |
Per-run cost ceiling exceeded |
TimeoutExceededError |
Agent exceeded max_runtime |
RetryExhaustedError |
All retry attempts failed |
AgentValidationError |
output_validator rejected output |
CircuitOpenError |
Circuit breaker is OPEN |
RateLimitError |
Rate limiter rejected (non-blocking mode) |
Safety Pipeline (per run)
1. max_cost_per_run check
2. budget check (thread/async-safe lock)
3. rate_limiter.acquire()
4. circuit_breaker.allow_request()
5. agent.run(task) [with timeout]
6. output_validator(result)
7. actual_cost adjustment (if agent returns {"actual_cost": X})
8. budget commit
9. circuit_breaker.record_success/failure()
10. audit log write
Running Tests
# All 263 tests
python -m unittest discover -s agent_safety_box/tests -p "test_*.py" -v
# Single module
python -m unittest agent_safety_box.tests.test_ultimate -v
Architecture
agent_safety_box/
โโโ __init__.py # Public API
โโโ wrapper.py # AgentWrapper + AsyncAgentWrapper (v1)
โโโ wrapper_v2.py # AgentWrapperV2 + AsyncAgentWrapperV2 (v2)
โโโ middleware.py # HookManager, RollingMetrics, Bulkhead,
โ # AdaptiveTimeout, CostForecaster, FallbackChain
โโโ safety.py # CircuitBreaker + RateLimiter
โโโ exceptions.py # All custom exceptions
โโโ logger.py # AuditLogger (JSONL + rotation)
โโโ tests/
โโโ conftest.py # Shared stubs and base class
โโโ test_budget.py # Budget enforcement (31 tests)
โโโ test_execution.py# Timeout + retry (30 tests)
โโโ test_logger.py # Audit logging (21 tests)
โโโ test_safety.py # Circuit + rate limiter (31 tests)
โโโ test_stress.py # Concurrency + chaos (18 tests)
โโโ test_ultimate.py # Deep edge cases (132 tests)
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file agent_safety_box-1.1.0.tar.gz.
File metadata
- Download URL: agent_safety_box-1.1.0.tar.gz
- Upload date:
- Size: 40.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
89558ba67bb66be47884b31e29a1eeec4e004160394dbfbedd889696f44e25d7
|
|
| MD5 |
b83ec22afacd1fa7f087ed45fd838f89
|
|
| BLAKE2b-256 |
1bba2d0dbcaf6d3b57c2958c27611bc437506546f7f57ef3a083a0e4c2cc5354
|
File details
Details for the file agent_safety_box-1.1.0-py3-none-any.whl.
File metadata
- Download URL: agent_safety_box-1.1.0-py3-none-any.whl
- Upload date:
- Size: 45.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2e136fda897438390603456a759769a2221e55bb1f20123d2908b00c6d3ffa28
|
|
| MD5 |
b601fd1670b3945ed458836735587a05
|
|
| BLAKE2b-256 |
15433d72afcf7418f2bc949b3f7ecc606cc9df082ce0f01f3833f71a16b06c16
|