Studio agent — built in-houseAnalytics · Text-to-SQL
SQL Analyst Agent
Ask the database a question in English; it writes the SQL, runs it, and self-corrects.
$npm run sql "your question"
$ npm run sql "your question"
SQL Analyst Agent · demo.sqlite — 60 customers, 210 orders, 420 line items
Revenue by category and top customers. Schema introspection, two revenue queries across three joined tables, and a plain-English answer with figures we verified by hand.
270
Rows across the sample DB
Read-only
Enforced at the harness
Self-fix
Rewrites on SQL errors
$136,554
Figure it computed — verified
Text-to-SQL looks solved in a demo and breaks in reality. A model that has not seen the schema guesses a column name and writes a query that either errors or, worse, runs and returns a plausible-but-wrong number. Analytics that can’t be trusted are analytics no one uses. The agent had to ground itself in the real schema, verify by executing rather than asserting, and never be able to mutate the data it is reading.
Before writing anything, the agent introspects the schema and, when a column is ambiguous, samples rows. It writes SQL, runs it against a real SQLite database, and if the query errors it reads the message and fixes it rather than fabricating a result. The harness enforces read-only at the boundary — anything but a SELECT or WITH is rejected — so the agent can explore freely without any risk to the data.
A runnable agent over a 60-customer, 210-order sample database. Asked which category earns the most and who the top customers are, it introspected the schema, wrote two correct revenue queries joining three tables, and answered with real figures — Services at $136,554, ahead of Licenses and Add-ons. We re-ran its SQL by hand: the numbers match exactly. The transcript is below.
Capabilities
Built with
3 tools, one decision loop.
get_schema
Returns the real CREATE TABLE statements, so the agent writes against the actual columns instead of guessing their names.
sample_rows
Pulls a few rows from a table when a column’s meaning is ambiguous — grounding the query in the data’s real shape.
run_sql
Executes a query and returns the rows. Read-only by contract: anything that isn’t a SELECT or WITH is refused before it touches the database.
The calls that decide whether it survives contact.
Verify by running, not by asserting
The agent never claims a number it did not compute. Every figure in its answer comes back from a query it actually executed, which is why the results survive an independent re-run — the difference between an analyst and an autocomplete.
Read-only at the boundary
The guard against a destructive query lives in the harness, not the prompt. A model can be talked into anything; a regex that rejects everything but SELECT/WITH cannot. Safety belongs where it can’t be argued away.
Look before you query
Introspecting the schema first is what separates a query that runs from one that errors on an invented column. The cheap step up front removes most of the self-correction the agent would otherwise need.
Full transparency
This is one of our own studio agents, not client work. It runs on sample data we built ourselves, and the terminal above replays a real recorded run — the reasoning, tool calls, errors and timings are exactly what happened, only the playback is paced for watching. We show it because it is the honest version of “we build AI agents”: code you could run, not a slide.