Skip to main content

🛡️ 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

Release files for agent-safety-box 1.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for agent-safety-box 1.1.0
File Size Uploaded
agent_safety_box-1.1.0.tar.gz 40.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for agent-safety-box 1.1.0
File Interpreter ABI Platform
agent_safety_box-1.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 86.2 kB

Release files / agent_safety_box-1.1.0.tar.gz

Download URL agent_safety_box-1.1.0.tar.gz
Size 40.8 kB
Tags Source
SHA-256 checksum
How to use checksums
89558ba67bb66be47884b31e29a1eeec4e004160394dbfbedd889696f44e25d7
BLAKE2b-256 checksum
How to use checksums
1bba2d0dbcaf6d3b57c2958c27611bc437506546f7f57ef3a083a0e4c2cc5354
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.3

Release files / agent_safety_box-1.1.0-py3-none-any.whl

Download URL agent_safety_box-1.1.0-py3-none-any.whl
Size 45.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2e136fda897438390603456a759769a2221e55bb1f20123d2908b00c6d3ffa28
BLAKE2b-256 checksum
How to use checksums
15433d72afcf7418f2bc949b3f7ecc606cc9df082ce0f01f3833f71a16b06c16
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.3

Release history Release notifications | RSS feed

This release

1.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page