Download the PHP package behindsolution/laragrep without Composer

On this page you can find all versions of the php package behindsolution/laragrep. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package laragrep

Latest Version Tests

Transform natural language questions into safe, parameterized SQL queries using AI.
LaraGrep uses an agent loop — the AI executes queries, sees the results,
and iteratively reasons until it can provide a final answer.


Quick Start

1. Install

2. Publish config and migrations

3. Create the SQLite database and run migrations

LaraGrep stores conversations, monitor logs, and recipes in a separate SQLite database by default, keeping everything isolated from your main database.

Create the file and run migrations:

Add a laragrep connection to your config/database.php:

Then point LaraGrep to it in your .env:

Run the migrations:

Already using SQLite as your main database? You can skip the connection setup — LaraGrep will use the default sqlite connection as-is.

4. Add your API key to .env

5. Define your tables in config/laragrep.php

6. Ask your first question

That's it. LaraGrep validates, executes, and answers automatically.


Monitor

LaraGrep includes a built-in monitoring dashboard. Enable it to track every query, error, token usage, and performance metric.

Enable

Access the dashboard at GET /laragrep/monitor:

Protect it with middleware:


Async Mode

The agent loop can take 30-100+ seconds with multiple iterations, easily exceeding PHP or Nginx timeouts. Async mode dispatches the processing to a queue job and returns immediately.

Enable

Requires a real queue driver (redis, database, sqs, etc.). LaraGrep will throw an exception at boot if the queue connection uses the sync driver.

When enabled, all requests become async — the frontend doesn't decide, the backend does.

How It Works

The agent loop runs in a background job. When it finishes, the result is delivered via broadcasting (WebSocket) and/or polling (GET endpoint).

Polling

Returns the current status:

While the AI is working, the response includes a progress message describing the current step:

Or when completed:

Or on failure:

Broadcasting (Optional)

If you have Laravel broadcasting configured (Reverb, Pusher, Soketi, Ably), LaraGrep broadcasts two events on the channel returned in the response:

Event Payload
laragrep.answer.progress queryId, iteration, message
laragrep.answer.ready queryId, summary, conversationId, recipeId
laragrep.answer.failed queryId, error

Frontend example (Laravel Echo):

For private channels, set LARAGREP_ASYNC_PRIVATE=true and register the channel authorization in your routes/channels.php:

Broadcasting is entirely optional — polling via GET works without any broadcasting setup. If you only want polling, make sure broadcasting is disabled in your .env:

Completed records cleanup

Async records are automatically cleaned up after 24 hours (configurable via LARAGREP_ASYNC_RETENTION_HOURS).


How It Works

Unlike simple text-to-SQL tools, LaraGrep uses an agent loop:

  1. You ask a question in natural language
  2. The AI analyzes the schema and decides which queries to run
  3. LaraGrep validates and executes the queries safely
  4. The AI sees the results and decides: run more queries, or provide the final answer
  5. Repeat until the AI has enough data to answer (up to max_iterations)

This means the AI can build on previous results, self-correct, break down complex analysis into steps, and batch independent queries in a single iteration.


Configuration

AI Provider

OpenAI:

Anthropic:

Ollama (local):

Ollama exposes an OpenAI-compatible API, so it works with the openai provider. The API key can be any non-empty string. This keeps your data fully local.

Runtime AI Config (per-request)

The AI provider, API key, model, and fallback can all be swapped at request time via middleware — useful for multi-tenant setups where each tenant brings its own API key (BYOK) or chooses a different model.

Apply it on the LaraGrep routes (or globally) and the new values take effect for that request — both sync and async.

How it works:

Same pattern as user_language — you don't need a custom controller, just a middleware that mutates config().

Fallback Provider

If the primary provider fails (timeout, rate limit, API down), LaraGrep can automatically retry with a fallback:

Works in any direction — OpenAI primary with Anthropic fallback, or vice versa. When the primary succeeds, the fallback is never called. No cooldown, no circuit breaker — just tries in order.

Schema Loading Mode

Mode Behavior
manual Only use tables defined in config (default)
auto Auto-load from information_schema (MySQL/MariaDB/PostgreSQL)
merged Auto-load first, then overlay config definitions

Table Definitions

Define tables using fluent classes with IDE autocomplete:

Supported column types: id(), bigInteger(), integer(), smallInteger(), tinyInteger(), string(), text(), decimal(), float(), boolean(), date(), dateTime(), timestamp(), json(), enum().

Modifiers: ->unsigned(), ->nullable(), ->description().

For JSON columns, ->template() provides an example structure so the AI knows how to query with JSON_EXTRACT.

Organizing Large Schemas

For projects with many tables, extract each definition into its own class:

Multi-Connection Tables

When some tables live in a different database, use ->connection() to tell LaraGrep which connection to use for queries on that table:

The second parameter is optional and describes the database engine. This is important when the external database uses a different SQL dialect (e.g., ClickHouse, PostgreSQL, SQLite) — the AI will generate compatible syntax for each table.

When the AI encounters tables on different connections, it will:

  1. Generate engine-compatible SQL for each table
  2. Include the connection name in each query entry so the executor runs it on the right database
  3. Avoid cross-connection JOINs — instead, it queries each database separately and combines the results in the final answer

Multi-Tenant / Dynamic Connections

In multi-tenant applications where each tenant has its own database, the connection name is only known at runtime. Pass a Closure instead of a string to resolve the connection dynamically:

The closure is evaluated per-request, so it works in HTTP (middleware sets the tenant), queue jobs, and artisan commands — as long as your tenant context is available.

You can mix dynamic and static connections. For example, tenant tables on a dynamic connection and shared tables on a fixed central database:

Table-level connections also accept closures:

Named Scopes (Contexts)

Work with multiple databases or table sets:

Select a scope via the URL: POST /laragrep/analytics

Query Protection

Agent Loop

Simple questions typically resolve in 1-2 iterations. Complex analytical questions may need more. Higher values increase capability but also cost.

Smart Schema

For large databases, LaraGrep can make an initial AI call to identify only the relevant tables, reducing token usage across all iterations.

Activates automatically when the table count reaches the threshold. With 200 tables and only 5 relevant, this reduces token usage by ~60%.

Question Clarification

When users ask vague questions ("Show me the sales"), the AI may guess filters or return overly generic results. Clarification adds a pre-agent-loop step that analyzes the question against developer-defined rules and asks for missing context before proceeding.

Enable:

Custom clarification prompt:

Add extra instructions to the clarification system prompt — for example, to prevent the AI from mentioning internal table names in its questions:

Define rules per context:

Flow:

Clarification response:

The frontend can display these questions, collect the answers, and resubmit with clarification_answers. LaraGrep will call the AI to reformulate the original question into a precise, self-contained question and then run the agent loop with it automatically.

Answering clarification questions:

The AI reformulates the vague question into something like "Show me the sales for Store Centro in January 2026" and proceeds with the agent loop. The reformulated question is what gets stored in conversation history and recipes.

If reformulation fails for any reason, the original question is used as fallback — the agent loop still runs.

Programmatic usage:

Token usage impact:

The clarification call is lightweight — it sends only table names and descriptions (no columns or relationships), plus the rules and question. Compared to the agent loop:

Call Input (typical) Output (typical)
Clarification ~200-400 tokens ~15-40 tokens
Suggestion Filter ~100-200 tokens ~10-20 tokens
Reformulation ~150-300 tokens ~15-30 tokens
Smart Schema Filter ~150-300 tokens ~15-30 tokens
Agent Loop (per iteration) ~500-2000+ tokens ~100-300 tokens

When the question is clear ("proceed"), the overhead is a single lightweight API call (~200-400 input tokens). When clarification is triggered, it saves the entire agent loop cost (potentially 3-10 iterations) by catching vague questions early. The reformulation call is equally lightweight — it only sends the original question and Q&A pairs (no schema), producing a plain text question.

Conversation-aware clarification:

When a conversation_id is provided, the clarification step receives the conversation history. This prevents false positives — for example, "Please continue" in an ongoing conversation won't trigger clarification because the AI sees the full context.

Page suggestions:

If your application has existing dashboards or reports that overlap with common questions, you can list them as suggestions. When the user's question matches a suggestion, the AI includes it as a natural clarification question — e.g., "Would you like me to query the data now, or would you prefer to check the existing Incidents Dashboard (/dashboard/incidents)?"

Each suggestion needs a label (what the user sees), a description (what the AI uses to judge relevance), and a url. When clarification is triggered and suggestions are configured, a separate lightweight AI call filters which suggestions are relevant to the question. Only matching suggestions are included in the response — if none match, the suggestions field is omitted. The frontend can render them as clickable links alongside the clarification questions.

With the feature disabled or no clarification_rules defined, zero API calls are made — clarifyQuestion() returns null immediately.

Answer Guard

A final review pass on every answer before it reaches the user. The AI receives the answer and a list of rules defined per context, then either keeps it, rewrites it to comply, or replaces it with a natural refusal. Use this to prevent leaking internal table names, tenant identifiers, raw SQL, or anything else end users shouldn't see.

Enable:

Define rules per context:

Flow:

The frontend always receives the same response shape — only the summary content changes. The user never sees that a guard ran; refusals are phrased naturally by the AI.

Behavior:

Token usage:

Call Input (typical) Output (typical)
Answer Guard ~150-400 tokens (rules + summary) ~50-200 tokens (rewritten or original)

Programmatic usage:

Global Filters

Mandatory SQL fragments that must appear in every query touching specific tables. Mirrors the role of Eloquent global scopes — use them to enforce multi-tenant access, soft-delete-style restrictions, or row-level security at the LaraGrep layer.

Define per context:

Accepts a Closure (evaluated per request), a static array, or null.

How it works:

  1. The closure is evaluated by the controller in HTTP context — auth(), request(), and any per-request state are available.
  2. The resolved map is passed into the system prompt as a MANDATORY GLOBAL FILTERS section. The AI is told to copy each fragment exactly into the WHERE clause of every query that references the table.
  3. After the AI generates a query, QueryValidator checks: for each filtered table actually referenced in the SQL, the corresponding fragment must appear verbatim. If missing, the query is rejected and the AI is forced to retry with a specific error message.
  4. If the AI can't produce a compliant query within max_iterations, the request fails — the query never executes without the filter.

Async safety:

Closures cannot be serialized into queue jobs. The controller resolves the closure once during HTTP dispatch and passes the resulting array of strings to ProcessQuestionJob. The job runs the filters as-is — never re-evaluates the closure in worker context, where auth()/request() would be unavailable. The same applies to broadcasting and polling — both see the already-filtered result.

Inlined values, not bindings:

Fragments must contain literal values, not ? placeholders. The values come from server-trusted sources (auth, tenant context, IDs from the database), so inlining is safe — but cast IDs to int and quote/escape strings before building the fragment.

Programmatic override:

Pass null (default) to use the configured closure. Pass an array (even empty []) to override and disable filters for that call.

No filters configured?

If global_filters is null or returns [], no AI-side prompt changes happen and no validation is added — zero overhead per request.

Conversation Persistence

Multi-turn conversations are enabled by default. Previous questions and answers are sent as context for follow-ups.

Route Protection


Usage

API Endpoint

Basic request:

With authentication and options:

Using a named scope:

Debug response (when debug: true):

Programmatic Usage

Formatting Results

Use formatResult() to transform raw query results into structured formats via AI.

Query format — a single consolidated SQL query for export:

Returns the SQL itself, no LIMIT. Use it with Laravel's streaming tools:

Notification format — ready-to-render content for email, Slack, or webhooks:

Saved Queries (Recipes)

Auto-save a "recipe" after each answer — the question, scope, and queries that worked. The response includes a recipe_id for exports, notifications, or scheduled re-execution.

Enable:

After enabling, publish and run the migration for the laragrep_recipes table.

API response with recipe:

Dispatch a recipe:

The period parameter controls timing:

LaraGrep fires a RecipeDispatched event. Your app handles the rest via a listener:

Programmatic usage:

With monitor enabled? Inject LaraGrep\Monitor\MonitorRecorder instead of LaraGrep. It wraps the same methods (answerQuestion, replayRecipe, formatResult) and automatically records every execution in the dashboard. When the monitor is disabled, MonitorRecorder resolves to null — so use LaraGrep as the safe default.


Extending

Custom AI Client

Implement LaraGrep\Contracts\AiClientInterface and rebind in a service provider:

Custom Metadata Loader

LaraGrep auto-detects MySQL/MariaDB and PostgreSQL. For other databases, implement LaraGrep\Contracts\MetadataLoaderInterface:

Custom Conversation Store

Implement LaraGrep\Contracts\ConversationStoreInterface for Redis, file-based storage, etc.:


Environment Variables

Variable Default Description
LARAGREP_PROVIDER openai AI provider (openai, anthropic)
LARAGREP_API_KEY API key for the AI provider
LARAGREP_MODEL gpt-4o-mini Model identifier
LARAGREP_BASE_URL Override API endpoint URL
LARAGREP_MAX_TOKENS 1024 Max response tokens
LARAGREP_TIMEOUT 300 HTTP timeout in seconds
LARAGREP_FALLBACK_PROVIDER Fallback AI provider
LARAGREP_FALLBACK_API_KEY Fallback API key
LARAGREP_FALLBACK_MODEL Fallback model identifier
LARAGREP_FALLBACK_BASE_URL Fallback API endpoint URL
LARAGREP_MAX_ITERATIONS 10 Max query iterations per question
LARAGREP_MAX_ROWS 20 Max rows per query (auto LIMIT)
LARAGREP_MAX_QUERY_TIME 3 Max query execution time (seconds)
LARAGREP_SMART_SCHEMA Table count threshold for smart filtering
LARAGREP_CLARIFICATION_ENABLED false Enable pre-query question clarification
LARAGREP_CLARIFY_SYSTEM_PROMPT Extra instructions for clarification prompt
LARAGREP_ANSWER_GUARD_ENABLED false Enable answer guard review on final summaries
LARAGREP_SCHEMA_MODE manual Schema loading mode
LARAGREP_USER_LANGUAGE en AI response language
LARAGREP_RESPONSE_FORMAT html Summary format: html, markdown, or text
LARAGREP_CONNECTION Database connection name
LARAGREP_DATABASE_TYPE DB type hint for AI
LARAGREP_DATABASE_NAME DB_DATABASE DB name hint for AI
LARAGREP_EXCLUDE_TABLES Comma-separated tables to hide
LARAGREP_DEBUG false Enable debug mode
LARAGREP_ROUTE_PREFIX laragrep API route prefix
LARAGREP_CONVERSATION_ENABLED true Enable conversation persistence
LARAGREP_CONVERSATION_CONNECTION sqlite DB connection for conversations
LARAGREP_CONVERSATION_MAX_MESSAGES 10 Max messages per conversation
LARAGREP_CONVERSATION_RETENTION_DAYS 10 Auto-delete conversations after days
LARAGREP_MONITOR_ENABLED false Enable monitoring dashboard
LARAGREP_MONITOR_CONNECTION sqlite DB connection for monitor logs
LARAGREP_MONITOR_TABLE laragrep_logs Table name for monitor logs
LARAGREP_MONITOR_RETENTION_DAYS 30 Auto-delete logs after days
LARAGREP_RECIPES_ENABLED false Enable recipe auto-save
LARAGREP_RECIPES_CONNECTION sqlite DB connection for recipes
LARAGREP_RECIPES_TABLE laragrep_recipes Table name for recipes
LARAGREP_RECIPES_RETENTION_DAYS 30 Auto-delete recipes after days
LARAGREP_ASYNC_ENABLED false Enable async mode
LARAGREP_ASYNC_CONNECTION laragrep DB connection for async table
LARAGREP_ASYNC_TABLE laragrep_async Table name for async records
LARAGREP_ASYNC_RETENTION_HOURS 24 Auto-delete records after hours
LARAGREP_ASYNC_QUEUE default Queue name for async jobs
LARAGREP_ASYNC_QUEUE_CONNECTION Queue connection (falls back to default)
LARAGREP_ASYNC_CHANNEL_PREFIX laragrep Broadcasting channel prefix
LARAGREP_ASYNC_PRIVATE false Use private broadcasting channels

Security

Testing

License

MIT


All versions of laragrep with dependencies

PHP Build Version
Package Version
Requires php Version ^8.1
illuminate/support Version ^10.0|^11.0|^12.0
illuminate/http Version ^10.0|^11.0|^12.0
illuminate/database Version ^10.0|^11.0|^12.0
illuminate/routing Version ^10.0|^11.0|^12.0
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package behindsolution/laragrep contains the following files

Loading the files please wait ...