subhashladumor1 / laravel-ai-guard
Laravel AI Guard π‘οΈ β AI cost & budget control for Laravel AI SDK. Track token usage, control OpenAI & LLM spending, enforce AI budgets, and prevent unexpected billing spikes.
Installs: 1
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/subhashladumor1/laravel-ai-guard
Requires
- php: ^8.1
- illuminate/support: ^10.0|^11.0|^12.0
Requires (Dev)
- php: ^8.1|^8.2|^8.3
- illuminate/cache: ^9.0|^10.0|^11.0|^12.0
- illuminate/database: ^9.0|^10.0|^11.0|^12.0
- illuminate/http: ^9.0|^10.0|^11.0|^12.0
- illuminate/session: ^9.0|^10.0|^11.0|^12.0
- illuminate/support: ^9.0|^10.0|^11.0|^12.0
- orchestra/testbench: ^8.0
- phpunit/phpunit: ^9.0|^10.0|^11.0|^12.0
Suggests
- laravel/ai: π€ Use with Laravel AI SDK (12.x) to track token usage, estimate AI cost, and enforce budgets automatically.
README
Track costs β’ Set budgets β’ Never get surprised by the bill.
Laravel AI Guard is a powerful AI cost optimization package built for the Laravel AI SDK (12.x) π. It helps Laravel developers track OpenAI & LLM token usage π, estimate AI costs before execution β οΈ, enforce per-user or per-tenant AI budgets π§Ύ, and prevent unexpected AI billing spikes π₯ in production.
Designed for Laravel SaaS applications, APIs, and AI-powered platforms, Laravel AI Guard acts as a financial firewall π‘οΈ between your app and AI providersβkeeping AI usage safe, predictable, and cost-efficient πΈ.
---π Quick Navigation
| Jump to | Jump to |
|---|---|
| What's Inside | How It Works |
| Quick Start | Usage Examples |
| Configuration | Package Structure |
β¨ What's Inside
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β
β βββββββββββββββ βββββββββββββββ βββββββββββββββ βββββββββββββββ β
β β TRACK β β BUDGET β β ESTIMATE β β BLOCK β β
β β Every call β β Per user/ β β Before you β β Over-spend β β
β β in DB β β tenant/app β β call (free) β β requests β β
β βββββββββββββββ βββββββββββββββ βββββββββββββββ βββββββββββββββ β
β β
β βββββββββββββββββββββββββββ β
β β π¨ KILL SWITCH β β
β β Disable all AI β β
β β in one config change β β
β βββββββββββββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Works with: Laravel AI SDK (12.x) β’ OpenAI β’ Anthropic β’ Any AI API
π How It Works
Request Flow (Before β During β After)
flowchart TD
subgraph BEFORE["π‘οΈ BEFORE"]
A[Request arrives] --> B{Budget OK?}
B -->|Yes| C[Optional: Estimate cost]
B -->|No| D[β Block - 402]
C --> E[Continue]
end
subgraph DURING["β‘ DURING"]
E --> F[Your app calls AI]
F --> G[Laravel AI SDK or any API]
end
subgraph AFTER["π AFTER"]
G --> H[Record tokens, cost, user]
H --> I[Save to ai_usages]
I --> J[Update ai_budgets]
end
BEFORE --> DURING --> AFTER
Loading
Budget Hierarchy (Checked in Order)
flowchart LR
subgraph layers["Budget layers checked top to bottom"]
direction TB
A["π GLOBAL<br/>Whole app limit"]
B["π’ TENANT<br/>Org/team limit"]
C["π€ USER<br/>Per-user limit"]
end
A --> B --> C
C --> D{All OK?}
D -->|Yes β| E[Allow request]
D -->|Any exceeded β| F[Block - 402]
Loading
TL;DR: Laravel AI SDK does the AI. Laravel AI Guard decides whether you're allowed to call and how much you spent. They work together.
π€ Why Should I Care?
WITHOUT AI GUARD WITH AI GUARD
βββββββββββββββββββββββββββ βββββββββββββββββββββββββββ
β πΈ Surprise bill β β π Full visibility β
β π Runaway loop? β β β π Budget limits β
β π° Invoice shock β β π Predictable costs β
βββββββββββββββββββββββββββ βββββββββββββββββββββββββββ
AI APIs charge by the token. One heavy user, one bugβand your bill spikes. Most apps don't track until the invoice arrives. AI Guard gives you visibility, limits, and control.
π Under the Hood
Cost Calculation
flowchart LR
subgraph inputs["Inputs"]
A[Input Tokens]
B[Output Tokens]
C[Model Pricing]
end
subgraph formula["Formula"]
D["(Input Γ· 1000) Γ Input Price"]
E["(Output Γ· 1000) Γ Output Price"]
F["+"]
end
subgraph result["Result"]
G["Total Cost $"]
end
A --> D
B --> E
C --> D
C --> E
D --> F
E --> F
F --> G
Loading
Example: 500 input + 200 output tokens (gpt-4o: $0.0025/1k in, $0.01/1k out)
| Step | Calculation | Result |
|---|---|---|
| Input cost | (500 Γ· 1000) Γ 0.0025 | $0.00125 |
| Output cost | (200 Γ· 1000) Γ 0.01 | $0.00200 |
| Total | $0.00325 |
Estimation (No API Call = No Cost)
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β AIGuard::estimate($prompt) β
β β
β Input tokens β characters Γ· 4 (configurable) β
β Output tokens β input Γ 0.5 (configurable) β
β β
β "Write a short poem" (18 chars) β ~5 in, ~3 out β 8 β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Kill Switch
| Method | How |
|---|---|
.env (recommended) |
AI_GUARD_DISABLED=true |
| Config | 'ai_disabled' => true |
Result: Middleware returns 503 Service Unavailable β no AI calls get through.
π‘ 5 Ways to Reduce AI Costs
β ESTIMATE β‘ BUDGET β’ TRACK β£ KILL SWITCH β€ TAG
βββββββββββββββ βββββββββββββββ βββββββββββββββ βββββββββββββββ βββββββββββββββ
β Show cost β β Set limits β β Run report β β Emergency β β Break down β
β before call β β per user/ β β to see β β stop all β β by feature β
β β β tenant β β where $ goesβ β AI if neededβ β (chat, etc) β
βββββββββββββββ βββββββββββββββ βββββββββββββββ βββββββββββββββ βββββββββββββββ
π Requirements
| Requirement | Version |
|---|---|
| PHP | 8.1+ |
| Laravel | 10.x, 11.x, or 12.x |
| Laravel AI SDK | Optional (for agents/streaming) |
π Quick Start (3 Steps)
flowchart LR
subgraph step1["Step 1"]
A[composer require]
end
subgraph step2["Step 2"]
B[publish config<br/>& migrations]
end
subgraph step3["Step 3"]
C[migrate]
end
A --> B --> C
Loading
1. Install
composer require subhashladumor1/laravel-ai-guard
2. Publish & migrate
php artisan vendor:publish --tag=ai-guard-config php artisan vendor:publish --tag=ai-guard-migrations php artisan migrate
3. Optional β translations
php artisan vendor:publish --tag=ai-guard-lang
Creates: ai_usages (every call) + ai_budgets (limits & usage)
βοΈ Configuration
Edit config/ai-guard.php after publishing:
| Setting | Purpose |
|---|---|
ai_disabled |
Turn off all AI |
pricing |
Cost per 1k tokens per model |
default_model |
Fallback (e.g. gpt-4o) |
default_provider |
Fallback (e.g. openai) |
budgets |
Limits (global, user, tenant); period |
estimation |
Chars per token, output multiplier |
Example .env:
AI_GUARD_DISABLED=false AI_GUARD_GLOBAL_LIMIT=100 AI_GUARD_USER_LIMIT=10 AI_GUARD_TENANT_LIMIT=50
π Usage Examples
With Laravel AI SDK (12.x)
sequenceDiagram
participant App
participant AIGuard
participant AI
App->>AIGuard: checkAllBudgets()
App->>AIGuard: estimate(prompt)
App->>AI: prompt()
AI-->>App: response
App->>AIGuard: recordFromResponse()
Loading
// 1. Before β check budget AIGuard::checkAllBudgets(auth()->id(), $tenantId); $estimate = AIGuard::estimate($userPrompt); // 2. Call AI (as normal) $response = (new YourAgent)->prompt($userPrompt); // 3. After β record usage AIGuard::recordFromResponse($response, userId: auth()->id(), tenantId: $tenantId, tag: 'chat');
Multi-model: Pass model and provider so estimate and budgets use the right cost:
$estimate = AIGuard::estimate($userPrompt, model: 'gpt-4o-mini', provider: 'openai'); AIGuard::recordFromResponse($response, userId: auth()->id(), provider: 'openai', model: 'gpt-4o-mini');
Streaming: record in ->then() callback when stream finishes.
With Any Other AI API
// Before β same AIGuard::checkAllBudgets(auth()->id(), $tenantId); // After β record manually AIGuard::recordAndApplyBudget([ 'provider' => 'openai', 'model' => 'gpt-4o', 'input_tokens' => 400, 'output_tokens' => 250, 'user_id' => auth()->id(), 'tenant_id' => $tenantId, 'tag' => 'chat', ]);
Multi-model and dynamic cost (no config change)
Cost is resolved in order: per-call override β runtime pricing β config. So you can support many models and change costs at runtime without editing config/ai-guard.php.
1. Per-call pricing override β pass pricing for a single estimate or record:
// Estimate with custom cost per 1k tokens (no config entry needed) $estimate = AIGuard::estimate($userPrompt, 'my-model', 'my-provider', [ 'input' => 0.001, 'output' => 0.002, ]); // Record with custom pricing when cost isn't pre-calculated AIGuard::recordFromResponse($response, auth()->id(), $tenantId, 'openai', 'gpt-4o', 'chat', [ 'input' => 0.0025, 'output' => 0.01, ]); // record() can omit 'cost' and use 'pricing' to calculate AIGuard::record([ 'provider' => 'openai', 'model' => 'gpt-4o', 'input_tokens' => 400, 'output_tokens' => 250, 'pricing' => ['input' => 0.0025, 'output' => 0.01], 'user_id' => auth()->id(), ]);
2. Runtime pricing registry β register models once (e.g. in a service provider or from DB); then estimate() and recording use them automatically:
$calc = AIGuard::getCostCalculator(); // Single model $calc->setPricing('openai', 'gpt-4o-mini', ['input' => 0.00015, 'output' => 0.0006]); // Many models at once $calc->setPricingMap([ 'openai' => [ 'gpt-4o' => ['input' => 0.0025, 'output' => 0.01], 'gpt-4o-mini' => ['input' => 0.00015, 'output' => 0.0006], ], 'anthropic' => [ 'claude-3-5-sonnet' => ['input' => 0.003, 'output' => 0.015], ], ]); // Now estimate/record use these models without config $estimate = AIGuard::estimate($userPrompt, 'gpt-4o-mini', 'openai'); AIGuard::checkAllBudgets(auth()->id(), $tenantId);
Add, update or remove models at runtime:
$calc = AIGuard::getCostCalculator(); // Add or update a model $calc->setPricing('openai', 'gpt-4o', ['input' => 0.0025, 'output' => 0.01]); // Remove a model from runtime (falls back to config, or 0 if not in config) $calc->removePricing('openai', 'gpt-4o'); // Clear all runtime pricing $calc->clearRuntimePricing();
Config file β publish and edit config/ai-guard.php to add, remove or update models permanently:
'pricing' => [ 'openai' => [ 'gpt-4o' => ['input' => 0.0025, 'output' => 0.01], 'gpt-4o-mini' => ['input' => 0.00015, 'output' => 0.0006], // Add new models here ], // Add new providers here ],
Budget checks use the same cost you record (per user/tenant), so multi-model costs and budgets work together.
Middleware
Route::post('/chat', ChatController::class)->middleware('ai.guard');
| Condition | Response |
|---|---|
| Over budget | 402 + JSON |
| AI disabled | 503 |
Artisan Commands
| Command | Purpose |
|---|---|
php artisan ai-guard:report |
Usage & cost report |
php artisan ai-guard:report --period=month |
Monthly report |
php artisan ai-guard:report --days=7 |
Last 7 days |
php artisan ai-guard:reset-budgets |
Reset when period ends |
php artisan ai-guard:reset-budgets --dry-run |
Preview only |
Schedule reset: $schedule->command('ai-guard:reset-budgets')->daily();
ποΈ Package Structure
flowchart TB
subgraph entry["Entry Points"]
F[AIGuard Facade]
M[EnforceAIBudget Middleware]
C1[ai-guard:report]
C2[ai-guard:reset-budgets]
end
subgraph core["Core"]
GM[GuardManager]
end
subgraph services["Services"]
BR[BudgetResolver]
BE[BudgetEnforcer]
TE[TokenEstimator]
CC[CostCalculator]
end
subgraph storage["Storage"]
AU[AiUsage]
AB[AiBudget]
end
F --> GM
M --> GM
C1 --> GM
C2 --> GM
GM --> BR
GM --> BE
GM --> TE
GM --> CC
BR --> AB
BE --> AB
CC --> AU
Loading
laravel-ai-guard/
βββ src/
β βββ GuardManager.php # Core logic
β βββ Facades/AIGuard.php
β βββ Budget/ # BudgetResolver, BudgetEnforcer
β βββ Cost/ # TokenEstimator, CostCalculator
β βββ Models/ # AiUsage, AiBudget
β βββ Middleware/
β βββ Commands/
β βββ Exceptions/
βββ database/migrations/
βββ lang/ # 11 locales
βββ tests/
π Multi-Language
11 locales: en, ar, es, fr, de, zh, hi, bn, pt, ru, ja
App locale used automatically. Customize: php artisan vendor:publish --tag=ai-guard-lang
π’ Multi-Tenant (SaaS)
- Store
tenant_idon each usage - Set tenant budgets in config
- Middleware reads tenant from
X-Tenant-IDheader or request attribute
π§ͺ Testing
composer install && php artisan test
π License
MIT. See LICENSE.