PHPackages                             webdirect/ai-filters - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. webdirect/ai-filters

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

webdirect/ai-filters
====================

AI-powered filters for Filament v4 panels. Filter any table with natural language through the official laravel/ai SDK.

v0.3.0(1mo ago)4133MITPHPPHP ^8.3

Since Apr 16Pushed 1mo agoCompare

[ Source](https://github.com/PrunaCatalin/webdirect-filament-ai-filters)[ Packagist](https://packagist.org/packages/webdirect/ai-filters)[ Docs](https://github.com/PrunaCatalin/webdirect-filament-ai-filters)[ RSS](/packages/webdirect-ai-filters/feed)WikiDiscussions main Synced 1w ago

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

Webdirect AI Filters for Filament
=================================

[](#webdirect-ai-filters-for-filament)

> **Credits**: the idea for this plugin came from [this video](https://www.youtube.com/watch?v=82ntd5LopoI) on the [Filament Daily](https://www.youtube.com/@FilamentDaily) channel by Povilas Korop. Huge thank-you — go subscribe.

A Filament v4 panel plugin that lets users filter any table with natural language. Click the **AI Filter** button on a table, type what you want (`"active platinum customers from Germany signed up last year"`), and the plugin sends your prompt plus the table's available filters to an AI model. The model responds with a structured set of filter values that the plugin applies to the table.

Powered by the official [`laravel/ai`](https://laravel.com/docs/13.x/ai-sdk)package, so any provider it supports (Anthropic, OpenAI, Gemini, ...) can be used.

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

[](#requirements)

PackageVersionPHP^8.3Laravel^11 / ^12 / ^13filament/filament^4.0laravel/ai^0.6Installation
------------

[](#installation)

### 1. Require the package

[](#1-require-the-package)

```
composer require webdirect/ai-filters
```

`laravel/ai` is pulled in automatically. The plugin's service provider is auto-discovered, no manual registration needed.

### 2. Publish the config

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

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

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

### 3. Configure your AI provider

[](#3-configure-your-ai-provider)

The plugin uses whatever provider you configure in `config/ai.php`. The fastest path for Anthropic:

```
ANTHROPIC_API_KEY=sk-ant-...
AI_FILTERS_PROVIDER=anthropic
AI_FILTERS_MODEL=claude-haiku-4-5-20251001
```

For OpenAI:

```
OPENAI_API_KEY=sk-...
AI_FILTERS_PROVIDER=openai
AI_FILTERS_MODEL=gpt-4o-mini
```

If you want to override the provider's API key from the plugin's own config, set `AI_FILTERS_API_KEY` instead — the plugin will rewrite `ai.providers..key` at boot.

### 4. Register the plugin on a panel

[](#4-register-the-plugin-on-a-panel)

```
use Webdirect\AiFilters\AiFiltersPlugin;

public function panel(Panel $panel): Panel
{
    return $panel
        // ...
        ->plugin(AiFiltersPlugin::make());
}
```

> Registering the plugin is optional today — the action works on its own — but doing so future-proofs you for panel-level configuration helpers.

Usage
-----

[](#usage)

Add `AiFilterAction::make()` to any Filament table's `headerActions()`:

```
use Webdirect\AiFilters\Actions\AiFilterAction;

public static function configure(Table $table): Table
{
    return $table
        ->columns([/* ... */])
        ->filters([
            SelectFilter::make('status')
                ->options([
                    'active' => 'Active',
                    'inactive' => 'Inactive',
                ])
                ->multiple(),
            // ...
        ])
        ->headerActions([
            AiFilterAction::make(),
        ]);
}
```

That's it. Open the table, click **AI Filter**, write what you want, hit **Apply**.

### Supported filter types

[](#supported-filter-types)

The plugin is fully dynamic: it introspects each filter's form schema and sends the AI a rich description of every form field — its name, type, label, whether it's `required`, its Laravel validation rules, and (for Select/Radio) the accepted options.

This means **any** Filament filter works out of the box, including your own custom-schema filters. The built-in handling for the common ones:

FilterFields exposed to AI`SelectFilter` (single)`value` + option keys`SelectFilter` with `->multiple()``values` (array) + option keys`TernaryFilter``value` + `booleanLike: true``Filter` (toggle / no schema)`isActive` (Checkbox / Toggle)`Filter` with custom schemaevery form field: name, type, required, rules, options, inputType (email/number/url), inputFormat (date/datetime/time), placeholderFor custom-schema filters, the AI sees the field names you defined, so use descriptive keys like `from`, `until`, `min_revenue`, `email_domain`.

### Global search

[](#global-search)

If the table has searchable columns and the user's request maps to free text (e.g. "find Amira"), the AI will fall back to setting the table's global search. Filters are preferred whenever a matching one exists.

### Customising the action

[](#customising-the-action)

`AiFilterAction::make()` returns a regular Filament `Action`, so you can chain on top of it:

```
AiFilterAction::make('aiFilter')
    ->label('Ask AI')
    ->icon('heroicon-o-bolt')
    ->color('warning')
    ->visible(fn () => auth()->user()->can('use-ai-filters'));
```

### Translations

[](#translations)

The plugin ships with translations for the following locales:

`en` (default) · `ro` · `es` · `fr` · `de` · `it` · `nl` · `pt_BR` · `pl` · `tr`

Laravel automatically picks the right file based on the active locale (`App::setLocale()` / `APP_LOCALE`). If a locale is missing, Laravel falls back to the configured fallback locale (English by default).

**Publishing translations** — to customize the shipped strings:

```
php artisan vendor:publish --tag=ai-filters-translations
```

This copies every locale to `lang/vendor/ai-filters//ai-filters.php`. Edit whichever you need. Published files take precedence over the ones shipped in the package.

**Overriding via config** — for a table-specific label you can bypass translations entirely by setting the string in `config/ai-filters.php`:

```
'action' => [
    'label' => 'Ask the AI',           // wins over the translation
    'modal_heading' => null,           // null → translation is used
    'modal_description' => null,
],
```

Every `null` value falls back to the translated string; every string value wins over it.

Missing a language? PRs welcome — copy `resources/lang/en/ai-filters.php`, translate, open a pull request.

### Customising the system prompt

[](#customising-the-system-prompt)

The full system prompt that steers the AI lives in a Markdown file, not in PHP code. You can override it with your own file without touching the package.

**1. Publish the default template** so you have a copy to work from:

```
php artisan vendor:publish --tag=ai-filters-prompt
```

This copies the built-in template to `resources/prompts/ai-filters/filter-agent.md`.

**2. Point the plugin at your file** either via `.env`:

```
AI_FILTERS_PROMPT_PATH="${PWD}/resources/prompts/ai-filters/filter-agent.md"
```

or directly in `config/ai-filters.php`:

```
'prompt_path' => resource_path('prompts/ai-filters/filter-agent.md'),
```

When `prompt_path` is `null`, the built-in template is used.

**3. Placeholders** — the template is rendered with `strtr()` against:

PlaceholderReplaced with`{{available}}`pretty-printed JSON list of filters + fields + rules + options`{{current}}`JSON of the current `tableFilters` state`{{searchable}}`JSON array of searchable column names`{{currentSearch}}`current global search value`{{extra}}`rendered `ai-filters.instructions` text (empty when not set)Any placeholder you omit is simply not rewritten — keep only what you need.

Configuration reference
-----------------------

[](#configuration-reference)

`config/ai-filters.php`:

```
return [
    'provider' => env('AI_FILTERS_PROVIDER', 'anthropic'),
    'model'    => env('AI_FILTERS_MODEL'),
    'api_key'  => env('AI_FILTERS_API_KEY'),

    'instructions' => null, // extra system-prompt text appended to the agent

    'prompt_path'  => env('AI_FILTERS_PROMPT_PATH'), // override path to MD template, null = built-in

    'action' => [
        'label'             => 'AI Filter',
        'icon'              => 'heroicon-o-sparkles',
        'modal_heading'     => 'Filter with AI',
        'modal_description' => 'Describe what you want to find. Active filters are sent as context.',
    ],
];
```

KeyPurpose`provider`Name of the `laravel/ai` provider to use (`anthropic`, `openai`, ...).`model`Specific model id. `null` = provider default.`api_key`Optional. Overrides the provider's configured API key at boot.`instructions`Free text appended to the agent's system prompt. Use for table-specific business rules.`prompt_path`Absolute path to a Markdown prompt template. `null` = built-in template.`action.*`Visual defaults for the action button and modal.How it works
------------

[](#how-it-works)

1. The user clicks **AI Filter** and types a prompt.
2. The plugin reads the table's filters via `$table->getFilters()` and extracts each filter's name, type, accepted form-field keys, and (for `SelectFilter`) its options.
3. It also reads the current `$livewire->tableFilters` and `$livewire->tableSearch`.
4. All of the above is passed to a `FilterAgent` (a `laravel/ai` Agent with `HasStructuredOutput`), which returns: ```
    {
      "filters": [
        { "filter": "status", "key": "values", "values": ["active"] },
        { "filter": "tier",   "key": "value",  "value": "platinum" }
      ],
      "search": null
    }
    ```
5. The plugin merges those updates back into `$livewire->tableFilters` (and sets `$livewire->tableSearch` if the AI returned a search query).
6. Filament re-renders the table with the new state.

Troubleshooting
---------------

[](#troubleshooting)

### `AI provider [anthropic] has insufficient credits or quota`

[](#ai-provider-anthropic-has-insufficient-credits-or-quota)

Anthropic free credit grants are scoped to the Workbench / Claude Code, not the API. Add real billing credit at [console.anthropic.com → Billing](https://console.anthropic.com/settings/billing)and create a fresh API key afterwards.

### `model: claude-3-5-haiku-20241022` not found

[](#model-claude-3-5-haiku-20241022-not-found)

Some legacy models are not enabled on every tier. Switch to a current model:

```
AI_FILTERS_MODEL=claude-haiku-4-5-20251001
```

### "No matching filters" warning

[](#no-matching-filters-warning)

The AI couldn't map the request to any available filter. Either:

- Add more filters to the table that cover the request, or
- Add hints in `ai-filters.instructions` (e.g. mappings between user terminology and filter names), or
- Make the request more specific.

### Verify config is loaded after `.env` changes

[](#verify-config-is-loaded-after-env-changes)

```
php artisan config:clear
```

### Inspecting the agent's raw response

[](#inspecting-the-agents-raw-response)

A `Log::info('AiFilterAction', [...])` entry is written on every run. Check `storage/logs/laravel.log` to see the prompt, the filter list sent to the AI, and the structured response it returned.

Architecture
------------

[](#architecture)

```
packages/webdirect/ai-filters/
├── composer.json
├── config/
│   └── ai-filters.php
├── resources/
│   └── prompts/
│       └── filter-agent.md         # default system prompt template
└── src/
    ├── AiFiltersPlugin.php         # Filament Plugin contract
    ├── AiFiltersServiceProvider.php # config + prompt publish, provider key override
    ├── Actions/
    │   └── AiFilterAction.php      # the table header action
    └── Agents/
        └── FilterAgent.php         # laravel/ai agent w/ structured output

```

Credits
-------

[](#credits)

- Original idea: [this video](https://www.youtube.com/watch?v=82ntd5LopoI) on the [Filament Daily](https://www.youtube.com/@FilamentDaily) channel by Povilas Korop. Go subscribe.
- Built on top of [`laravel/ai`](https://laravel.com/docs/13.x/ai-sdk) and [Filament v4](https://filamentphp.com).

License
-------

[](#license)

MIT

###  Health Score

40

—

FairBetter than 86% of packages

Maintenance89

Actively maintained with recent releases

Popularity14

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity42

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

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

3

Last Release

53d ago

### Community

Maintainers

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

---

Top Contributors

[![PrunaCatalin](https://avatars.githubusercontent.com/u/26250063?v=4)](https://github.com/PrunaCatalin "PrunaCatalin (7 commits)")

---

Tags

laravelaifilamentfilament-pluginfilamentphpnatural-languagelaravel-aitable-filtersai-filters

### Embed Badge

![Health badge](/badges/webdirect-ai-filters/health.svg)

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

###  Alternatives

[jibaymcs/filament-tour

Bring the power of DriverJs to your Filament panels and start a tour !

12351.0k](/packages/jibaymcs-filament-tour)[hammadzafar05/mobile-bottom-nav

A thumb-friendly mobile bottom navigation bar for Filament panels. It programmatically integrates with the Filament navigation registry to provide a seamless, ergonomic mobile experience with full support for dark mode and safe-area insets.

1812.3k](/packages/hammadzafar05-mobile-bottom-nav)[wsmallnews/filament-nestedset

Filament nestedset tree builder powered by kalnoy/nestedset with Filament v4 and v5 support

196.5k14](/packages/wsmallnews-filament-nestedset)

PHPackages © 2026

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