Skip to main content

sqlmind

LangGraph-native NL→SQL agent library — drop your database query pipeline directly into an existing agent graph as a composable node.

Python 3.10+ License: MIT


Why sqlmind?

Most NL→SQL tools are standalone apps or ChatGPT wrappers. sqlmind is a library — designed to be dropped into your existing LangGraph agent as a composable node. No hosting, no vendor lock-in, no new service to manage.

Feature sqlmind Most alternatives
LangGraph-native nodes ✅ First-class ❌ Standalone only
Pluggable guardrails ✅ Full interface ❌ Fixed policies
Semantic glossary ✅ YAML/dict/custom ❌ None
Canonical metric defs ✅ Injected into LLM ❌ LLM guesses
Self-correction loop ✅ Up to N retries ❌ One-shot
Read-only by default ✅ Session-level ⚠️ Convention only
Any LLM ✅ Protocol + adapters ❌ OpenAI only

Installation

# Core + PostgreSQL + LangGraph/LangChain
pip install sqlmind[langgraph,postgres]

# Add OpenAI or Anthropic direct adapters
pip install sqlmind[openai]
pip install sqlmind[anthropic]

# Everything
pip install sqlmind[all]

Quick Start

Shape A — Single drop-in node

from sqlmind import SQLAgent, SQLAgentConfig
from sqlmind.core import PostgresConnection
from sqlmind.guardrails import ReadOnlyGuardrail, RowLimitGuardrail, BlockedColumnsGuardrail
from sqlmind.semantic import Glossary, MetricRegistry
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, END

# 1. Connect (read-only enforced at DB session level)
conn = PostgresConnection(url="postgresql://user:pass@host/mydb")

# 2. Semantic layer — eliminates LLM guessing about your business terms
glossary = Glossary.from_yaml("glossary.yaml")
metrics = MetricRegistry()
metrics.define("mrr", "Monthly Recurring Revenue", formula="SUM(amount) WHERE cycle='monthly'", unit="USD")

# 3. Guardrails — fail closed, explainable violations
guardrails = [
    ReadOnlyGuardrail(),                              # Block INSERT/UPDATE/DELETE/DROP
    RowLimitGuardrail(max_rows=500),                  # Inject LIMIT clause
    BlockedColumnsGuardrail(columns=["ssn", "password_hash"]),  # PII protection
]

# 4. Build agent — any LLM works
agent = SQLAgent(
    connection=conn,
    llm=ChatOpenAI(model="gpt-4o"),    # or OpenAIAdapter, AnthropicAdapter, or any custom LLM
    guardrails=guardrails,
    glossary=glossary,
    metrics=metrics,
)

# 5. Drop into your LangGraph graph — ONE LINE
graph = StateGraph(dict)
graph.add_node("db", agent.as_node())
graph.set_entry_point("db")
graph.add_edge("db", END)
app = graph.compile()

result = app.invoke({"user_query": "How many active users signed up last month?"})
# → {"success": True, "sql_result": [...], "row_count": 1, "sql_executed": "SELECT ...", ...}

Shape B — Exploded sub-graph (power users)

Individual nodes for full control flow — route to human-in-the-loop on low confidence, add custom steps between pipeline stages.

from sqlmind.integrations import clarify_node, generate_node, validate_node, execute_node

graph = StateGraph(MyState)
graph.add_node("clarify",  clarify_node(agent))
graph.add_node("generate", generate_node(agent))
graph.add_node("validate", validate_node(agent))
graph.add_node("execute",  execute_node(agent))

# Your own routing
def route_after_clarify(state):
    return "human_in_loop" if state.get("needs_clarification") else "generate"

graph.add_conditional_edges("clarify", route_after_clarify, {...})

Use outside LangGraph

result = agent.query("Show me top 10 customers by revenue this quarter")
print(result["sql"])         # The executed SQL
print(result["rows"])        # Query result as list of dicts
print(result["explanation"]) # Human-readable explanation

Custom LLM Integration

Any LLM works. Three ways:

# Option 1: Any LangChain model (ChatOpenAI, ChatAnthropic, ChatOllama, etc.)
from langchain_openai import ChatOpenAI
agent = SQLAgent(connection=conn, llm=ChatOpenAI(model="gpt-4o"))

# Option 2: Direct OpenAI (no LangChain dep)
from sqlmind.llm import OpenAIAdapter
agent = SQLAgent(connection=conn, llm=OpenAIAdapter(api_key="sk-...", model="gpt-4o"))

# Option 3: Direct Anthropic
from sqlmind.llm import AnthropicAdapter
agent = SQLAgent(connection=conn, llm=AnthropicAdapter(model="claude-3-5-sonnet-20241022"))

# Option 4: Fully custom — implement 2 methods
class MyCustomLLM:
    def complete(self, messages, **kwargs):
        ...  # return LLMResponse(content="...")
    def complete_structured(self, messages, schema, **kwargs):
        ...  # return dict

agent = SQLAgent(connection=conn, llm=MyCustomLLM())

Custom Guardrails

from sqlmind.guardrails import Guardrail, GuardrailResult
import datetime

class NoDeleteOnWeekendsGuardrail(Guardrail):
    def check(self, query, context):
        is_weekend = datetime.date.today().weekday() >= 5
        has_delete = "DELETE" in query.sql.upper()
        if is_weekend and has_delete:
            return GuardrailResult(
                passed=False,
                guardrail_name=self.name,
                reason="DELETE queries are blocked on weekends per data policy.",
            )
        return GuardrailResult(passed=True, guardrail_name=self.name)

agent = SQLAgent(
    connection=conn,
    llm=llm,
    guardrails=[ReadOnlyGuardrail(), NoDeleteOnWeekendsGuardrail()],
)

Glossary YAML Format

# glossary.yaml
amt_cents:
  description: "Revenue in USD cents. Always divide by 100 before display."
  example: "SELECT SUM(amt_cents) / 100.0 AS revenue_usd FROM orders"
  tags: [finance, revenue]

status:
  description: "User status: 1=active, 2=trial, 3=churned, 4=suspended"
  tags: [user, lifecycle]

# Shorthand
mrr: "Monthly Recurring Revenue. See metric definitions for formula."

Configuration

from sqlmind import SQLAgentConfig

config = SQLAgentConfig(
    max_retries=3,                # Self-correction attempts on execution error
    confidence_threshold=0.65,    # Below this → trigger clarification step
    max_rows=1000,                # Hard row cap
    query_timeout_seconds=30,     # Wall-clock execution timeout
    memory_window=10,             # Multi-turn context turns kept
    input_state_key="user_query", # LangGraph state key for the question
    output_state_key="sql_result",# LangGraph state key for the result
    verbose=False,                # Debug logging
    llm_temperature=0.0,          # Deterministic generation
)

LangGraph State Contract

The sqlmind node reads and writes these keys on the shared LangGraph state:

Key Direction Type Description
user_query Read str The NL question
sql_result Write list[dict] Query result rows
sql_executed Write str Final SQL (after any guardrail rewrites)
row_count Write int Number of rows returned
success Write bool Whether execution succeeded
error Write str|None Error message if failed
clarification_question Write str|None Set if question was ambiguous
sql_confidence Write float Model confidence 0.0–1.0
execution_attempts Write int Number of self-correction attempts

Architecture

sqlmind/
├── core/           # DB connection + schema introspection + embedding index
├── semantic/       # Glossary (YAML/dict) + MetricRegistry
├── agent/          # clarify → generate → validate → execute → memory
├── guardrails/     # Abstract interface + 5 built-ins + custom registry
├── integrations/   # langgraph_node.py (as_node + exploded nodes)
└── llm/            # LLMProvider protocol + LangChain/OpenAI/Anthropic adapters

Running Tests

pip install sqlmind[dev]
pytest tests/ -v

License

MIT

Metadata

Release files for sqlmind 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sqlmind 0.1.1
File Size Uploaded
sqlmind-0.1.1.tar.gz 45.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for sqlmind 0.1.1
File Interpreter ABI Platform
sqlmind-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 96.2 kB

Release files / sqlmind-0.1.1.tar.gz

Download URL sqlmind-0.1.1.tar.gz
Size 45.7 kB
Tags Source
SHA-256 checksum
How to use checksums
7744a060977694d2505daf7394632eb5b14de19d65d45dca8db1701dc48a1a83
BLAKE2b-256 checksum
How to use checksums
462a90ea4eba1e110ca7ec3b6fb6a420010f9a0c89a20d66aab6b65366482ee6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.3

Release files / sqlmind-0.1.1-py3-none-any.whl

Download URL sqlmind-0.1.1-py3-none-any.whl
Size 50.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e4ce7c2c273f5864cd0de7a7be3c8a9c5d4fb8620d7d89b060d2ccdb3ef479f0
BLAKE2b-256 checksum
How to use checksums
423ebfd5e91649be6b2d21dacfa43b72a83582adad737440f385ef0a2aaf6640
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.3

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page