Skip to main content
Usage tracking in LarAgent automatically captures token consumption metrics, helping you monitor API usage, estimate costs, and optimize your AI agent implementations.

What Gets Tracked

LarAgent’s usage tracking system captures:
  • Prompt tokens - Tokens used in the input/request
  • Completion tokens - Tokens used in the output/response
  • Total tokens - Combined prompt + completion tokens
  • Timestamps - When each response was generated
  • Model and provider information - Which model and provider generated the response
  • Agent and user context - Which agent and user triggered the response

Configuration

Usage tracking can be configured at multiple levels, with the following priority order:
Priority: Agent property > Provider config > Global config

Global Configuration

Enable usage tracking for all agents in config/laragent.php:
config/laragent.php
return [
    /**
     * Enable usage tracking globally for all agents.
     * Can be overridden per-provider or per-agent.
     */
    'track_usage' => false,

    /**
     * Default storage drivers for usage tracking.
     * If null, uses 'default_storage' configuration.
     */
    'default_usage_storage' => null,

    // Or specify explicit drivers:
    // 'default_usage_storage' => [
    //     \LarAgent\Context\Drivers\CacheStorage::class,
    //     \LarAgent\Context\Drivers\FileStorage::class,
    // ],
];

Provider Configuration

Configure usage tracking for specific providers:
config/laragent.php
return [
    'providers' => [
        'default' => [
            'label' => 'openai',
            'api_key' => env('OPENAI_API_KEY'),
            'driver' => \LarAgent\Drivers\OpenAi\OpenAiDriver::class,
            
            // Enable usage tracking for this provider
            'track_usage' => true,
            
            // Provider-specific usage storage
            'usage_storage' => [
                \LarAgent\Usage\Drivers\EloquentUsageDriver::class,
            ],
        ],
        
        'gemini' => [
            'label' => 'gemini',
            'api_key' => env('GEMINI_API_KEY'),
            
            // Disable tracking for this provider
            'track_usage' => false,
        ],
    ],
];

Agent Configuration

Set usage tracking directly in your agent class using properties:
app/AiAgents/MyAgent.php
<?php

namespace App\AiAgents;

use LarAgent\Agent;
use LarAgent\Context\Drivers\CacheStorage;

class MyAgent extends Agent
{
    protected $instructions = 'You are an assistant.';
    
    /**
     * Enable usage tracking for this agent.
     */
    protected $trackUsage = true;
    
    /**
     * Storage drivers for usage data.
     * Can be array of driver classes or string alias.
     */
    protected $usageStorage = [
        CacheStorage::class,
    ];
}
You can also use string aliases for storage:
class MyAgent extends Agent
{
    protected $trackUsage = true;
    
    // Use database storage for persistent tracking
    protected $usageStorage = 'database';
}
AliasDriver ClassDescription
'in_memory'InMemoryStorageNo persistence
'session'SessionStorageSession-based storage
'cache'CacheStorageLaravel cache storage
'file'FileStorageFile-based storage
'database'EloquentUsageDriverDatabase storage (requires migration)
'database-simple'SimpleEloquentStorageSimplified database storage

Method Override

For complete control, override methods in your agent class:
app/AiAgents/CustomTrackingAgent.php
<?php

namespace App\AiAgents;

use LarAgent\Agent;
use LarAgent\Usage\UsageStorage;

class CustomTrackingAgent extends Agent
{
    protected $instructions = 'Custom tracking agent.';
    
    /**
     * Override to customize tracking behavior.
     */
    public function shouldTrackUsage(): bool
    {
        // Custom logic - e.g., only track for production
        return app()->environment('production');
    }
    
    /**
     * Create a custom usage storage instance.
     */
    public function createUsageStorage(): UsageStorage
    {
        return new UsageStorage(
            $this->context()->getIdentity(),
            $this->usageStorageDrivers(),
            $this->model(),
            $this->providerName
        );
    }
}

Runtime Configuration

Enable or disable tracking dynamically at runtime:
// Enable tracking for a specific request
$agent = SupportAgent::for('session-123')
    ->trackUsage(true)
    ->respond('Hello!');

// Disable tracking
$agent->trackUsage(false);

Database Setup

To persist usage data in a database while using database driver, publish and run the migration:
1

Publish the migration

php artisan la:publish usage-storage
2

Run the migration

php artisan migrate
This creates the laragent_usage table with columns for all tracked metrics.

Working with Usage Data

The methods below allow you to access and analyze usage data tracked by LarAgent for any driver, but if you use the EloquentUsageDriver (or "database" alias), you also have direct access to the underlying database model for advanced queries.

Accessing Usage Storage

// Get the usage storage instance
$usageStorage = $agent->usageStorage();

// Returns null if tracking is disabled
if ($usageStorage === null) {
    // Tracking is disabled
}

Getting Usage Records

// Get all usage records for this agent/user
$usage = $agent->getUsage();

// Get usage with filters
$usage = $agent->getUsage([
    'model_name' => 'gpt-4',
    'date' => '2024-01-15',
]);
FilterDescription
'agent_name'Filter by agent class name
'user_id'Filter by user ID (null for non-user sessions)
'group'Filter by group
'model_name'Filter by model name
'provider_name'Filter by provider label
'date'Filter by specific date (Y-m-d)
'date_from'Filter from date
'date_to'Filter to date

Aggregating Usage Statistics

// Get aggregate statistics
$stats = $agent->getUsageAggregate();
// Returns:
// [
//     'total_prompt_tokens' => 1500,
//     'total_completion_tokens' => 800,
//     'total_tokens' => 2300,
//     'record_count' => 10,
// ]

// Aggregate with filters
$stats = $agent->getUsageAggregate([
    'date_from' => '2024-01-01',
    'date_to' => '2024-01-31',
]);

Grouping Usage Data

// Group usage by model
$byModel = $agent->getUsageGroupedBy('model_name');
// Returns:
// [
//     'gpt-4' => ['total_tokens' => 1500, 'record_count' => 5],
//     'gpt-3.5-turbo' => ['total_tokens' => 800, 'record_count' => 10],
// ]

// Group by provider
$byProvider = $agent->getUsageGroupedBy('provider_name');

// Group by agent
$byAgent = $agent->getUsageGroupedBy('agent_name');

// Group by user
$byUser = $agent->getUsageGroupedBy('user_id');

// With filters
$byModel = $agent->getUsageGroupedBy('model_name', [
    'date_from' => '2024-01-01',
]);

Getting Usage Identities

// Get all tracked usage identities for this agent class
$identities = $agent->getUsageIdentities();

foreach ($identities as $identity) {
    echo "User: " . $identity->getUserId();
    echo "Chat: " . $identity->getChatName();
}

Clearing Usage Data

// Clear all usage records for this identity
$agent->clearUsage();

Usage Data Structure

Each usage record contains:
[
    'agent_name' => 'SupportAgent',
    'user_id' => 'user-123',        // null for non-user sessions
    'group' => null,                 // Optional group identifier
    'model_name' => 'gpt-4',
    'provider_name' => 'openai',
    'prompt_tokens' => 150,
    'completion_tokens' => 75,
    'total_tokens' => 225,
    'recorded_at' => '2024-01-15T10:30:00Z',
]

Direct Eloquent Model Usage

When using the EloquentUsageDriver (database storage), you have direct access to the LaragentUsage Eloquent model for complex queries and reporting.
use LarAgent\Usage\Models\LaragentUsage;

Database Schema

ColumnTypeDescription
session_keystringUnique identifier for the agent session
record_idstringUnique identifier for the usage record
agent_namestringName of the agent class
user_idstring/nullUser ID (if user-based session)
groupstring/nullGroup identifier
chat_namestring/nullChat/session name
model_namestringAI model name (e.g., gpt-4)
provider_namestringProvider label (e.g., openai)
prompt_tokensintegerTokens used in input
completion_tokensintegerTokens used in output
total_tokensintegerTotal tokens consumed
recorded_atdatetimeWhen the usage was recorded

Query Scopes

The model includes convenient query scopes for filtering:
use LarAgent\Usage\Models\LaragentUsage;

// Filter by agent
LaragentUsage::forAgent('SupportAgent')->get();

// Filter by user
LaragentUsage::forUser('user-123')->get();

// Filter by model
LaragentUsage::forModel('gpt-4')->get();

// Filter by provider
LaragentUsage::forProvider('openai')->get();

// Filter by group
LaragentUsage::forGroup('premium-users')->get();

// Filter by date range
LaragentUsage::betweenDates('2024-01-01', '2024-01-31')->get();

// Filter by specific date
LaragentUsage::onDate('2024-01-15')->get();

// Chain multiple scopes
LaragentUsage::forAgent('SupportAgent')
    ->forProvider('openai')
    ->betweenDates('2024-01-01', '2024-01-31')
    ->get();

Aggregation Methods

use LarAgent\Usage\Models\LaragentUsage;

// Get aggregate totals for all records
$totals = LaragentUsage::aggregate();
// Returns:
// [
//     'total_prompt_tokens' => 15000,
//     'total_completion_tokens' => 8000,
//     'total_tokens' => 23000,
//     'record_count' => 150,
// ]

// Aggregate with filters (pass a query builder)
$query = LaragentUsage::forAgent('SupportAgent')
    ->betweenDates('2024-01-01', '2024-01-31');
$totals = LaragentUsage::aggregate($query);

// Group by a column
$byModel = LaragentUsage::groupByColumn('model_name');
// Returns Collection keyed by model_name

Advanced Queries

Leverage Laravel’s query builder for complex analytics:
// Get daily token usage for the last 30 days
$dailyUsage = LaragentUsage::query()
    ->where('recorded_at', '>=', now()->subDays(30))
    ->selectRaw('DATE(recorded_at) as date, SUM(total_tokens) as tokens')
    ->groupBy('date')
    ->orderBy('date')
    ->get();

Real-World Example: Cost Monitoring Dashboard

Here’s a complete example of building a cost monitoring dashboard with usage tracking.
1

Enable Global Tracking

Configure tracking in your config/laragent.php:
config/laragent.php
return [
    'track_usage' => true,
    
    'default_usage_storage' => [
        \LarAgent\Usage\Drivers\EloquentUsageDriver::class,
    ],
];
2

Create Analytics Service

app/Services/UsageAnalyticsService.php
<?php

namespace App\Services;

use App\AiAgents\SupportAgent;
use App\AiAgents\CodeAssistant;
use Carbon\Carbon;

class UsageAnalyticsService
{
    protected array $agents = [
        SupportAgent::class,
        CodeAssistant::class,
    ];
    
    /**
     * Get total usage across all agents for a date range.
     */
    public function getTotalUsage(string $from, string $to): array
    {
        $totals = [
            'prompt_tokens' => 0,
            'completion_tokens' => 0,
            'total_tokens' => 0,
            'record_count' => 0,
        ];
        
        foreach ($this->agents as $agentClass) {
            $agent = $agentClass::make();
            $stats = $agent->getUsageAggregate([
                'date_from' => $from,
                'date_to' => $to,
            ]);
            
            if ($stats) {
                $totals['prompt_tokens'] += $stats['total_prompt_tokens'] ?? 0;
                $totals['completion_tokens'] += $stats['total_completion_tokens'] ?? 0;
                $totals['total_tokens'] += $stats['total_tokens'] ?? 0;
                $totals['record_count'] += $stats['record_count'] ?? 0;
            }
        }
        
        return $totals;
    }
    
    /**
     * Get usage breakdown by provider.
     */
    public function getUsageByProvider(): array
    {
        $byProvider = [];
        
        foreach ($this->agents as $agentClass) {
            $agent = $agentClass::make();
            $grouped = $agent->getUsageGroupedBy('provider_name');
            
            if ($grouped) {
                foreach ($grouped as $provider => $stats) {
                    if (!isset($byProvider[$provider])) {
                        $byProvider[$provider] = [
                            'total_tokens' => 0,
                            'record_count' => 0,
                        ];
                    }
                    $byProvider[$provider]['total_tokens'] += $stats['total_tokens'] ?? 0;
                    $byProvider[$provider]['record_count'] += $stats['record_count'] ?? 0;
                }
            }
        }
        
        return $byProvider;
    }
    
    /**
     * Estimate cost based on token pricing.
     */
    public function estimateCost(string $from, string $to): array
    {
        $pricing = [
            'openai' => [
                'gpt-4' => ['prompt' => 0.03, 'completion' => 0.06],
                'gpt-3.5-turbo' => ['prompt' => 0.001, 'completion' => 0.002],
            ],
        ];
        
        $costs = [];
        
        foreach ($this->agents as $agentClass) {
            $agent = $agentClass::make();
            $usage = $agent->getUsage([
                'date_from' => $from,
                'date_to' => $to,
            ]);
            
            if ($usage) {
                foreach ($usage as $record) {
                    $provider = $record->providerName ?? 'unknown';
                    $model = $record->modelName ?? 'unknown';
                    
                    if (isset($pricing[$provider][$model])) {
                        $rates = $pricing[$provider][$model];
                        $cost = (($record->promptTokens / 1000) * $rates['prompt']) +
                                (($record->completionTokens / 1000) * $rates['completion']);
                        
                        $key = "{$provider}:{$model}";
                        $costs[$key] = ($costs[$key] ?? 0) + $cost;
                    }
                }
            }
        }
        
        return $costs;
    }
}
3

Create Dashboard Controller

app/Http/Controllers/Admin/UsageController.php
<?php

namespace App\Http\Controllers\Admin;

use App\Services\UsageAnalyticsService;
use Illuminate\Http\Request;

class UsageController extends Controller
{
    public function __construct(
        protected UsageAnalyticsService $analytics
    ) {}
    
    public function dashboard(Request $request)
    {
        $from = $request->input('from', now()->startOfMonth()->format('Y-m-d'));
        $to = $request->input('to', now()->format('Y-m-d'));
        
        return response()->json([
            'total_usage' => $this->analytics->getTotalUsage($from, $to),
            'by_provider' => $this->analytics->getUsageByProvider(),
            'estimated_cost' => $this->analytics->estimateCost($from, $to),
        ]);
    }
}
4

Add Usage Alert Job

app/Jobs/CheckUsageThresholds.php
<?php

namespace App\Jobs;

use App\Services\UsageAnalyticsService;
use App\Notifications\UsageThresholdExceeded;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;

class CheckUsageThresholds implements ShouldQueue
{
    use Queueable;
    
    protected int $dailyThreshold = 1000000; // 1M tokens
    
    public function handle(UsageAnalyticsService $analytics): void
    {
        $today = now()->format('Y-m-d');
        $usage = $analytics->getTotalUsage($today, $today);
        
        if ($usage['total_tokens'] > $this->dailyThreshold) {
            $admin = \App\Models\User::find(1);
            $admin->notify(new UsageThresholdExceeded($usage));
        }
    }
}
5

Schedule the Alert

app/Console/Kernel.php
protected function schedule(Schedule $schedule)
{
    $schedule->job(new CheckUsageThresholds)->hourly();
}
Your cost monitoring dashboard is now ready to track usage and alert on thresholds.
For production applications, consider setting up usage alerts at different thresholds (50%, 75%, 90%) to proactively manage costs before hitting limits.