rdst ask
Turn a plain-English question into a validated, read-only SQL query against a target.
rdst ask takes a natural-language question and generates SQL that is safe to run
against your database. It validates the query before executing (read-only, valid
columns, required LIMIT), shows you the SQL for confirmation, runs it with a
timeout, and renders the results.
Quality depends heavily on your semantic layer: with just table and column names the LLM is guessing, with descriptions and enum meanings it is informed.
Common usage
# Simple question
rdst ask "How many customers signed up last month?" --target prod-orders
# Generate SQL without running it
rdst ask "Average order value by segment" --target prod-orders --dry-run
# Agent mode for ambiguous or multi-step questions
rdst ask "Which suppliers are most at risk of losing their top customer?" \
--target prod-orders --agent
# Non-interactive for scripts
rdst ask "Count of orders in the last 24h" --target prod-orders --no-interactiveModes
| Mode | When to use | Behavior |
|---|---|---|
| Default | Clear, schema-grounded questions | Linear flow: generate SQL → confirm → execute → show results |
--agent | Ambiguous or multi-step questions | The LLM iteratively explores the schema, runs EXPLAIN checks, and drafts SQL over several turns |
Example interaction
$ rdst ask "What were our top 10 customers by revenue last month?" --target prod-orders
Using semantic layer (34 tables annotated).
Generated SQL:
SELECT c.id, c.name, SUM(o.total_cents) AS revenue_cents
FROM customers c
JOIN orders o ON o.customer_id = c.id
WHERE o.created_at >= DATE_TRUNC('month', NOW() - INTERVAL '1 month')
AND o.created_at < DATE_TRUNC('month', NOW())
AND o.status = 'paid'
GROUP BY c.id, c.name
ORDER BY revenue_cents DESC
LIMIT 10;
Validation: OK
✓ Read-only
✓ All referenced columns exist
✓ LIMIT present (10)
Execute? [Y/n] y
Results (10 rows, 78 ms):
id name revenue_cents
─────── ────────────────────── ──────────────
1023 Acme Manufacturing 4,820,135
2118 Blue Orchid Foods 3,914,200
745 Hendricks Retail 3,120,980
...How it works
rdst ask runs every question through the same pipeline:
| Step | What happens |
|---|---|
| 1. Load schema | Prefer the semantic layer (fast, annotated); fall back to live introspection if no layer is configured. |
| 2. Clarify (optional) | Detect ambiguity. For example: "last month" → prompt if you want calendar month or rolling 30 days. |
| 3. Generate SQL | LLM produces candidate SQL (temperature=0.0 for determinism). |
| 4. Validate | Read-only? All columns exist? LIMIT present? If not, retry with the error as context, up to 3 times. |
| 5. Confirm | Show the SQL. You can accept, reject, or edit before running. |
| 6. Execute | Run with --timeout (default 600s). Render results. |
--agent inserts a schema-exploration loop before step 3 for questions where the
model needs to learn about the schema before it can write good SQL.
Flags reference
| Flag | What it does |
|---|---|
--target <name> | Target database |
--dry-run | Generate and show SQL without executing it |
--timeout <seconds> | Query timeout (default 600) |
--verbose | Show detailed reasoning and intermediate steps |
--agent | Use agent mode (iterative schema exploration) |
--no-interactive | Skip confirmation prompts (for scripts) |
Get better results
The single highest-impact thing you can do for rdst ask quality is configure a
semantic layer:
rdst schema init --target prod-orders
rdst schema annotate --target prod-orders --use-llm # AI-generated descriptions
rdst schema show --target prod-orders # review
rdst schema edit --target prod-orders # tweak enum meanings and business termsBefore:
The LLM sees
status VARCHAR(16)and has to guess what values mean.
After:
The LLM sees that
statusis an enum withpaid,refunded,shipped,cancelled, and thatpaidandshippedboth represent completed orders in your business.
Semantic layers are per-target. If you have ten targets with identical schemas,
you can export one and import it into the others with
rdst schema export / rdst schema import.
Safety guarantees
rdst ask enforces three rules on every query it generates and will never let
you execute one that violates them:
- Read-only. No
INSERT,UPDATE,DELETE,DDL, or procedure calls. - Columns must exist. The validator checks every referenced column against the actual schema before executing.
LIMITis required. Prevents accidentally running unbounded scans.
On top of this, the generated query is shown to you for confirmation before
execution. --no-interactive bypasses the confirmation prompt but does not bypass
the validation rules.
See also
rdst schema— how to build the semantic layer that powersaskrdst analyze— when you already have a SQL query and want performance insights instead- Data agents — expose
ask-style access to external clients with stricter safety policies