PHPackages                             wcflabs/ai-ledger - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Logging &amp; Monitoring](/categories/logging)
4. /
5. wcflabs/ai-ledger

ActiveLibrary[Logging &amp; Monitoring](/categories/logging)

wcflabs/ai-ledger
=================

Telescope-like monitoring dashboard for Laravel AI SDK (laravel/ai) interactions

1.0.0(3d ago)019↓50%MITPHP ^8.3

Since Jul 7Compare

[ Source](https://github.com/WCFLabs/ai-ledger)[ Packagist](https://packagist.org/packages/wcflabs/ai-ledger)[ RSS](/packages/wcflabs-ai-ledger/feed)WikiDiscussions Synced today

READMEChangelog (2)Dependencies (12)Versions (3)Used By (0)

AI Ledger for Laravel
=====================

[](#ai-ledger-for-laravel)

A Telescope-like monitoring dashboard for [Laravel AI](https://github.com/laravel/ai) SDK interactions. Logs agent invocations, tool calls, token usage, costs, and latency — with a built-in web dashboard and support for MCP server/client tracing.

[![Tests](https://github.com/wcflabs/ai-ledger/actions/workflows/tests.yml/badge.svg)](https://github.com/wcflabs/ai-ledger/actions/workflows/tests.yml)[![Latest Version](https://camo.githubusercontent.com/c8b6ca6463267450d0a1c691280085890dbc6b9beecd96b589ef91dee3947ad9/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7763666c6162732f61692d6c65646765722e737667)](https://packagist.org/packages/wcflabs/ai-ledger)[![MIT License](https://camo.githubusercontent.com/7013272bd27ece47364536a221edb554cd69683b68a46fc0ee96881174c4214c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d626c75652e737667)](LICENSE)[![PHP ^8.3](https://camo.githubusercontent.com/85b6ffb096d7b29a36e035186f26d895deccc30521e2ff4cff83b01a810df482/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d253545382e332d3737374242342e737667)](https://php.net)[![Laravel ^12.0](https://camo.githubusercontent.com/89fcf72032e4286cf5bfb654b0595d3f8a4986cee8a398bc9fed84a5a12d0bbc/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d25354531322e302d4646324432302e737667)](https://laravel.com)

Features
--------

[](#features)

- Automatic recording of every `laravel/ai` agent invocation (prompt text, response, token counts, cost, latency)
- Per-invocation tool call tracing for agent tools, MCP server tools, and MCP client tools
- Cost calculation for OpenAI, Anthropic, Gemini, Groq, DeepSeek, and Mistral models
- Built-in web dashboard (Blade + Alpine.js + Chart.js, no build step required)
- Tag invocations programmatically or declaratively with `#[Tag]`
- Flexible filtering: skip individual invocations or tool calls via events
- Two storage drivers: `database` (full-featured) and `file` (lightweight, local dev)
- Automatic daily pruning via the Laravel scheduler

---

Requirements
------------

[](#requirements)

- PHP ^8.3
- Laravel ^12.0
- `laravel/ai` ^0.8.1

---

Installation
------------

[](#installation)

### 1. Install via Composer

[](#1-install-via-composer)

```
composer require wcflabs/ai-ledger
```

### 2. Publish the configuration

[](#2-publish-the-configuration)

```
php artisan vendor:publish --tag=ai-ledger-config
```

This creates `config/ai-ledger.php`.

### 3. Publish and register the authorization provider

[](#3-publish-and-register-the-authorization-provider)

```
php artisan vendor:publish --tag=ai-ledger-provider
```

This copies `AiLedgerApplicationServiceProvider` into `app/Providers/`. Register it in `bootstrap/providers.php`:

```
return [
    // ...
    App\Providers\AiLedgerApplicationServiceProvider::class,
];
```

### 4. Publish and run the migrations

[](#4-publish-and-run-the-migrations)

```
php artisan vendor:publish --tag=ai-ledger-migrations
php artisan migrate
```

---

Dashboard
---------

[](#dashboard)

Once installed, the dashboard is available at `/ai-ledger` (configurable via `dashboard.path` in the config).

**Authentication:**

By default, the dashboard is accessible in the `local` environment only. For production access, open `app/Providers/AiLedgerApplicationServiceProvider.php` and add authorized email addresses to the `viewAiLedger` gate:

```
protected function gate(): void
{
    Gate::define('viewAiLedger', function ($user) {
        return in_array($user?->email, [
            'admin@example.com',
        ]);
    });
}
```

You can also provide a fully custom auth callback anywhere (e.g., in a service provider):

```
use WCFLabs\AiLedger\Facades\AiLedger;

AiLedger::auth(function ($request) {
    return $request->user()?->isAdmin();
});
```

---

Configuration
-------------

[](#configuration)

All options live in `config/ai-ledger.php`.

KeyDefaultDescription`enabled``true`Master switch. Set `AI_LEDGER_ENABLED=false` to disable all recording.`driver``"database"`Storage driver: `"database"` or `"file"`. Env: `AI_LEDGER_DRIVER`.`drivers.database.connection``null`Database connection name. Env: `AI_LEDGER_DB_CONNECTION`. Uses the default connection when `null`.`drivers.file.path``storage/logs/ai-ledger`Directory for file-driver JSON logs.`dashboard.enabled``true`Whether to register the dashboard routes.`dashboard.path``"ai-ledger"`URL prefix for the dashboard.`dashboard.middleware``["web"]`Middleware applied to all dashboard routes.`pruning.enabled``true`Whether to schedule automatic daily pruning. Env: `AI_LEDGER_PRUNING_ENABLED`.`pruning.days``30`Number of days of records to retain. Env: `AI_LEDGER_PRUNING_DAYS`.`recording.prompt_text``true`Store the full prompt sent to the model.`recording.response_text``true`Store the full response from the model.`recording.tool_arguments``true`Store tool call input arguments.`recording.tool_results``true`Store tool call results.`recording.max_prompt_length``null`Truncate stored prompts to this many characters (`null` = no limit).`recording.max_response_length``null`Truncate stored responses to this many characters (`null` = no limit).`recording.max_tool_result_length``5000`Truncate stored tool results to this many characters.`pricing`*(see config)*USD-per-million-token pricing table keyed by provider and model name.---

Storage Drivers
---------------

[](#storage-drivers)

### `database` (default)

[](#database-default)

Stores invocations and tool calls in two database tables (`ai_ledger_invocations`, `ai_ledger_tool_calls`). Supports full filtering, aggregation, and the metrics dashboard.

### `file`

[](#file)

Writes one JSON file per invocation to `storage/logs/ai-ledger/`. Intended for local development only — it does not support filtering events, dashboard aggregation, or the metrics chart. No migrations required.

```
AI_LEDGER_DRIVER=file
```

---

Tagging Invocations
-------------------

[](#tagging-invocations)

Tags appear in the dashboard and can be used to categorize invocations by feature, user type, or any other dimension.

### Declarative — `#[Tag]` attribute

[](#declarative--tag-attribute)

Apply the `#[Tag]` attribute to any Agent or Tool class:

```
use WCFLabs\AiLedger\Attributes\Tag;
use Laravel\Ai\Agent;

#[Tag('checkout', 'billing')]
class CheckoutAgent extends Agent
{
    // ...
}
```

### Programmatic — `AiLedger::tag()`

[](#programmatic--ailedgertag)

Call `AiLedger::tag()` before the invocation runs. Tags are flushed and attached to the next recorded invocation:

```
use WCFLabs\AiLedger\Facades\AiLedger;

AiLedger::tag('user:premium', 'feature:recommendations');

$result = $agent->handle($input);
```

---

Suppressing Logging
-------------------

[](#suppressing-logging)

Wrap any code block with `AiLedger::withoutLogging()` to prevent it from being recorded:

```
use WCFLabs\AiLedger\Facades\AiLedger;

$result = AiLedger::withoutLogging(function () use ($agent, $input) {
    return $agent->handle($input);
});
```

---

MCP Integration
---------------

[](#mcp-integration)

> Requires `laravel/mcp` to be installed.

MCP calls are logged **automatically** — no manual setup required.

- **Inbound MCP server tool calls** (external MCP clients calling your app): intercepted transparently by overriding `laravel/mcp`'s `CallTool` handler in the container.
- **MCP tools used inside Laravel AI agents** (`McpServerTool`, `McpTool`): captured via the standard `InvokingTool`/`ToolInvoked` events with the correct `tool_type` (`mcp_server` or `mcp_client`).

### Manual decorator (advanced)

[](#manual-decorator-advanced)

If you call an MCP client directly outside of a Laravel AI agent context, you can opt in to logging via `LoggingMcpClientDecorator`:

```
use WCFLabs\AiLedger\Mcp\LoggingMcpClientDecorator;

$client = new LoggingMcpClientDecorator($mcpClient);

$result = $client->callTool('search', ['query' => 'example']);
```

All other methods on the underlying client are proxied transparently via `__call`.

---

Filtering
---------

[](#filtering)

You can prevent individual invocations or tool calls from being stored by listening to the filtering events and returning `false`.

### Skip an invocation

[](#skip-an-invocation)

```
use WCFLabs\AiLedger\Events\FilteringInvocation;
use Illuminate\Support\Facades\Event;

Event::listen(FilteringInvocation::class, function (FilteringInvocation $event) {
    // Skip invocations triggered by internal health-check agents
    if (str_contains($event->data['agent_class'] ?? '', 'HealthCheck')) {
        return false;
    }
});
```

### Skip a tool call

[](#skip-a-tool-call)

```
use WCFLabs\AiLedger\Events\FilteringToolCall;
use Illuminate\Support\Facades\Event;

Event::listen(FilteringToolCall::class, function (FilteringToolCall $event) {
    if ($event->data['tool_name'] === 'internal_ping') {
        return false;
    }
});
```

Returning `false` from the listener skips storage but still executes the agent or tool normally.

---

Artisan Commands
----------------

[](#artisan-commands)

CommandDescription`php artisan ai-ledger:status`Show driver, total invocation count, oldest record, and pruning configuration.`php artisan ai-ledger:prune [--days=N]`Delete records older than N days (defaults to `pruning.days` from config).`php artisan ai-ledger:clear [--force]`Delete **all** AI Ledger records. Prompts for confirmation unless `--force` is passed.---

Pruning
-------

[](#pruning)

When `pruning.enabled` is `true`, the package automatically schedules `ai-ledger:prune` to run daily via the Laravel scheduler (`callAfterResolving`). No manual scheduler entry is required.

To override the retention period at runtime:

```
php artisan ai-ledger:prune --days=7
```

---

License
-------

[](#license)

MIT — see [LICENSE](LICENSE).

###  Health Score

42

—

FairBetter than 88% of packages

Maintenance99

Actively maintained with recent releases

Popularity9

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity49

Maturing project, gaining track record

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

2

Last Release

3d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/c4f8509ad1fadd590840e0cf47344a2ca1c115dcffdc0e6a2f6caa58d78e7bbf?d=identicon)[joshuaruesweg](/maintainers/joshuaruesweg)

---

Tags

laravelloggingmonitoringmcpaidashboardllm

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/wcflabs-ai-ledger/health.svg)

```
[![Health](https://phpackages.com/badges/wcflabs-ai-ledger/health.svg)](https://phpackages.com/packages/wcflabs-ai-ledger)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3345.3M347](/packages/psalm-plugin-laravel)[laravel/pulse

Laravel Pulse is a real-time application performance monitoring tool and dashboard for your Laravel application.

1.7k15.1M134](/packages/laravel-pulse)[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9762.4M133](/packages/roots-acorn)[laravel/ai

The official AI SDK for Laravel.

1.0k3.2M216](/packages/laravel-ai)[laravel/mcp

Rapidly build MCP servers for your Laravel applications.

77022.3M167](/packages/laravel-mcp)[api-platform/laravel

API Platform support for Laravel

58174.6k17](/packages/api-platform-laravel)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
