sharifuddin / laravel-ai-bridge
A professional, robust, and modular AI-driven integration for Laravel, enabling LLMs (like Gemini) to dynamically execute application controller methods as tools.
Requires
- php: ^8.1|^8.2|^8.3|^8.4
- guzzlehttp/guzzle: ^7.2
- illuminate/cache: ^9.0|^10.0|^11.0|^12.0
- illuminate/http: ^9.0|^10.0|^11.0|^12.0
- illuminate/routing: ^9.0|^10.0|^11.0|^12.0
- illuminate/support: ^9.0|^10.0|^11.0|^12.0
Requires (Dev)
- orchestra/testbench: ^7.0|^8.0|^9.0|^10.0
- phpunit/phpunit: ^9.5|^10.0|^11.0
Suggests
- ext-mongodb: Required alongside mongodb/mongodb for the "mongodb" vector store driver.
- ext-pdo_mysql: Required for the "mysql" vector store driver (AI_VECTOR_STORE=mysql).
- ext-pdo_pgsql: Required for the default "postgresql" vector store driver, together with the pgvector Postgres extension (CREATE EXTENSION vector).
- mongodb/mongodb: Required to use the "mongodb" vector store driver (MongoDB Atlas Vector Search).
Provides
None
Conflicts
None
Replaces
None
README
A production-grade Laravel AI orchestration package. Laravel AI Bridge lets an LLM (Gemini, with a pluggable provider interface) discover the right application tool for a natural-language prompt via hybrid semantic + lexical retrieval, then executes it securely โ with strict argument validation, Laravel-authorization re-checks, multi-tenant isolation, and aggressive token/cost caching.
๐ Key Features
- Hybrid tool retrieval โ query normalization โ embedding โ vector search โ lexical scoring โ permission/tenant filtering โ ranked top-K โ confidence/ambiguity detection. The AI model only ever sees the smallest useful set of tool declarations, never your whole tool catalog.
- First-class
ToolInterfacetools โ define tools as small, testable classes (AI::tool(ListUsersTool::class)), mapped to your own Actions/Services โ not directly to controllers. - Full backward compatibility โ existing controllers reflected via
ToolProviderInterface/CachedControllerToolProviderkeep working, now flowing through the same secure retrieval + execution pipeline via an automatic adapter. - Security first โ every tool call is re-validated and re-authorized (
Gate/$user->can()) immediately before execution, even though retrieval already filtered by permission. AI tool-call output is never trusted as proof of authorization. - Multi-tenant isolation โ tools can declare
requiresTenant(); a pluggableTenantContextResolverInterfacelets your app supply the current company/branch/organization without the package assuming any specific tenancy package. - Pluggable vector store โ
VectorStoreInterfacewith PostgreSQL + pgvector as the default (AI_VECTOR_STORE=postgresql), plusmysql,mongodb,qdrant, andpineconeas drop-in alternatives, and a dependency-free in-memory/cache-backedArrayVectorStorefallback so the package works out of the box and degrades gracefully if the configured store is unavailable. - Token-efficient caching โ embeddings, retrieval results, and tool metadata are all cached via Laravel's cache abstraction, with keys safely namespaced by user/tenant so nothing leaks across accounts.
- Bounded, normalized results โ tool output is truncated and shaped into
{success, data, meta}before it ever reaches the AI or the HTTP response; large result sets never blow the context window. - Ready-to-use dual interfaces:
POST /api/ai/prompt(REST) andGET /ai/assistant(Copilot-style chat UI).
โ๏ธ Requirements
- PHP:
^8.1 | ^8.2 | ^8.3 | ^8.4 - Laravel:
^9.0 | ^10.0 | ^11.0 | ^12.0 - Google Gemini API key (chat + embeddings) from Google AI Studio
- (Default vector store): PostgreSQL with the
pgvectorextension (CREATE EXTENSION vector;) โ the store bootstraps its own table automatically on first use. - (Optional alternatives):
mysql(stock MySQL/MariaDB, no extension needed),mongodb(requirescomposer require mongodb/mongodb+ext-mongodb+ an Atlas Vector Search index),qdrant/pinecone(called over HTTP, no extra composer dependency). If the selected driver's dependencies/connection aren't available, the package automatically falls back to the built-in dependency-freearraydriver.
๐ฆ Installation
1. Install via Composer
composer require sharifuddin/laravel-ai-bridge
2. Publish Configuration
php artisan vendor:publish --tag=ai-bridge-config
3. Configure Environment
Add the following to your .env file:
For MYSQL
GEMINI_API_KEY='' AI_BRIDGE_EMBEDDING_DRIVER=gemini AI_BRIDGE_EMBEDDING_MODEL=gemini-embedding-001 # Vector store (default: postgresql, via the pgvector extension on your # existing Postgres connection). Switch drivers with a single env var: # AI_VECTOR_STORE=postgresql # default AI_VECTOR_STORE=mysql AI_BRIDGE_LEGACY_ENFORCE_PERMISSIONS=false
For postgresql
GEMINI_API_KEY=your-gemini-api-key AI_BRIDGE_EMBEDDING_DRIVER=gemini # Vector store (default: postgresql, via the pgvector extension on your # existing Postgres connection). Switch drivers with a single env var: AI_VECTOR_STORE=postgresql # default # AI_VECTOR_STORE=mysql # AI_VECTOR_STORE=mongodb # AI_VECTOR_STORE=qdrant # AI_VECTOR_STORE=pinecone # AI_VECTOR_STORE=array # dependency-free, local dev/testing only
4. Vector Store Architecture
VectorStoreInterface
โ
โโโ PostgreSQLVectorStore โ default (pgvector)
โโโ MySQLVectorStore
โโโ MongoVectorStore
โโโ QdrantVectorStore
โโโ PineconeVectorStore
โโโ ArrayVectorStore โ dependency-free fallback
๐ง Defining a first-class tool
namespace App\AiTools; use Sharifuddin\LaravelAiBridge\Execution\ExecutionContext; use Sharifuddin\LaravelAiBridge\Tools\AbstractTool; class ListUsersTool extends AbstractTool { public function name(): string { return 'list_users'; } public function category(): string { return 'users'; } public function description(): string { return 'List application users with pagination, search, status filtering and role filtering.'; } public function parametersSchema(): array { return [ 'search' => ['type' => 'string', 'required' => false, 'description' => 'Search by name or email'], 'status' => ['type' => 'string', 'required' => false, 'enum' => ['active', 'inactive']], 'per_page' => ['type' => 'integer', 'required' => false, 'default' => 20, 'min' => 1, 'max' => 100], ]; } public function permission(): ?string { return 'view-users'; } public function metadata(): array { return ['aliases' => ['users list', 'user list'], 'entity' => 'user', 'action' => 'list']; } public function execute(array $arguments, ExecutionContext $context): mixed { return app(\App\Services\UserService::class)->list($arguments, $context); } }
Register it (e.g. in a service provider's boot(), or list it in config/ai-bridge.php):
use Sharifuddin\LaravelAiBridge\Facades\AI; AI::tool(\App\AiTools\ListUsersTool::class);
Custom tool example for your own app
This is the pattern most apps use when they want AI to call their own business logic:
<?php namespace App\AiTools; use Sharifuddin\LaravelAiBridge\Execution\ExecutionContext; use Sharifuddin\LaravelAiBridge\Tools\AbstractTool; class WeatherTool extends AbstractTool { public function name(): string { return 'get_weather'; } public function category(): string { return 'weather'; } public function description(): string { return 'Get the current weather for a city using the app weather service.'; } public function parametersSchema(): array { return [ 'city' => [ 'type' => 'string', 'required' => true, 'description' => 'City name, for example Dhaka or London', ], 'unit' => [ 'type' => 'string', 'required' => false, 'enum' => ['celsius', 'fahrenheit'], 'default' => 'celsius', ], ]; } public function permission(): ?string { return null; // or 'view-weather' if you want to require authorization } public function metadata(): array { return [ 'aliases' => ['weather report', 'current weather', 'forecast'], 'entity' => 'weather', 'action' => 'lookup', ]; } public function execute(array $arguments, ExecutionContext $context): mixed { $city = $arguments['city']; $unit = $arguments['unit'] ?? 'celsius'; return app(\App\Services\WeatherService::class)->getForCity($city, $unit); } }
And register it in a service provider:
use Sharifuddin\LaravelAiBridge\Facades\AI; public function boot(): void { AI::tool(\App\AiTools\WeatherTool::class); }
Then index and ask the assistant:
php artisan ai:tools:index
POST /api/ai/prompt { "prompt": "What is the weather in Dhaka today?" }
The AI will only see the declarations for the tools that match the prompt, and it will execute the selected custom tool only after validation + re-authorization.
Index it into the vector store, then chat:
php artisan ai:tools:index
POST /api/ai/prompt
{"prompt": "Show me all active users"}
Behind the scenes: normalize โ embed โ vector search โ hybrid rank โ permission/tenant filter โ send only the matching tool declarations to Gemini โ validate its chosen arguments โ re-authorize โ execute โ return a compact, bounded JSON result.
Multi-tenant tools
public function requiresTenant(): bool { return true; }
// AppServiceProvider::register() $this->app->bind(TenantContextResolverInterface::class, fn () => new CallbackTenantContextResolver(fn () => auth()->user() ? ['company_id' => auth()->user()->company_id] : null ) );
๐งฉ Backward compatibility (legacy controller tools)
Controllers previously discovered via ToolProviderInterface/CachedControllerToolProvider (implementing the interface, or just reflected by public method) keep working with zero changes. They are wrapped as LegacyControllerToolAdapter instances and merged into the same registry, so they get the same semantic retrieval, argument validation, and authorization re-check as first-class tools. Disable this via ai-bridge.legacy_controllers.enabled = false once fully migrated.
The original AiProcessorInterface methods (processPrompt(), selectRelevantTools()) are preserved unchanged for any code calling them directly. AiController and the new AiService::chat() pipeline are what changed.
โก Artisan Commands
php artisan ai:tools:index # index new/changed tools (skips unchanged embeddings) php artisan ai:tools:reindex # force re-embed everything php artisan ai:tools:reindex --tool=list_users php artisan ai:tools:list # inspect the currently registered tools
๐ Architecture
User โ ChatRequest โ QueryNormalizer โ EmbeddingProvider โ VectorStore
โ (semantic + lexical + metadata) hybrid scoring โ permission/tenant filter
โ ranked top-K โ confidence/ambiguity check โ AiProvider (Gemini)
โ ArgumentValidator โ re-authorization โ ToolExecutor โ your Action/Service
โ ToolResult (normalized, truncated) โ AI โ final response
Key interfaces (all in Sharifuddin\LaravelAiBridge\Contracts): ToolInterface, ToolRegistryInterface, VectorStoreInterface, EmbeddingProviderInterface, AiProviderInterface, TenantContextResolverInterface. Swap any implementation without touching the rest of the pipeline.
See config/ai-bridge.php for every tunable: retrieval weights/thresholds, cache TTLs, vector store connection, embedding driver, execution limits.
๐ Security Model
- AI never decides authorization โ Laravel does, twice: once at retrieval (so disallowed tools are never even shown to the model) and again immediately before execution.
- Arguments are whitelisted and validated against each tool's declared schema (types,
min/max,enum) โ an AI-suppliedper_page=999999is rejected, not clamped silently. - Only tools registered in the
ToolRegistrycan ever be executed โ there is no arbitrary class/method invocation from AI-generated strings. - Cache keys fold in a security fingerprint (user + tenant), so retrieval/embedding caches can never serve one user's/tenant's results to another.
๐ฌ Chat UI
๐งช Testing
composer install vendor/bin/phpunit
๐ License
This package is open-sourced software licensed under the MIT license.
๐ค Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
๐จโ๐ป Author
Sharif Uddin
- GitHub: @sharifwebdev
- Email: sharif.webpro@gmail.com
- Website: https://sharifwebdev.github.io/
๐ Support
If you find this package useful, please consider:
- โญ Starring the repository
- ๐ Reporting issues
- ๐ก Suggesting features
- ๐ง Submitting pull requests
๐ Changelog
Detailed changes for each release are documented in the CHANGELOG.md.
๐ Links
๐ฏ Quick Start Cheat Sheet
# 1. Install composer require sharifuddin/laravel-ai-bridge # 2. Publish config php artisan vendor:publish --tag=ai-bridge-config # 3. Add to .env GEMINI_API_KEY=your-gemini-api-key AI_BRIDGE_EMBEDDING_DRIVER=gemini AI_VECTOR_STORE=postgresql # 4. Define a tool AI::tool(\App\AiTools\ListUsersTool::class); # 5. Index tools php artisan ai:tools:index # 6. Chat via API POST /api/ai/prompt "prompt": "Show me all active users" # OR use the Chat UI GET /ai/assistant
Happy Building! ๐คโจ



