PyPI (Python API)
Use this path when you want to embed NL2SQL directly in a Python application. See the Core API documentation at docs/api/index.md.
Install
# Core only
pip install nl2sql
# install all available adapters. (Never prefer this, until you really need all adapters.)
pip install "nl2sql[all]"
# Core with selected adapters
pip install "nl2sql[postgres]"
pip install "nl2sql[mysql,mssql]"
pip install "nl2sql[duckdb]"
Configure
Create config files in your working directory:
configs/datasources.yamlconfigs/llm.yamlconfigs/policies.jsonconfigs/secrets.yaml(optional)
Start from the examples in configs/datasources.example.yaml, configs/llm.demo.yaml,
and configs/policies.example.json.
Detailed schemas for each file:
Configuration paths at startup
You can pass config paths directly when creating the engine:
from nl2sql import NL2SQL
engine = NL2SQL(
ds_config_path="configs/datasources.yaml",
llm_config_path="configs/llm.yaml",
secrets_config_path="configs/secrets.yaml",
policies_config_path="configs/policies.json"
)
Use startup configuration for fixed, app-wide settings. Use runtime registration when you need to add or override datasources/LLMs per request, per tenant, or on a long-running process without restart.
Datasource configuration
configs/datasources.yaml defines one or more database connections and limits:
version: 1
datasources:
- id: my_postgres
description: "Primary analytics DB."
connection:
type: postgres
host: localhost
port: 5432
user: ${env:POSTGRES_USER}
password: ${env:POSTGRES_PASSWORD}
database: analytics
statement_timeout_ms: 8000
row_limit: 100
max_bytes: 10485760
Install the adapter extras that match connection.type:
See Adapters for the full list of available adapters. See Datasource config for field definitions.
LLM configuration
configs/llm.yaml selects the default model and any per-agent overrides:
version: 1
default:
provider: openai
model: gpt-5.2
temperature: 0.0
api_key: ${env:OPENAI_API_KEY}
agents:
indexing_enrichment:
provider: openai
model: gpt-5.2
temperature: 0.0
api_key: ${env:OPENAI_API_KEY}
version: 1
default:
provider: openrouter
model: anthropic/claude-sonnet-4.5
temperature: 0.0
api_key: ${env:OPENROUTER_API_KEY}
A local Ollama daemon is configured the same way, with
provider: ollama and no api_key; how well a given local model handles the
pipeline's structured output varies by model, so see
LLM configuration → Ollama first.
Note that OpenRouter serves chat completions only. Embeddings are selected
separately with EMBEDDING_PROVIDER: the default openai means nl2sql index
needs OPENAI_API_KEY set as well, while EMBEDDING_PROVIDER=local embeds with
a key-free ONNX model (see
System configuration → Embeddings).
See LLM config for full schema details.
Add a datasource at runtime
You can register a datasource programmatically without editing config files:
from nl2sql import NL2SQL
engine = NL2SQL()
engine.add_datasource({
"id": "runtime_pg",
"description": "Runtime Postgres datasource",
"connection": {
"type": "postgres",
"host": "localhost",
"port": 5432,
"user": "postgres",
"password": "postgres",
"database": "analytics"
},
"statement_timeout_ms": 8000,
"row_limit": 100,
"max_bytes": 10485760
})
engine.index_datasource("runtime_pg")
You can also register datasources from a config file at runtime:
from nl2sql import NL2SQL
engine = NL2SQL()
engine.add_datasource_from_config("configs/datasources.yaml")
Add an LLM at runtime
You can also register or override LLMs programmatically:
from nl2sql import NL2SQL
engine = NL2SQL()
engine.configure_llm({
"name": "default",
"provider": "openai",
"model": "gpt-5.2",
"temperature": 0.0,
"api_key": "${env:OPENAI_API_KEY}"
})
You can also load LLMs from a config file at runtime:
Policies configuration (RBAC)
configs/policies.json defines which roles can access which datasources/tables:
{
"version": 1,
"roles": {
"admin": {
"description": "System Administrator",
"role": "admin",
"allowed_datasources": ["*"],
"allowed_tables": ["*"]
}
}
}
Secrets configuration (optional)
configs/secrets.yaml is only needed when you want to pull secrets from a provider:
version: 1
providers:
# - id: azure-prod
# type: azure
# vault_url: "https://my-vault.vault.azure.net/"
Secrets providers are installed via extras and selected in configs/secrets.yaml:
Run a query
from nl2sql import NL2SQL
from nl2sql.auth.models import UserContext
engine = NL2SQL()
user_ctx = UserContext(user_id="user123", roles=["admin"])
result = engine.run_query(
"Top 5 customers by revenue last quarter?",
user_context=user_ctx
)
print(result.final_answer)
for sub_query in result.sub_queries:
print(sub_query.datasource_id, sub_query.sql)
The QueryResult includes sub_queries (each with its generated sql),
final_answer, errors, warnings, artifact_refs, and a trace_id for
observability. Result rows are not inlined; they live in artifact storage and are
addressed through artifact_refs.
Lifecycle (configure → index → query)
- Configure datasources, LLMs, and policies.
- Index schemas at least once (and after schema changes).
- Run queries.
Index schema (required)
Configure providers
Secrets providers are installed via extras and selected in configs/secrets.yaml:
See Configuration system for environment variables and defaults.