AI API Guard
A provider-independent Python toolkit for adding reliability, observability, usage tracking, and cost awareness around AI API calls.
OpenAI is the first supported provider adapter. It covers synchronous chat completions. The library does not replace provider SDKs. It wraps a provider you supply.
Why AI API Guard?
Application code that calls an AI SDK directly usually owns the surrounding work: transient failures, retry behavior, request observability, token usage, cost calculation, and provider-specific exceptions.
AI API Guard is a small orchestration layer in front of a provider. Your code calls AIGuard. The guard calls an AIProvider, retries the transient failures it knows about, and can report one metrics record for the finished call.
Features
- Provider-independent
AIProviderabstraction AIGuardorchestration- Configurable retries with exponential backoff
- Retries for transient provider failures
- Request metrics callback
- Latency measurement and attempt tracking
- Token usage tracking
- Caller-supplied pricing and cost calculation
- Provider-independent exception hierarchy
- Optional OpenAI adapter
- Typed, tested Python API
Not implemented yet:
- Async clients
- Streaming
- Automatic pricing downloads
- Built-in provider price lists
Installation
This package is not published to PyPI yet. Install it from source.
git clone https://github.com/muhammad-yousaf-raza/ai-api-guard.git
cd ai-api-guard
python -m pip install -e ".[openai]"
Omit [openai] if you only need the provider-independent core.
After a PyPI release, the intended commands are:
pip install ai-api-guard
pip install "ai-api-guard[openai]"
Those release commands are not available today.
The OpenAI extra installs the official OpenAI Python SDK. OpenAIProvider() does not take a hard-coded API key. When you omit api_key and client, the SDK reads OPENAI_API_KEY from the environment.
Quick start
from ai_api_guard import AIGuard
from ai_api_guard.providers.openai import OpenAIProvider
provider = OpenAIProvider()
guard = AIGuard(provider)
response = guard.chat(
model="gpt-4o-mini",
messages=[
{
"role": "user",
"content": "Explain exponential backoff in one sentence.",
}
],
)
print(response.content)
examples/openai_basic.py is the same kind of script. It also prints the model, token counts, and cost.
This example is documentation. It is not a record of a live API call.
Without a pricing map, response.cost stays 0.0. See Cost tracking.
Retry configuration
max_attempts is the total number of provider calls, including the first attempt. It is not the number of extra retries.
from ai_api_guard import AIGuard, RetryPolicy
from ai_api_guard.providers.openai import OpenAIProvider
policy = RetryPolicy(
max_attempts=3,
initial_delay=0.5,
max_delay=8.0,
backoff_multiplier=2.0,
)
guard = AIGuard(OpenAIProvider(), retry_policy=policy)
These values are also the defaults. After a retryable failure, the guard waits initial_delay seconds, then multiplies that delay by backoff_multiplier for each later failure. The wait never exceeds max_delay.
AIGuard retries only:
RateLimitErrorProviderTimeoutErrorProviderUnavailableError
The final failure is re-raised unchanged. AuthenticationError, a generic ProviderError, and any other exception are not retried.
Observability
Pass on_metrics to receive one RequestMetrics record for each chat call. Intermediate retry attempts do not emit their own records.
from ai_api_guard import AIGuard, RequestMetrics
from ai_api_guard.providers.openai import OpenAIProvider
def handle_metrics(metrics: RequestMetrics) -> None:
print(metrics.provider)
print(metrics.model)
print(metrics.attempts)
print(metrics.latency)
print(metrics.total_tokens)
print(metrics.cost)
guard = AIGuard(OpenAIProvider(), on_metrics=handle_metrics)
latency is the elapsed time for the whole guarded call, in seconds. attempts is the number of provider calls made. On success, token counts and cost are copied from the AIResponse. On failure they are zero, and error_type is the exception class name. success is True only when the call returns a response.
If handle_metrics raises, that exception is ignored. The chat result is unchanged.
Cost tracking
Prices are not built in. You supply them. The numbers below are example values only, not current provider pricing, and they do not name a currency. Each number is a currency unit per 1,000,000 tokens.
from ai_api_guard import ModelPricing
from ai_api_guard.providers.openai import OpenAIProvider
# Example values only — not current provider pricing.
pricing = {
"example-model": ModelPricing(
input_cost_per_million=1.0,
output_cost_per_million=2.0,
)
}
provider = OpenAIProvider(pricing=pricing)
OpenAIProvider looks up the model name returned by the API first, then the model name you requested. When it finds a ModelPricing entry, it fills response.cost. When it does not, response.cost stays 0.0.
Exception handling
from ai_api_guard import (
AuthenticationError,
ProviderError,
ProviderTimeoutError,
ProviderUnavailableError,
RateLimitError,
)
try:
response = guard.chat(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Hello"}],
)
except AuthenticationError:
print("credentials were rejected")
except (RateLimitError, ProviderTimeoutError, ProviderUnavailableError):
print("retries were exhausted")
except ProviderError:
print("the provider returned an error")
guard is the AIGuard constructed above. RateLimitError, ProviderTimeoutError, and ProviderUnavailableError are retried until max_attempts is exhausted, then raised. AuthenticationError and a generic ProviderError propagate on the first occurrence.
The OpenAI adapter translates SDK authentication, rate-limit, timeout, connection, and other API errors into these types. Other Python exceptions are left unchanged.
Architecture
Application
|
v
AIGuard
|
+-- RetryPolicy
+-- RequestMetrics
|
v
AIProvider
|
+-- OpenAIProvider
+-- Future Providers
|
v
AIResponse
OpenAIProvider is not imported by import ai_api_guard. Import it from ai_api_guard.providers.openai when the OpenAI extra is installed.
Provider support
| Provider | Status |
|---|---|
| OpenAI | Supported |
| Anthropic | Planned |
| Gemini | Planned |
Planned providers are not implemented. OpenAI support is synchronous chat completions only.
Development
python -m pip install -e ".[dev,openai]"
python -m pytest -v
python -m ruff check .
python -m mypy src
The test suite does not call the OpenAI API and does not need an API key.
Project status
AI API Guard is pre-alpha (version 0.1.0). Public APIs may change before 1.0.
Contributing
Bug reports, feature discussions, provider adapters, and improvements to tests or documentation are welcome. Open an issue or a pull request on GitHub.
License
Author
Muhammad Yousaf Raza
- GitHub: muhammad-yousaf-raza
- LinkedIn: muhammad-yousaf-raza
Metadata
Release files for ai-api-guard 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| ai_api_guard-0.1.0.tar.gz | 21.5 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ai_api_guard-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 37.1 kB
Release files / ai_api_guard-0.1.0.tar.gz
| Download URL | ai_api_guard-0.1.0.tar.gz |
|---|---|
| Size | 21.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8f4b864397ebd3fe88ee65a92bbcfd281a1db7c0dd4f430293f6e66078442d2a
|
|
BLAKE2b-256 checksum How to use checksums |
9f90677aa765d20a90c1223408b94011a6b6792f3fc019ce730d06267bf07e28
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logRelease files / ai_api_guard-0.1.0-py3-none-any.whl
| Download URL | ai_api_guard-0.1.0-py3-none-any.whl |
|---|---|
| Size | 15.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e18e65845439d1785419f86f8a8ecee842d2c52470c90c03c0eedc8723596ce9
|
|
BLAKE2b-256 checksum How to use checksums |
3c700f71ba3dc379ae68d78e4bfb1d28053bfec3d997fad321086a9e46fd51ec
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logSecurity for ai-api-guard 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for ai_api_guard-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.