Demo
An AI assistant that can read, and nothing more
An AI assistant answers questions about an invented climbing gym through a small data server. The server offers four tools, all of them reads, and every query passes the same checks: a statement guard, read-only access, a query check, a cost ceiling and a row cap. Pick a request, or call the server yourself, and see what is refused and why.
This is a simulation. No AI model runs on this page: the assistant’s requests and replies are scripted. The server’s checks and its small query engine are real code running in your browser, over records made from a fixed formula. The gym, its groups and every number are invented. Nothing can be changed, nothing you type leaves your browser or is kept, and reloading the page starts again.
Ask the assistant
Each request is written for you. The assistant decides which tools to call; the server decides what it will do.
Call the server yourself
The exchange
Nothing asked yet. Pick a request or call the server yourself: each tool call, the checks it passed through and what came back appear here. Earlier calls stay in the audit list.
The server
Four tools, all of them reads
show_tables: Lists the tables, with how many rows each holds and its full size.show_columns: Lists one table’s columns, their types and the bytes each adds to a row.read_query: Runs one read-only query. Start with daily_summary, and filter visits by day.find_group: Finds a group by its exact name or alias. A close name returns candidates, never a guess.
No tool can add, change or delete a record, so there is nothing to misuse.
What every call passes
- Statement guard. One read statement only, a plain SELECT; no word that writes or changes a table; no comment or quoted name that could hide one; only the four tables, named plainly.
- Read-only access. Every call runs as the person who asked, with read access only, so even a query that slipped past the guard could not change anything.
- Query check. The small engine reads the whole query first. A column the table does not have, or a form it does not handle, is refused with the reason before anything is estimated or read.
- Cost ceiling. The bytes a query would read are worked out before it runs, from the days it touches and the columns it names. Over 750 KB and it is refused before reading anything. The ceiling is set low here so you can reach it.
- Row cap. At most 25 rows come back, with a note saying how many were left out.
- Exact names. A group is found by its exact name, slug or alias. A close name returns candidates to confirm, never a guess.
The records cover days 1 to 360. Today is day 360.
Audit list
Every call is listed here under the person who made it, refusals included.
What the demo shows
- Read only by construction. The server offers four tools and all of them read. Asked to change a booking, the assistant finds no tool that could, so nothing is changed. There is no rule to get around, because the path does not exist.
- A statement guard on every query. Only one read statement runs. A delete, an update, a second statement or a comment is refused before it reaches the data, with the reason in plain words.
- A cost ceiling checked before the query runs. The server works out how much a query would read from the days it touches and the columns it names. Every visit with every column is over the ceiling and is refused; a filter on day, or the table added up in advance, fits.
- Answers kept small. At most 25 rows come back, with a note saying how many were left out, so a result never floods the assistant.
- Refuse rather than guess. Asked about the Rooks, the server finds two close names and returns both for you to confirm. It never picks one, and an unknown name gets a plain refusal.
- Every call attributed. Each call runs as the person who asked and is written to the audit list, refusals included.
- The model asks; code decides. In a real system a language model would choose the calls and write the replies. Here they are scripted, and every check, estimate and answer is worked out by code in this page.