Ask your database a question. Keep the answer live.

chat · northwind
Chart monthly revenue for this year
get_schema_summary
SELECT date_trunc('month', order_date) AS month,
       SUM(total) AS revenue
FROM orders
WHERE order_date >= '2026-01-01'
GROUP BY 1 ORDER BY 1;
✓single read-only statementSELECT date_trunc('month', order_date) … GROUP BY 1one statementno INTOno denylist hit
✗refused before a connection opensUPDATE orders SET total = 0;
Monthly revenue replayed · 96 ms · no model

Same call, same database, fresh rows. The agent isn't in this loop at all.

How it works

Three beats, and the model is only in the first one.

1

Ask in plain words

The agent reads your schema, writes dialect-correct SQL — T-SQL, PostgreSQL or KQL — and streams every tool call into the chat as it runs. Nothing is hidden behind a spinner.

2

Nothing reaches your database unread

ReadOnlyGuard parses the statement first. One SELECT or WITH, no batching, no SELECT INTO, nothing on the denylist — or it's refused before a connection is ever opened.

3

Pin it. It stays alive.

The widget keeps the exact call that produced it. Refresh replays that call against your database — no model, no re-interpretation, the same numbers your SQL would give you.

Inside a widget

Every widget carries its own query.

Monthly revenuerefreshed 12 s ago
SourceCallsJsonstored verbatim · replayed on refresh
{
  "tool": "run_readonly_query_json",
  "data_source": "northwind",
  "sql": "SELECT date_trunc('month', order_date) AS month, SUM(total) AS revenue FROM orders WHERE order_date >= '2026-01-01' GROUP BY 1 ORDER BY 1"
}

Result rows are never copied to our servers. The widget knows how to get its data, not the data itself.

What's inside

Named after what it actually does

run_readonly_query_json

The agent shows its work

Every tool call streams into the chat as it runs. The SQL is dialect-correct T-SQL, PostgreSQL or KQL — yours to read, every time.

SourceCallsJson

Widgets remember their query

A pinned widget stores the call that produced it, verbatim — never the rows.

ReadOnlyGuard

Writes cannot happen

One SELECT or WITH, or it's refused before a connection is opened.

ScheduledRefreshService

Refreshes while you sleep

Set a cadence; the server replays each widget on time and the dashboard opens on fresh rows.

get_table_relationships

Your schema as a map

Tables, views and foreign keys as a draggable graph — the map the agent walks.

SchemaDiff

Your files are a source too

Drop csv, Excel or JSON into a bucket and ask; each becomes a typed SQLite table. Replace a file and every widget built on it is re-checked, then refreshed.

anthropic · openai · gemini

Your model, your key

Start on Klyrova credit, or bring your own key and pick from your provider's live model list. Keys never leave the server.

mssql · postgres · kql · sqlite

Five sources, one place

Warehouses, lakehouse endpoints and KQL databases sit beside your Postgres and your own uploaded files — every connection is read-only by contract.

Security

Read-only by contract,
not by promise

The guard parses every statement before your database ever sees it. Anything that isn't a single read is refused — no exceptions, no flags to flip. Your credentials are encrypted, bound to your account, and never shown again.

ReadOnlyGuard

UPDATE orders SET total = 0;

✗ rejected — not a single read-only statement

SELECT 1; DROP TABLE orders;

✗ rejected — batching is not allowed

SELECT month, SUM(total) FROM orders GROUP BY month;

✓ 8 rows · 96 ms

Klyrova Ask your database. Keep the answer live.PrivacyTerms