janschuri / eloquent-ai-tools
Give Eloquent models the ability to register themselves as AI tool sources.
Requires
- php: ^8.3
- illuminate/contracts: ^13.0
- illuminate/database: ^13.0
- illuminate/json-schema: ^13.16
- illuminate/support: ^13.0
- laravel/ai: ^0.10
Requires (Dev)
- larastan/larastan: ^3.10
- laravel/pint: ^1.29
- orchestra/testbench: ^11.0
- pestphp/pest: ^4.0
This package is auto-updated.
Last update: 2026-08-12 20:33:35 UTC
README
Turn Eloquent models into safe, structured AI tools with a small, drop-in layer that stays inside normal Eloquent conventions.
The Problem
Giving an AI agent access to your application data usually pushes you into one of two bad options:
- Let it generate SQL. Fast to prototype, but now you are validating and sandboxing arbitrary queries.
- Hand-write tool classes around every model or operation. Safer, but full of boilerplate and easy to let drift away from your schema.
EloquentAiTools takes a third path. Instead of introducing a parallel query system, it plugs into the Eloquent models, scopes, casts, and relations you already have. You describe what a model should expose, and the package builds a read-only query tool from that config plus the model schema Laravel already knows about.
No generated SQL. No hand-maintained JSON schema. No separate tool class per model.
Installation
composer require janschuri/eloquent-ai-tools
Requirements
- PHP
^8.3 - Laravel
^13.0 - Laravel AI SDK (
laravel/ai)^0.10
Quick Start
<?php use EloquentAiTools\Concerns\HasToolModel; use EloquentAiTools\Decision; use EloquentAiTools\ToolBuilder; use Illuminate\Database\Eloquent\Model; use Laravel\Ai\Tools\Request; class Article extends Model { use HasToolModel; public static function toolConfig() { return static::newToolConfig([ 'title' => 'Article headline', 'status' => 'Publication status', 'views' => 'View count', 'published_at' => 'Publish date', ]) ->label('Articles') ->modelDescription('Articles from the CMS.') ->allowRead() ->maxLimit(50) ->whereMaxDepth(3) ->whereMaxConditionsPerGroup(10) ->scopes([ 'published' => 'Only published articles.', ]) ->reading(function (Request $request, array $appliers) { return Decision::accept(); // or Decision::deny(...) / Decision::approve(...) / a bool }); } } $tools = ToolBuilder::make() ->add(Article::toolConfig()) ->build();
That exposes a read_articles tool. Its schema and description are generated from the Article config plus the active query resolvers, so the tool stays aligned with the model instead of becoming a second thing to maintain.
If you need a more specific or collision-resistant name, add a tool key:
->toolKey('cms')
That changes the tool name to read_cms_articles.
Out of the box, the tool supports:
- an
explainfield for query intent - reusable numeric
expressions - explicit
selectprojections, including whole-result and grouped aggregates - required
distinctcontrol for duplicate-prone relation queries - typed
wherefilters, including nested condition groups and relation existence checks groupByorderBylimitandoffset- auto-derived relation joins for supported dotted relation paths
- Eloquent scopes, so you can keep using Laravel's native way to restrict model queries
- scoped eager loading for configured relations, including nested
withpaths - scoped direct relation aggregates through
withAggregate - an optional per-model read policy callback
Documentation
The long-form docs now live in /wiki and are intended to be mirrored to the GitHub wiki on pushes to master:
- Home
- Quick Start
- Tool Configuration
- Query Reference
- Query Model
- Relation Paths And Scopes
- Policies And Approvals
- Exposed Surface
- Responses And Errors
- Caching
- Roadmap
Changelog
Releases are tagged automatically from Conventional Commits — see GitHub Releases for what changed in each version.
License
MIT