knobik/sql-agent
Self-learning text-to-SQL agent for Laravel that turns natural language into accurate, safe SQL. Uses schema introspection, a curated knowledge base, query patterns, and conversation memory; recovers from errors and saves learnings. Includes built-in chat UI.
Installation:
composer require knobik/sql-agent
php artisan sql-agent:install
This publishes config, migrations, and assets.
Configure LLM Provider (.env):
SQL_AGENT_LLM_PROVIDER=openai # or anthropic, ollama, etc.
SQL_AGENT_LLM_MODEL=gpt-4o
SQL_AGENT_LLM_API_KEY=your_key_here
First Query (in a controller/route):
use Knobik\SqlAgent\Facades\SqlAgent;
$response = SqlAgent::run('List all active users with their order count');
dd($response->results); // Raw query results
Key Files to Review:
config/sql-agent.php (LLM settings, database connections)database/migrations/ (for knowledge base tables)resources/views/vendor/sql-agent/ (chat UI customization)Replace manual SQL writing with natural language:
// Instead of:
// DB::table('users')->where('active', true)->get();
// Use:
$response = SqlAgent::run('Show me users who signed up in Q1 2024 with their lifetime value');
$chartData = collect($response->results)->pluck('lifetime_value')->toArray();
// With schema context (auto-injected)
$response = SqlAgent::run('Find customers from California with orders over $1000');
// With explicit context
$response = SqlAgent::run('Recent high-value transactions')
->withContext(['timeframe' => 'last_30_days', 'threshold' => 500]);
// In a Blade view:
@sqlAgentChat(['initial_prompt' => 'Analyze our sales trends'])
resources/views/vendor/sql-agent/chat.blade.phpresources/css/sql-agent.css// Add custom business rules
SqlAgent::addKnowledge([
'rule' => 'A "premium" customer has spent > $1000 in their lifetime',
'sql' => 'SELECT * FROM customers WHERE lifetime_value > 1000'
]);
// Clear stale learnings (e.g., after schema changes)
SqlAgent::forgetLearnings();
$queries = [
'Top products by revenue',
'Monthly active users trend',
'Unpaid invoices older than 60 days'
];
$results = SqlAgent::batch($queries);
foreach ($results as $result) {
// Process each response
}
jsonb columns for complex filtering:
SqlAgent::run('Find users with metadata containing "premium"')
->withHint('Use jsonb_path_ops for metadata search');
SqlAgent::run('Optimize this query for large tables')
->withHint('Add FORCE INDEX on orders(customer_id)');
// app/Services/SqlAgentService.php
class SqlAgentService {
public function getCustomerInsights(string $segment) {
$response = SqlAgent::run("Insights for {$segment} customers")
->withContext(['segment' => $segment]);
return $this->formatResponse($response);
}
}
// Test with mocked LLM responses
$mock = Mockery::mock(SqlAgent::class);
$mock->shouldReceive('run')
->with('test query')
->andReturn((object)[
'sql' => 'SELECT * FROM test',
'results' => [['id' => 1]]
]);
Schema Drift:
php artisan sql-agent:refresh-knowledge or manually update knowledge_base table.LLM Token Limits:
SQL_AGENT_CHUNK_SIZE=500 in config.->withHint('Use minimal columns').Permission Errors:
SQL_AGENT_SAFE_MODE=true to auto-sanitize queries or grant explicit permissions to the agent’s DB user.Circular Learning:
learnings table or set SQL_AGENT_MAX_LEARNING_ITERATIONS=3.SQL_AGENT_DEBUG=true
$response = SqlAgent::run('...')->debug();
// Inspect $response->llmDebug for prompt/response pairs
| Error | Solution |
|---|---|
LLMProviderNotFound |
Verify SQL_AGENT_LLM_PROVIDER matches a supported adapter. |
TableNotFound |
Check SQL_AGENT_DATABASE_CONNECTION or manually add table metadata. |
QueryTooComplex |
Break into sub-queries or simplify the prompt. |
RateLimitExceeded |
Implement retry logic with SQL_AGENT_RETRY_DELAY=5. |
// Register a new provider (e.g., app/Providers/SqlAgentServiceProvider.php)
SqlAgent::extend('custom', function () {
return new CustomLLMAdapter(config('sql-agent.custom_llm'));
});
// Add a processor to modify SQL before execution
SqlAgent::addProcessor(function ($query, $prompt) {
if (str_contains($prompt, 'export')) {
$query->with('FOR EXPORT');
}
return $query;
});
cp vendor/knobik/sql-agent/resources/views/vendor/sql-agent/* resources/views/vendor/sql-agent/
// In a service provider
SqlAgent::plugin('data-export', function () {
return new DataExportPlugin();
});
SQL_AGENT_CACHE_ENABLED=true
SQL_AGENT_CACHE_TTL=3600
batch() for independent queries:
$results = SqlAgent::batch([
'Query 1',
'Query 2'
], parallel: true);
How can I help you explore Laravel packages today?