-
Notifications
You must be signed in to change notification settings - Fork 132
feat: Add SQL Query Generator AgentKit #159
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| # SQL Query Generator | ||
|
|
||
| An AI-powered agent that converts natural language questions into optimized SQL queries. Paste your database schema, ask a question in plain English, and get production-ready SQL with explanations, confidence scores, and assumption tracking. | ||
|
|
||
| ## What It Does | ||
|
|
||
| - Takes a database schema (CREATE TABLE statements) and a plain English question | ||
| - Generates an optimized, read-only SQL SELECT query | ||
| - Returns a structured response with the query, explanation, tables used, assumptions, and confidence level | ||
| - Only generates SELECT statements — never INSERT, UPDATE, DELETE, DROP, or ALTER | ||
| - Produces standard SQL compatible with PostgreSQL, MySQL, and SQLite | ||
|
|
||
| ## Problem It Solves | ||
|
|
||
| Writing SQL queries from scratch takes time, especially for complex joins, aggregations, and subqueries. This tool lets developers, analysts, and data teams quickly get a working query by describing what they need in plain English. It's also useful for learning SQL — the explanation and assumptions help users understand the query logic. | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| - [Node.js](https://nodejs.org) 18+ | ||
| - [Lamatic.ai](https://lamatic.ai) account with a deployed SQL query generation flow | ||
| - A configured LLM provider (e.g., Anthropic, OpenAI, Google) in Lamatic Studio | ||
|
|
||
| ## Setup | ||
|
|
||
| ### 1. Clone and navigate | ||
|
|
||
| ```bash | ||
| git clone https://github.com/Lamatic/AgentKit.git | ||
| cd AgentKit/kits/sql-query-generator/apps | ||
| ``` | ||
|
|
||
| ### 2. Install dependencies | ||
|
|
||
| ```bash | ||
| npm install | ||
| ``` | ||
|
|
||
| ### 3. Configure environment | ||
|
|
||
| ```bash | ||
| cp .env.example .env | ||
| ``` | ||
|
|
||
| Fill in your values: | ||
|
|
||
| ``` | ||
| SQL_QUERY_GENERATOR_FLOW_ID = "your-flow-id" | ||
| LAMATIC_API_URL = "https://your-org.lamatic.dev" | ||
| LAMATIC_PROJECT_ID = "your-project-id" | ||
| LAMATIC_API_KEY = "sk-your-api-key" | ||
| ``` | ||
|
Comment on lines
+46
to
+51
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mission briefing: code fence needs a language identifier. The environment variable example block (lines 46-51) is missing a language specifier. Intelligence analysts recommend adding 📋 Proposed fix for code fence language-```
+```env
SQL_QUERY_GENERATOR_FLOW_ID = "your-flow-id"
LAMATIC_API_URL = "https://your-org.lamatic.dev"
LAMATIC_PROJECT_ID = "your-project-id"
LAMATIC_API_KEY = "sk-your-api-key"🧰 Tools🪛 markdownlint-cli2 (0.22.1)[warning] 46-46: Fenced code blocks should have a language specified (MD040, fenced-code-language) 🤖 Prompt for AI Agents |
||
|
|
||
| ### 4. Run locally | ||
|
|
||
| ```bash | ||
| npm run dev | ||
| ``` | ||
|
|
||
| Open [http://localhost:3000](http://localhost:3000) in your browser. | ||
|
|
||
| ## Usage | ||
|
|
||
| 1. Paste your database schema (CREATE TABLE statements) in the schema field | ||
| 2. Type your question in plain English | ||
| 3. Click "Generate SQL" | ||
| 4. View the generated query, copy it, and read the explanation | ||
|
|
||
| You can also click "Load sample" to try it with example data. | ||
|
|
||
| ## Deploy to Vercel | ||
|
|
||
| 1. Push to your fork | ||
| 2. Import the repo on [Vercel](https://vercel.com) | ||
| 3. Set root directory to `kits/sql-query-generator/apps` | ||
| 4. Add environment variables | ||
| 5. Deploy | ||
|
|
||
| ## Flow Architecture | ||
|
|
||
| ``` | ||
| API Request → Generate Text (LLM) → API Response | ||
| ``` | ||
|
|
||
| The flow uses a single LLM node with a carefully crafted system prompt that: | ||
| - Enforces read-only query generation | ||
| - Requires structured JSON output | ||
| - Handles ambiguous questions gracefully | ||
| - Tracks assumptions and confidence | ||
|
|
||
| ## Environment Variables | ||
|
|
||
| | Variable | Description | | ||
| |---|---| | ||
| | `SQL_QUERY_GENERATOR_FLOW_ID` | The deployed Lamatic flow ID | | ||
| | `LAMATIC_API_URL` | Your Lamatic API endpoint URL | | ||
| | `LAMATIC_PROJECT_ID` | Your Lamatic project ID | | ||
| | `LAMATIC_API_KEY` | Your Lamatic secret API key | | ||
|
|
||
| ## Author | ||
|
|
||
| **Aakriti** — [pandey.aakriti1@gmail.com](mailto:pandey.aakriti1@gmail.com) | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,19 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # SQL Query Generator Agent | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ## Overview | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| This agent converts natural language questions into optimized, read-only SQL queries. Users provide their database schema (as CREATE TABLE statements) and ask questions in plain English. The agent returns a well-structured SQL SELECT query along with an explanation, the tables used, any assumptions made, and a confidence score. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+3
to
+4
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial | 💤 Low value Agent, your documentation formatting needs a tactical adjustment. The heading "## Overview" (line 3) should have a blank line after it according to markdown best practices (MD022). This improves readability across different renderers. Note: If 📄 Proposed fix for heading spacing ## Overview
+
This agent converts natural language questions into optimized, read-only SQL queries. Users provide their database schema (as CREATE TABLE statements) and ask questions in plain English. The agent returns a well-structured SQL SELECT query along with an explanation, the tables used, any assumptions made, and a confidence score.Based on learnings: "In 📝 Committable suggestion
Suggested change
🧰 Tools🪛 markdownlint-cli2 (0.22.1)[warning] 3-3: Headings should be surrounded by blank lines (MD022, blanks-around-headings) 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ## Architecture | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| The agent uses a single Lamatic Flow with three nodes: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 1. **API Request** — receives the database schema and question via GraphQL | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 2. **Generate Text (LLM)** — processes the inputs using a system prompt tuned for SQL generation | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 3. **API Response** — returns the generated SQL as a JSON string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ## Key Design Decisions | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - **Read-only queries only** — the agent is explicitly instructed to never generate INSERT, UPDATE, DELETE, DROP, or ALTER statements, making it safe for production use | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - **Structured JSON output** — the response includes sql, explanation, tables_used, assumptions, and confidence fields for easy frontend parsing | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - **Cross-database compatibility** — queries target standard SQL that works across PostgreSQL, MySQL, and SQLite | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - **Explicit JOINs** — the agent prefers explicit JOIN syntax over implicit joins for readability | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ## Flows | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 1. `sql-query-generator` — the single flow that handles schema parsing, SQL generation, and response formatting | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+6
to
+19
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial | 💤 Low value Field report: multiple heading spacing issues detected. Agent, your document has four headings that need blank lines after them (lines 6, 12, 18) for proper markdown formatting (MD022). This is a consistent pattern throughout the file. 📄 Proposed fix for all heading spacing issues ## Architecture
+
The agent uses a single Lamatic Flow with three nodes:
1. **API Request** — receives the database schema and question via GraphQL
2. **Generate Text (LLM)** — processes the inputs using a system prompt tuned for SQL generation
3. **API Response** — returns the generated SQL as a JSON string
## Key Design Decisions
+
- **Read-only queries only** — the agent is explicitly instructed to never generate INSERT, UPDATE, DELETE, DROP, or ALTER statements, making it safe for production use
- **Structured JSON output** — the response includes sql, explanation, tables_used, assumptions, and confidence fields for easy frontend parsing
- **Cross-database compatibility** — queries target standard SQL that works across PostgreSQL, MySQL, and SQLite
- **Explicit JOINs** — the agent prefers explicit JOIN syntax over implicit joins for readability
## Flows
+
1. `sql-query-generator` — the single flow that handles schema parsing, SQL generation, and response formattingBased on learnings: "In 📝 Committable suggestion
Suggested change
🧰 Tools🪛 markdownlint-cli2 (0.22.1)[warning] 6-6: Headings should be surrounded by blank lines (MD022, blanks-around-headings) [warning] 12-12: Headings should be surrounded by blank lines (MD022, blanks-around-headings) [warning] 18-18: Headings should be surrounded by blank lines (MD022, blanks-around-headings) 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,4 @@ | ||||||||||||||||||
| SQL_QUERY_GENERATOR_FLOW_ID = "YOUR_FLOW_ID" | ||||||||||||||||||
| LAMATIC_API_URL = "YOUR_API_ENDPOINT" | ||||||||||||||||||
| LAMATIC_PROJECT_ID = "YOUR_PROJECT_ID" | ||||||||||||||||||
| LAMATIC_API_KEY = "YOUR_API_KEY" | ||||||||||||||||||
|
Comment on lines
+1
to
+4
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agent, tighten up your .env format—remove those extraneous spaces. Standard 🔧 Proposed fix to align with standard format-SQL_QUERY_GENERATOR_FLOW_ID = "YOUR_FLOW_ID"
-LAMATIC_API_URL = "YOUR_API_ENDPOINT"
-LAMATIC_PROJECT_ID = "YOUR_PROJECT_ID"
-LAMATIC_API_KEY = "YOUR_API_KEY"
+SQL_QUERY_GENERATOR_FLOW_ID="YOUR_FLOW_ID"
+LAMATIC_API_URL="YOUR_API_ENDPOINT"
+LAMATIC_PROJECT_ID="YOUR_PROJECT_ID"
+LAMATIC_API_KEY="YOUR_API_KEY"📝 Committable suggestion
Suggested change
🧰 Tools🪛 dotenv-linter (4.0.0)[warning] 1-1: [SpaceCharacter] The line has spaces around equal sign (SpaceCharacter) [warning] 2-2: [SpaceCharacter] The line has spaces around equal sign (SpaceCharacter) [warning] 2-2: [UnorderedKey] The LAMATIC_API_URL key should go before the SQL_QUERY_GENERATOR_FLOW_ID key (UnorderedKey) [warning] 3-3: [SpaceCharacter] The line has spaces around equal sign (SpaceCharacter) [warning] 3-3: [UnorderedKey] The LAMATIC_PROJECT_ID key should go before the SQL_QUERY_GENERATOR_FLOW_ID key (UnorderedKey) [warning] 4-4: [SpaceCharacter] The line has spaces around equal sign (SpaceCharacter) [warning] 4-4: [UnorderedKey] The LAMATIC_API_KEY key should go before the LAMATIC_API_URL key (UnorderedKey) 🤖 Prompt for AI Agents |
||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| node_modules/ | ||
| .next/ | ||
| .env | ||
| .env.local | ||
| *.tsbuildinfo | ||
| next-env.d.ts |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| "use server"; | ||
|
|
||
| import lamaticClient from "@/lib/lamatic-client"; | ||
|
|
||
| interface SQLGeneratorResult { | ||
| sql: string | null; | ||
| explanation: string; | ||
| tables_used: string[]; | ||
| assumptions: string | null; | ||
| confidence: "high" | "medium" | "low"; | ||
| } | ||
|
|
||
| interface GenerateQueryResponse { | ||
| success: boolean; | ||
| data?: SQLGeneratorResult; | ||
| error?: string; | ||
| } | ||
|
|
||
| function parseResponse(raw: string): SQLGeneratorResult { | ||
| let cleaned = raw.trim(); | ||
| if (cleaned.startsWith("```json")) { | ||
| cleaned = cleaned.slice(7); | ||
| } else if (cleaned.startsWith("```")) { | ||
| cleaned = cleaned.slice(3); | ||
| } | ||
| if (cleaned.endsWith("```")) { | ||
| cleaned = cleaned.slice(0, -3); | ||
| } | ||
| cleaned = cleaned.trim(); | ||
| return JSON.parse(cleaned); | ||
| } | ||
|
Comment on lines
+19
to
+31
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win The package is trusted but never inspected, Agent. 🛡️ Suggested defensive validation function parseResponse(raw: string): SQLGeneratorResult {
let cleaned = raw.trim();
if (cleaned.startsWith("```json")) {
cleaned = cleaned.slice(7);
} else if (cleaned.startsWith("```")) {
cleaned = cleaned.slice(3);
}
if (cleaned.endsWith("```")) {
cleaned = cleaned.slice(0, -3);
}
cleaned = cleaned.trim();
- return JSON.parse(cleaned);
+ const parsed = JSON.parse(cleaned);
+ const validConfidence = ["high", "medium", "low"];
+ return {
+ sql: typeof parsed.sql === "string" ? parsed.sql : null,
+ explanation: typeof parsed.explanation === "string" ? parsed.explanation : "",
+ tables_used: Array.isArray(parsed.tables_used) ? parsed.tables_used : [],
+ assumptions: typeof parsed.assumptions === "string" ? parsed.assumptions : null,
+ confidence: validConfidence.includes(parsed.confidence) ? parsed.confidence : "low",
+ };
}🤖 Prompt for AI Agents |
||
|
|
||
| export async function generateQuery( | ||
| schema: string, | ||
| question: string | ||
| ): Promise<GenerateQueryResponse> { | ||
| try { | ||
| if (!schema.trim()) { | ||
| return { success: false, error: "Please provide a database schema." }; | ||
| } | ||
| if (!question.trim()) { | ||
| return { success: false, error: "Please provide a question." }; | ||
| } | ||
|
|
||
| const flowId = process.env.SQL_QUERY_GENERATOR_FLOW_ID; | ||
| if (!flowId) { | ||
| return { success: false, error: "Flow ID is not configured." }; | ||
| } | ||
|
|
||
| const response = await lamaticClient.executeFlow(flowId, { | ||
| schema: schema, | ||
| question: question, | ||
| }); | ||
|
|
||
| const result = (response as any)?.result?.result; | ||
|
|
||
| if (!result) { | ||
| return { success: false, error: "No response received from the agent." }; | ||
| } | ||
|
|
||
| const parsed = parseResponse(result); | ||
| return { success: true, data: parsed }; | ||
| } catch (err) { | ||
| console.error("SQL generation error:", err); | ||
| return { | ||
| success: false, | ||
| error: err instanceof Error ? err.message : "Something went wrong.", | ||
| }; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| @import "tailwindcss"; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| import type { Metadata } from "next"; | ||
| import "./globals.css"; | ||
|
|
||
| export const metadata: Metadata = { | ||
| title: "SQL Query Generator", | ||
| description: | ||
| "Convert natural language questions into optimized SQL queries using AI.", | ||
| }; | ||
|
|
||
| export default function RootLayout({ | ||
| children, | ||
| }: { | ||
| children: React.ReactNode; | ||
| }) { | ||
| return ( | ||
| <html lang="en"> | ||
| <body>{children}</body> | ||
| </html> | ||
| ); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mission briefing, agent: use
.env.localfor Next.js development secrets.Your deployment package correctly references
.env.exampleas the template, but the local copy command should target.env.localinstead of.env. Next.js prioritizes.env.localfor developer-specific secrets and most kits'.gitignorefiles exclude it by default (along with.env). This prevents accidental commits of live credentials.🔒 Recommended fix for secure local development
As per coding guidelines: "The
.gitignorefile must exclude.envand.env.localto prevent accidental secret commits."📝 Committable suggestion
🤖 Prompt for AI Agents