-
Notifications
You must be signed in to change notification settings - Fork 119
feat: Add sql-query-explainer kit #150
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
02cf916
3d9f1be
99ad48a
0920b79
e540e97
08c3b17
bcc80b5
185dbfe
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,5 @@ | ||
| .env | ||
| .env.local | ||
| node_modules/ | ||
| *.log | ||
| .DS_Store |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,59 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # SQL Query Explainer | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ## About This Flow | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| This workflow accepts any SQL query and returns a **structured JSON explanation** — no database connection required. Useful for developers, data engineers, and analysts who need to quickly understand unfamiliar queries, document SQL code, or surface performance concerns before a query reaches production. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| This flow includes **3 nodes**: graphqlNode → LLMNode → graphqlResponseNode. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ## What It Returns | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| The API response contains an `explanation` field with a JSON object: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ```json | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "summary": "Plain-English description of what the query does.", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "dialect_hint": "PostgreSQL", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "clauses": [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { "clause": "SELECT", "explanation": "Retrieves user ID, name, and order count." } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "performance_concerns": ["LEFT JOIN on large table without index on user_id."], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "optimisation_suggestions": ["Add index on orders.user_id."], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "example_output_description": "Up to 20 rows with user ID, name, order count sorted descending." | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ## Example Input | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ```json | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "query": "SELECT u.id, u.name, COUNT(o.id) AS order_count FROM users u LEFT JOIN orders o ON u.id = o.user_id WHERE u.created_at >= '2024-01-01' GROUP BY u.id, u.name HAVING COUNT(o.id) > 5 ORDER BY order_count DESC LIMIT 20;" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ## Use Cases | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - **Code Review** — Auto-annotate SQL changes with plain-English descriptions and performance flags. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - **Developer Onboarding** — Help new engineers understand existing queries without DBA review. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - **SQL Education** — Build learning tools that explain queries clause by clause. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - **Data Documentation** — Generate consistent documentation for complex analytical queries. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - **Pre-Production Checks** — Surface SQL anti-patterns before queries run. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ## Prerequisites | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - A Lamatic.ai account ([lamatic.ai](https://lamatic.ai)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - An LLM provider connected in your Lamatic workspace | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ## Usage | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 1. Import this template into your Lamatic workspace | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 2. Connect your LLM provider credentials | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 3. Deploy the flow | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 4. Send a POST request with a `query` field containing your SQL | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+42
to
+52
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 requirement: add an environment-variables section. The README currently covers setup and usage, but it never states whether the kit needs any env vars or explicitly that none are required. That leaves the kit documentation incomplete for contributors. As per coding guidelines, Suggested addition ## Prerequisites
- A Lamatic.ai account
- An LLM provider connected in your Lamatic workspace
+
+## Environment Variables
+
+- None required. This kit uses the connected LLM provider configured in Lamatic.📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ## Tags | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Developer Tools, Generative, Analytics, SQL | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| *Author: Saad Mohammad | saadmd723@gmail.com* | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| # SQL Query Explainer | ||
|
|
||
| ## Overview | ||
| This AgentKit template solves the problem of quickly understanding any SQL query — no matter its complexity — without having to run it or ask a colleague. It is implemented as a **single-flow** API-invoked pipeline: an API request triggers an LLM analysis step, and the result is returned as a structured JSON object. The primary caller is a developer tool, internal portal, code review system, or any automation that needs an on-demand "explain this SQL" capability. | ||
|
|
||
| --- | ||
|
|
||
| ## Purpose | ||
| The goal of this agent is to reduce the time and cognitive overhead required to understand an unfamiliar SQL query. After it runs, the caller receives a compact structured breakdown that captures what the query does, how each clause contributes, what performance risks exist, and how to improve it — without needing to execute the query or consult a DBA. | ||
|
|
||
| Operationally, the agent accepts a raw SQL query string (any dialect), passes it to an LLM with a strict JSON-output system prompt, and returns a structured explanation object. This makes it suitable for developer portals, code review automations, SQL learning tools, data engineering onboarding flows, and any system that needs consistent, structured SQL documentation at scale. | ||
|
|
||
| Because this kit is a template with a single flow, all behaviour is concentrated in one pipeline. If you extend it (e.g., adding dialect detection, multi-query batching, or storage of past explanations), the existing flow remains the canonical entrypoint for "SQL query → explanation". | ||
|
|
||
| ## Flows | ||
|
|
||
| ### SQL Query Explainer | ||
|
|
||
| - Trigger | ||
| - Invocation: API call via a GraphQL-triggered request node (`graphqlNode`) exposed by the AgentKit runtime. | ||
| - Expected input shape: | ||
| - A payload containing the `query` field. | ||
| - The flow is designed around "SQL in, explanation out"; the GraphQL field name is `query` (string — the raw SQL query to analyse). | ||
| - Input notes: Any valid SQL query string is accepted. Multi-statement queries, CTEs, subqueries, window functions, and dialect-specific syntax are all supported. The LLM will do its best to infer the dialect. | ||
|
|
||
| - What it does | ||
| 1. `API Request` (`graphqlNode`) | ||
| - Accepts the incoming GraphQL/API request from the caller. | ||
| - Validates and surfaces the `query` field to downstream nodes as `{{triggerNode_1.output.query}}`. | ||
| 2. `Explain Query` (`LLMNode`) | ||
| - Runs an LLM analysis with a structured system prompt that instructs the model to return valid JSON only. | ||
| - System prompt (`sql-query-explainer_explain-query_system.md`) defines the output schema and rules. | ||
| - User prompt (`sql-query-explainer_explain-query_user.md`) injects the raw query as `{{triggerNode_1.output.query}}`. | ||
| - Produces `generatedResponse` — a JSON string containing the full explanation object. | ||
| 3. `API Response` (`graphqlResponseNode`) | ||
| - Formats and returns the explanation to the caller as the `explanation` field in the API response. | ||
|
|
||
| - When to use this flow | ||
| - Use when a developer needs to quickly understand an unfamiliar SQL query. | ||
| - Use in a code review pipeline to auto-generate SQL change descriptions. | ||
| - Use in a developer onboarding tool to help new engineers understand existing queries. | ||
| - Use in a data engineering portal to document complex analytical queries. | ||
| - Use in a SQL learning application to explain queries step by step. | ||
|
|
||
| - When not to use this flow | ||
| - Do not use when you need to execute the query and retrieve actual data. | ||
| - Do not use for extremely large queries (200+ lines) without chunking — LLM context windows may be strained. | ||
| - Do not use as a replacement for database-native EXPLAIN / EXPLAIN ANALYZE plans when diagnosing real execution bottlenecks. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| // Flow: sql-query-explainer | ||
| // Accepts a raw SQL query and returns a structured JSON explanation. | ||
|
|
||
| export const meta = { | ||
| "name": "SQL Query Explainer", | ||
| "description": "Accepts any SQL query and returns a structured JSON explanation: plain-English summary, clause breakdown, performance concerns, and optimisation suggestions.", | ||
| "tags": ["Developer Tools", "Generative", "Analytics"], | ||
| "testInput": { | ||
| "query": "SELECT u.id, u.name, COUNT(o.id) AS order_count FROM users u LEFT JOIN orders o ON u.id = o.user_id WHERE u.created_at >= '2024-01-01' GROUP BY u.id, u.name HAVING COUNT(o.id) > 5 ORDER BY order_count DESC LIMIT 20;" | ||
| }, | ||
| "githubUrl": "", | ||
| "documentationUrl": "", | ||
| "deployUrl": "https://studio.lamatic.ai/template/sql-query-explainer", | ||
| }; | ||
|
|
||
| export const nodes = [ | ||
| { | ||
| "id": "triggerNode_1", | ||
| "type": "graphqlNode", | ||
| "label": "API Request", | ||
| "data": { | ||
| "description": "Accepts the incoming API request. Expects a query string field containing the SQL to explain.", | ||
| "inputs": { | ||
| "inputSchema": { | ||
| "type": "object", | ||
| "properties": { | ||
| "query": { "type": "string", "description": "The raw SQL query string to explain." } | ||
| }, | ||
| "required": ["query"] | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| { | ||
| "id": "LLMNode_1", | ||
| "type": "LLMNode", | ||
| "label": "Explain Query", | ||
| "data": { | ||
| "description": "Sends the SQL query to the LLM with a structured system prompt. Returns JSON with summary, clauses, performance concerns, and optimisation suggestions.", | ||
| "inputs": { | ||
| "systemPrompt": "@prompts/sql-query-explainer_explain-query_system.md", | ||
| "userPrompt": "@prompts/sql-query-explainer_explain-query_user.md", | ||
| "modelConfig": "@model-configs/sql-query-explainer_explain-query.ts" | ||
| }, | ||
| "outputs": { "generatedResponse": "string" } | ||
| } | ||
| }, | ||
| { | ||
| "id": "responseNode_1", | ||
| "type": "graphqlResponseNode", | ||
| "label": "API Response", | ||
| "data": { | ||
| "description": "Returns the structured JSON explanation to the API caller.", | ||
| "inputs": { | ||
| "response": { "explanation": "{{LLMNode_1.output.generatedResponse}}" } | ||
| }, | ||
| "responseMode": "realtime" | ||
| } | ||
| } | ||
| ]; | ||
|
|
||
| export const edges = [ | ||
| { "id": "edge_trigger_to_llm", "source": "triggerNode_1", "target": "LLMNode_1" }, | ||
| { "id": "edge_llm_to_response", "source": "LLMNode_1", "target": "responseNode_1" } | ||
| ]; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| export default { | ||
| name: "SQL Query Explainer", | ||
| description: "This workflow accepts any SQL query (SELECT, INSERT, UPDATE, DELETE, CTEs, window functions, etc.) and returns a plain-English explanation, a clause-by-clause breakdown, a list of potential performance issues, and concrete optimisation suggestions. It is useful for developers learning SQL, onboarding engineers reading unfamiliar queries, and anyone who needs to quickly understand what a query does without running it.", | ||
| version: '1.0.0', | ||
| type: 'template' as const, | ||
| author: {"name":"Saad Mohammad","email":"saadmd723@gmail.com"}, | ||
| tags: ["developer-tools","sql","generative","analytics"], | ||
| steps: [ | ||
| { id: "sql-query-explainer", type: 'mandatory' as const } | ||
| ], | ||
| links: { | ||
| "deploy": "https://studio.lamatic.ai/template/sql-query-explainer", | ||
| "github": "https://github.com/Lamatic/AgentKit/tree/main/kits/sql-query-explainer" | ||
| }, | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| // Model config: Explain Query (LLMNode) | ||
| // Flow: sql-query-explainer | ||
|
|
||
| export default { | ||
| "generativeModelName": "@model-configs/sql-query-explainer_explain-query.ts", | ||
| "memories": "@model-configs/sql-query-explainer_explain-query.ts", | ||
| "messages": "@model-configs/sql-query-explainer_explain-query.ts" | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| You are an expert SQL analyst and database engineer with deep knowledge of SQL dialects including PostgreSQL, MySQL, SQLite, BigQuery, Snowflake, and SQL Server. | ||
|
|
||
| Your job is to analyse a SQL query provided by the user and return a structured, developer-friendly explanation. Your response must always follow this exact JSON structure: | ||
|
|
||
| ```json | ||
| { | ||
| "summary": "One or two sentence plain-English description of what the query does.", | ||
| "dialect_hint": "The SQL dialect this query appears to target, or 'Standard SQL' if dialect-agnostic.", | ||
| "clauses": [ | ||
| { | ||
| "clause": "Name of the SQL clause (e.g. SELECT, FROM, WHERE, GROUP BY, ORDER BY, WITH, JOIN, HAVING, LIMIT)", | ||
| "explanation": "Plain-English explanation of what this specific clause does in context." | ||
| } | ||
| ], | ||
| "performance_concerns": [ | ||
| "Description of a potential performance issue, or an empty array if none detected." | ||
| ], | ||
| "optimisation_suggestions": [ | ||
| "A concrete, actionable optimisation tip, or an empty array if none applicable." | ||
| ], | ||
| "example_output_description": "A brief description of what the result set would look like (columns, rows, shape) if the query ran successfully." | ||
| } | ||
| ``` | ||
|
|
||
| Rules: | ||
| - Always respond with valid JSON only. Do not include markdown code fences or any text outside the JSON object. | ||
| - Be precise and concise in each field. | ||
| - If the query has syntax errors, still do your best to explain the apparent intent and note the error in `performance_concerns`. | ||
| - Do not execute or simulate the query. Only analyse its structure and logic. | ||
| - Tailor explanations for a developer audience — avoid overly simplistic language but also avoid unnecessary jargon. |
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,3 @@ | ||||||||||||
| SQL Query: | ||||||||||||
|
|
||||||||||||
| {{triggerNode_1.output.query}} | ||||||||||||
|
Comment on lines
+1
to
+3
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 risk: delimit the SQL before interpolation. Raw interpolation here mixes user data with prompt instructions, which makes prompt-injection and instruction-smuggling easier. Wrap the query in an explicit fenced block or another delimiter so the model treats it as data. Suggested fix SQL Query:
-{{triggerNode_1.output.query}}
+```sql
+{{triggerNode_1.output.query}}
+```📝 Committable suggestion
Suggested change
🧰 Tools🪛 markdownlint-cli2 (0.22.1)[warning] 1-1: First line in a file should be a top-level heading (MD041, first-line-heading, first-line-h1) 🤖 Prompt for AI Agents |
||||||||||||
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 clarity: describe the response as JSON text, not a parsed object.
The flow forwards
generatedResponsedirectly intoexplanation, so the API emits JSON text unless another step parses it. Update the wording/example so consumers know they need to parse the field.Suggested wording tweak
📝 Committable suggestion
🤖 Prompt for AI Agents