Let's talk

Services

AI Data Assistant Development Services

Letting your team ask your own systems questions in plain English, with the database — never the model — deciding what each person is allowed to see.

Owners and operations leaders whose managers wait days for a report that is already out of date when it arrives

Most business questions about data still take the same slow route. Someone asks a manager, who asks an analyst, who writes a query, and an answer arrives two or three days later describing a situation that has since moved on.

The appeal of asking the system directly is obvious. The reason most attempts stall is also obvious once you have seen one fail: the answers cannot be trusted, and nobody can say exactly when they can be.

The two things that have to be true

An assistant over your own data is worth having only if both hold at once.

It must not show the wrong person the wrong rows. Not “should not” — cannot. That is an access control question, and the answer to it is never a sentence in a prompt.

It must not invent a figure. A system that is usually right about revenue is not useful, because every number then has to be checked, and checking it is the work you were trying to avoid.

Both are engineering problems with known answers, and neither is solved by using a better model. We have written both up in detail — why permissions belong in the database and why the model should never produce the number — including the trap where a database view silently bypasses the protection you just built.

What we do before writing any of it

The first engagement is a diagnostic, because an assistant is only as good as the description of your system that it is given, and that description does not exist yet in most companies.

It is generated from your code and verified against your live database rather than written from interviews. On the first system we ran it against, none of what it found had been asked for:

  • 21 of 45 join conditions were not backed by a foreign key. Real, load-bearing relationships that only exist in code — and exactly what a text-to-SQL tool guesses at and gets wrong. That work is written up here.
  • Two tables both describing order status, with colliding ids — id 2 meaning Approved in the live table and Cancelled in the legacy one, with 2,667 orders sitting on it. Reading the wrong one reports every approved order as cancelled.
  • 200 of 266 read endpoints had no explicit permission check. All authenticated, but the authorisation decision lived inside each handler where it had to be read case by case. Nobody set out to audit that; it fell out of writing down what the system does.

That last one is the reason we recommend the diagnostic even to companies who decide against the assistant. It is a description of your own system precise enough to hand to a machine, and the act of producing it surfaces things no roadmap was going to find. A related engagement found a target-setting endpoint that checked nothing at all, which meant any signed-in employee could write anyone’s sales target.

The report is yours either way.

How the answer is actually produced

The model does two things and no more: it picks which of a fixed set of operations the question wants, and it pulls a name out of the sentence.

Everything after that is a query, running as the person who asked. The rows come back scoped by the database. Totals are computed by the server over those exact rows. The model’s last job is to write a sentence around a number it was handed and is forbidden to change.

Anything that writes is confirmed by the user before it happens, and every request — including refusals and failures — is recorded with the query that ran.

Where this is running today

The pattern is implemented twice. It is live in production inside our own out-of-home advertising product, where the assistant resolves each caller’s permissions through the same engine that guards the REST API rather than a parallel list that can drift, and uses them twice: once to decide which tools are even described to the model, and again inside each tool before it executes.

The second implementation, for a field-sales operation, runs end to end on that client’s test environment — twenty-three tools, nineteen scoped queries, the permission gate and an automated browser test that signs in as real users. It is not in production, and it will not be until two known defects close. Both are named in the articles above, because the useful question about any system is not whether it has defects but whether the people who built it can tell you what they are.

What this is not

It is not a replacement for your reporting. Scheduled reports, statutory returns and anything with a fixed definition should stay exactly where they are; this is for the questions nobody wrote a report for, which is most of them.

It is not a way to avoid understanding your own data. If two tables disagree about what a status means, an assistant will report that disagreement confidently and at speed. The catalogue work is not a preliminary to the project — on a system of any age, it is most of it.

How it runs

What the engagement includes

  1. 01 A catalogue and diagnostic of the system you already run — the joins your schema does not declare, the reference data that contradicts itself, and which endpoints actually check a permission. Fixed scope, and the report is yours whether or not you build anything afterwards
  2. 02 The permission boundary built first — a read-only role, a schema built for the purpose, and row-level security policies a generated query cannot write itself out of
  3. 03 A measured model choice, using a routing suite on your own questions, so the model is selected on accuracy against a priced alternative rather than on preference
  4. 04 An answer path where the model never computes — it picks a tool and extracts a name, every value is bound, and totals are calculated on the server over the exact rows returned
  5. 05 Adversarial tests that sign in as real users and assert that two people asking the same question get different rows

Tell us how the work
runs today.

We will tell you honestly whether this service is the right shape for it, or whether something smaller would do.

AI Data Assistants — frequently asked questions

Is it safe to let an AI query our database?

It is safe if the refusal lives in the database rather than in the instructions given to the model. A sentence in a prompt saying "only show this manager their own region" is an argument with a text predictor, and anything expressible in text can be argued with. PostgreSQL row-level security applies the restriction in the engine, so a generated query with no WHERE clause at all still returns only the rows that caller is entitled to. The worst case becomes a query that returns nothing useful, rather than one that returns somebody else's numbers.

Will it get the numbers wrong?

It will if the model is allowed to do arithmetic. We measured this — asked to total ten rows, a capable model returned 3,585 on one run and 3,485 on the next when the true figure was 3,374, with no error raised on any attempt. The fix is structural rather than a sterner prompt: the model selects a tool and extracts a name, the database finds the rows, and the server computes the totals over the exact rows returned. You cannot get a wrong sum from something that is not permitted to add.

Do we need a data warehouse or a BI platform first?

Usually not, and this is where most advice points in the wrong direction. The standard answer assumes a semantic layer in a BI tool, which means a data engineer, a modelling project and a budget before anyone asks a question. If your operational system is the system of record and the data volume is ordinary, the assistant can run against a purpose-built read-only schema on the database you already have. We check the size and shape before recommending either way.

What does it cost to run each month?

Less than almost anyone expects, and it is not where the money goes. On a measured routing suite the spread between the cheapest usable model and the best one was two cents to forty-five cents per thousand questions, so accuracy is worth buying outright. The real cost is the engineering — the catalogue, the permission model, the scoped queries and the testing — which is one-off work, and which no model choice changes.

What happens when it does not know the answer?

It should refuse, and the refusal has to be true. That is harder than it sounds: in our own build a routing defect produced a refusal saying no matching person was found when the person was in scope and findable under a different phrasing. It is written up publicly and it is open. A system that answers every question is worse than one that declines some, because you cannot tell which answers to check.

Can you build this on our stack?

The approach transfers anywhere; the tooling is strongest on PostgreSQL with a Node or Python application, because the catalogue extractors read that code directly and row-level security with security_invoker views needs PostgreSQL 15 or later. On other stacks the diagnostic takes longer because more of the catalogue is assembled by hand. We will tell you which case you are in during the first conversation rather than after a purchase order.