Natural-language SQL assistant built with LangChain. It exposes:
- A web UI (
/) for non-technical users - One API endpoint (
POST /api/ask) for integrations - A CLI for quick local testing
The architecture is intentionally decoupled so model provider and database/provider logic can be swapped independently.
- Natura Language -> SQL generation against your live schema
- Read-focused SQL guardrails
- SQL query checking before execution
- Results + human summary in one response
- Provider abstraction (
openai,huggingface) - Database abstraction (
SQLDatabaseToolkitwrapped behindDatabaseProvider)
- Python 3.13+
- FastAPI + Uvicorn
- LangChain + LangChain Community + LangChain OpenAI
- SQLAlchemy (+ psycopg for Postgres)
git clone https://github.com/MurungaOwen/sql_agent.git
cd sql_agent
uv synccp .env.example .envEdit .env:
- Set
DATABASE_URL - Pick provider (
MODEL_PROVIDER=openaiorhuggingface) - Set matching API key
uv run uvicorn app:app --reloadOpen http://127.0.0.1:8000.
Example:
- "Who are the top 10 customers by total transaction amount?"
POST /api/ask
{
"question": "Who are the top transactionists this month?"
}{
"question": "Who are the top transactionists this month?",
"sql": "SELECT ... LIMIT 100;",
"rows": "[(...)]",
"summary": "Top customers by amount are ..."
}curl -X POST http://127.0.0.1:8000/api/ask \
-H "Content-Type: application/json" \
-d '{"question":"Show daily transaction count for the last 30 days"}'uv run python main.py "top 5 customers by revenue"
uv run python main.py "monthly sales for 2025" --json| Variable | Required | Default | Description |
|---|---|---|---|
DATABASE_URL |
Yes | - | SQLAlchemy database URL |
MODEL_PROVIDER |
No | openai |
openai or huggingface |
MODEL_NAME |
No | gpt-4o-mini |
Model ID for selected provider |
MODEL_TEMPERATURE |
No | 0 |
Generation temperature |
OPENAI_API_KEY |
If OpenAI | - | OpenAI key |
HUGGINGFACE_API_KEY |
If HF | - | Hugging Face token |
HUGGINGFACE_BASE_URL |
No | https://router.huggingface.co/v1 |
HF OpenAI-compatible endpoint |
MAX_ROWS |
No | 100 |
Auto-limit appended if missing |
TABLE_ALLOWLIST |
No | empty | Comma-separated allowed tables |
MODEL_PROVIDER=openai
MODEL_NAME=gpt-4o-mini
OPENAI_API_KEY=your_keyMODEL_PROVIDER=huggingface
MODEL_NAME=meta-llama/Llama-3.3-70B-Instruct
HUGGINGFACE_API_KEY=your_hf_token
HUGGINGFACE_BASE_URL=https://router.huggingface.co/v1Important: If MODEL_PROVIDER=huggingface, do not use gpt-4o-mini as MODEL_NAME.
- SQLite:
sqlite:///example.db - Postgres:
postgresql+psycopg://postgres:postgres@localhost:5432/bank - MySQL:
mysql+pymysql://user:pass@localhost:3306/dbname
app.py # FastAPI app + API + UI serving
main.py # CLI entrypoint
sql_agent/
config.py # env parsing (.env auto-load)
interfaces.py # LLMProvider / DatabaseProvider contracts
orchestrator.py # core orchestration flow
guardrails.py # read-only + table-scope + limit enforcement
factory.py # provider wiring from settings
adapters/
llm.py # OpenAI and HuggingFace providers
database.py # SQLDatabaseToolkit adapter
web/
index.html
assets/
styles.css
app.js
- Load schema context from DB tools
- Generate SQL from question
- Enforce guardrails
- Check SQL with toolkit checker
- Execute SQL
- Summarize result
If guardrails fail, one repair attempt is performed.
- Only
SELECT/WITHqueries allowed - Blocks write/DDL keywords (
INSERT,UPDATE,DELETE, etc.) - Optional table allowlist enforcement
- Applies
LIMIT MAX_ROWSif query has no limit
- Ensure
.envexists in project root - Ensure it contains
DATABASE_URL=... - Ensure you run commands from repository root
- Use
openaiorhuggingface
- Set
HUGGINGFACE_API_KEY - Use an HF model id (for example
meta-llama/Llama-3.3-70B-Instruct) - Keep
HUGGINGFACE_BASE_URL=https://router.huggingface.co/v1unless intentionally overriding
- Verify host/port/db/user/password in
DATABASE_URL - Ensure Postgres is running and reachable
- Confirm credentials and DB permissions
- Orchestrator logic is provider-agnostic and database-agnostic by design.
- Add new providers by implementing
LLMProviderand registering insql_agent/factory.py. - Add new DB strategies by implementing
DatabaseProviderand registering insql_agent/factory.py.
curl http://127.0.0.1:8000/healthExpected:
{"status":"ok"}
