> ## Documentation Index
> Fetch the complete documentation index at: https://docs.laragent.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Usage Tracking

> Monitor and analyze token consumption metrics from AI model responses in LarAgent

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:

<Note>
  **Priority:** Agent property > Provider config > Global config
</Note>

### Global Configuration

Enable usage tracking for all agents in `config/laragent.php`:

```php config/laragent.php theme={null}
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:

```php config/laragent.php theme={null}
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:

```php app/AiAgents/MyAgent.php theme={null}
<?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:

```php theme={null}
class MyAgent extends Agent
{
    protected $trackUsage = true;
    
    // Use database storage for persistent tracking
    protected $usageStorage = 'database';
}
```

<AccordionGroup>
  <Accordion title="Available Storage Aliases">
    | Alias               | Driver Class            | Description                           |
    | ------------------- | ----------------------- | ------------------------------------- |
    | `'in_memory'`       | `InMemoryStorage`       | No persistence                        |
    | `'session'`         | `SessionStorage`        | Session-based storage                 |
    | `'cache'`           | `CacheStorage`          | Laravel cache storage                 |
    | `'file'`            | `FileStorage`           | File-based storage                    |
    | `'database'`        | `EloquentUsageDriver`   | Database storage (requires migration) |
    | `'database-simple'` | `SimpleEloquentStorage` | Simplified database storage           |
  </Accordion>
</AccordionGroup>

### Method Override

For complete control, override methods in your agent class:

```php app/AiAgents/CustomTrackingAgent.php theme={null}
<?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:

```php theme={null}
// 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:

<Steps>
  <Step title="Publish the migration">
    ```bash theme={null}
    php artisan la:publish usage-storage
    ```
  </Step>

  <Step title="Run the migration">
    ```bash theme={null}
    php artisan migrate
    ```

    <Check>
      This creates the `laragent_usage` table with columns for all tracked metrics.
    </Check>
  </Step>
</Steps>

## 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](#direct-eloquent-model-usage) for advanced queries.

### Accessing Usage Storage

```php theme={null}
// Get the usage storage instance
$usageStorage = $agent->usageStorage();

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

### Getting Usage Records

```php theme={null}
// 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',
]);
```

<AccordionGroup>
  <Accordion title="Available Filter Options">
    | Filter            | Description                                    |
    | ----------------- | ---------------------------------------------- |
    | `'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                                 |
  </Accordion>
</AccordionGroup>

### Aggregating Usage Statistics

```php theme={null}
// 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

```php theme={null}
// 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

```php theme={null}
// 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

```php theme={null}
// Clear all usage records for this identity
$agent->clearUsage();
```

## Usage Data Structure

Each usage record contains:

```php theme={null}
[
    '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.

```php theme={null}
use LarAgent\Usage\Models\LaragentUsage;
```

### Database Schema

| Column              | Type        | Description                             |
| ------------------- | ----------- | --------------------------------------- |
| `session_key`       | string      | Unique identifier for the agent session |
| `record_id`         | string      | Unique identifier for the usage record  |
| `agent_name`        | string      | Name of the agent class                 |
| `user_id`           | string/null | User ID (if user-based session)         |
| `group`             | string/null | Group identifier                        |
| `chat_name`         | string/null | Chat/session name                       |
| `model_name`        | string      | AI model name (e.g., gpt-4)             |
| `provider_name`     | string      | Provider label (e.g., openai)           |
| `prompt_tokens`     | integer     | Tokens used in input                    |
| `completion_tokens` | integer     | Tokens used in output                   |
| `total_tokens`      | integer     | Total tokens consumed                   |
| `recorded_at`       | datetime    | When the usage was recorded             |

### Query Scopes

The model includes convenient query scopes for filtering:

```php theme={null}
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

```php theme={null}
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:

<Tabs>
  <Tab title="Daily Usage">
    ```php theme={null}
    // 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();
    ```
  </Tab>

  <Tab title="Top Users">
    ```php theme={null}
    // Get top users by token consumption
    $topUsers = LaragentUsage::query()
        ->whereNotNull('user_id')
        ->selectRaw('user_id, SUM(total_tokens) as total_tokens, COUNT(*) as requests')
        ->groupBy('user_id')
        ->orderByDesc('total_tokens')
        ->limit(10)
        ->get();
    ```
  </Tab>

  <Tab title="Cost Estimation">
    ```php theme={null}
    // Calculate estimated costs
    $costs = LaragentUsage::query()
        ->forProvider('openai')
        ->betweenDates('2024-01-01', '2024-01-31')
        ->selectRaw("
            model_name,
            SUM(prompt_tokens) as prompt_tokens,
            SUM(completion_tokens) as completion_tokens,
            CASE model_name
                WHEN 'gpt-4' THEN (SUM(prompt_tokens) / 1000 * 0.03) + (SUM(completion_tokens) / 1000 * 0.06)
                WHEN 'gpt-3.5-turbo' THEN (SUM(prompt_tokens) / 1000 * 0.001) + (SUM(completion_tokens) / 1000 * 0.002)
                ELSE 0
            END as estimated_cost
        ")
        ->groupBy('model_name')
        ->get();
    ```
  </Tab>
</Tabs>

## Real-World Example: Cost Monitoring Dashboard

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

<Steps>
  <Step title="Enable Global Tracking">
    Configure tracking in your `config/laragent.php`:

    ```php config/laragent.php theme={null}
    return [
        'track_usage' => true,
        
        'default_usage_storage' => [
            \LarAgent\Usage\Drivers\EloquentUsageDriver::class,
        ],
    ];
    ```
  </Step>

  <Step title="Create Analytics Service">
    ```php app/Services/UsageAnalyticsService.php theme={null}
    <?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;
        }
    }
    ```
  </Step>

  <Step title="Create Dashboard Controller">
    ```php app/Http/Controllers/Admin/UsageController.php theme={null}
    <?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),
            ]);
        }
    }
    ```
  </Step>

  <Step title="Add Usage Alert Job">
    ```php app/Jobs/CheckUsageThresholds.php theme={null}
    <?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));
            }
        }
    }
    ```
  </Step>

  <Step title="Schedule the Alert">
    ```php app/Console/Kernel.php theme={null}
    protected function schedule(Schedule $schedule)
    {
        $schedule->job(new CheckUsageThresholds)->hourly();
    }
    ```

    <Check>
      Your cost monitoring dashboard is now ready to track usage and alert on thresholds.
    </Check>
  </Step>
</Steps>

<Tip>
  For production applications, consider setting up usage alerts at different thresholds (50%, 75%, 90%) to proactively manage costs before hitting limits.
</Tip>
