solution-forest/ai-kit-filament
Seamlessly integrate Solution Forest AI Kit with Filament. Add AI chat, assistants, and configurable model/provider settings to your admin panel using ready-made resources and widgets for fast setup.
This package is the Filament v5 admin surface for the solutionforest/ai-kit core library. It does not implement retrieval or LLM calls itself — it gives you Resources and Pages over the core package's models (knowledge bases, documents, conversations, messages). Install the core package first, then the panel.
composer require solutionforest/ai-kit solutionforest/ai-kit-filament
php artisan vendor:publish --tag="ai-kit-config" # core config
php artisan vendor:publish --tag="ai-kit-filament-config"
php artisan vendor:publish --tag="ai-kit-migrations" # often lives in the core package
php artisan migrate
php artisan filament:assets
Register the plugin in the panel provider:
public function panel(Panel $panel): Panel
{
return $panel
->plugin(\SolutionForest\AiKit\Filament\AiKitFilamentPlugin::make());
}
Because the package is early (11 stars, first releases in 2026), confirm the actual class/namespace by reading src/*Plugin.php and composer.json before writing code against it.
Where to look first, in this order:
config/ai-kit.php — provider credentials, default embedding/chat models, storage disk, chunk sizes. This is where 90% of "it doesn't work" answers live.KnowledgeBaseResource and its relation managers — that's the ingestion workflow you'll be customizing.Playground page — the fastest way to validate your credentials and models end-to-end before touching your own app code.First use case: create a knowledge base in the admin, upload a PDF or add a documentation URL, confirm the document moves from pending to indexed (this requires a running queue worker), then open the Playground and ask a question that can only be answered from that document. If the answer cites your file, the pipeline is wired correctly and you can move on to integrating retrieval into your own controllers.
Treat the panel as an operator console, not the product. The natural split is: admins use this package's UI to curate knowledge and audit conversations; your end users hit your own controllers/Livewire components that call the core ai-kit services. Don't expose the Playground to non-admins — it is effectively an unmetered LLM proxy.
Gate everything. Filament Resources are reachable by any user who can access the panel unless you restrict them. Implement canAccessPanel() on your User model, then add policies per model and, if the plugin supports it, restrict via the plugin's configuration:
AiKitFilamentPlugin::make()
->navigationGroup('AI')
->authorize(fn (User $user) => $user->hasRole('ai-admin'));
Multi-tenant scoping. If you use Filament tenancy, the knowledge base Resource usually needs a tenant_id/team_id column and a global scope. Add the ownership column via your own migration rather than editing vendor migrations, and override getEloquentQuery() in a Resource subclass. Subclassing the vendor Resource and re-registering it is the intended extension path:
AiKitFilamentPlugin::make()
->resources([
\App\Filament\Resources\KnowledgeBaseResource::class,
]);
Ingestion patterns. Two entry points matter day-to-day: file upload (disk + MIME validation, then a queued chunk/embed job) and URL crawl. Both should run on a dedicated queue so a slow crawl doesn't block the UI's Livewire requests:
// config/queue.php or per-job
'ingest' => ['connection' => 'redis', 'queue' => 'ai-ingest'],
Dispatch ingestion from your own code too — when a user uploads a support ticket attachment in your app, push it into the same knowledge base. Reuse the core package's ingestion action/service so chunking and embedding config stay consistent with what the admin UI produces.
Conversation logs as a product asset. The conversation/message models with token counts are the most underrated part of this package. Wire a custom Filament widget or your own dashboard query over them to answer: cost per user, most-asked questions, failures by model, p95 latency. Also use the logged conversations as your eval set — export real prompts to build a regression suite before changing chunk sizes or models.
Playground as a debugging harness. Standardize on one "golden" knowledge base with known answerable and unanswerable questions. When retrieval quality drops, run those through the Playground before and after any config change (chunk size, top-k, embedding model). Note the model and settings in the conversation title or a note field so the logs are self-documenting.
Analytics widgets. Keep heavy aggregation out of Livewire widgets — precompute into a ai_usage_daily table via a scheduled command and have widgets read from it. Filament widgets polling against raw messages tables will fall over once you have real traffic.
Testing. RefreshDatabase plus Queue::fake() for ingestion assertions, and swap the LLM provider for a fake in your test container so Playground/retrieval tests are deterministic and free.
QUEUE_CONNECTION=sync with a job that times out, or no worker running. Check failed_jobs and php artisan queue:failed before debugging anything else.ai-kit-filament is pinned to Filament v5 and Livewire 3. Mixing with a v3/v4 panel — or an ai-kit core that's a minor version behind — produces confusing "class not found" and Livewire hydration errors. Pin all three in composer.json and bump together.knowledge_bases/documents. Publishing both migration sets will fail on CREATE TABLE. Check --pretend first, or guard with Schema::hasTable().php artisan config:cache after editing config/ai-kit.php, otherwise the running worker and web process disagree about the provider/model, and the two produce different answers for the same query.upload_max_filesize, post_max_size, and Livewire's temporary_file_upload.rules.resources()/pages()/widgets() registration methods, publishable views for overriding table columns and forms, and the core package's ingestion/retrieval services (call these directly from your app rather than duplicating chunking logic). If the plugin doesn't expose a setting you need, subclass the Resource and register the subclass — don't edit vendor/.How can I help you explore Laravel packages today?