Blog
Saved0

Text-to-SQL for AI agents: why valid queries return wrong answers

The agent's SQL ran cleanly and reported Q3 revenue 38% too high. How text-to-SQL answers the wrong question, and how typed, scoped, reviewed queries give agents data access you can defend.

LinkedIn
On this page
  1. The query ran. The number was wrong.
  2. What are the risks of text-to-SQL for AI agents?
  3. Why does valid SQL answer the wrong question?
  4. Typed collections, not raw tables
  5. Declare joins and results as contracts
  6. Scope belongs in the query, at field and record level
  7. How should AI agents query business data safely?
  8. Every answer needs a query receipt
  9. Common anti-patterns
  10. Ten rules for governed agent queries
  11. The result: answers that mean what they say
  12. Frequently asked questions
  13. How Frozion governs agent queries
  14. Sources
The short answer

Text-to-SQL lets a model write queries that run but answer the wrong question: joins that duplicate rows, sums across currencies, results at the wrong grain, or rows outside the user's scope. Governed data access gives agents typed collections, declared join and result contracts, field- and record-level scope, and reviewed queries that leave a receipt each time they run.

The query ran. The number was wrong.

A finance director asks an analytics agent for Q3 revenue by region ahead of a board pack. The agent reads the schema, writes SQL, runs it, and returns a tidy table. EMEA: $14.2 million. The query is syntactically perfect. It executes in under a second. Nobody sees an error.

The real EMEA figure was $10.3 million. The agent joined orders to order lines and then to payments, so every order paid in instalments was counted once per payment. It summed the amount column across euros, pounds and dollars as if they were one currency. It grouped at order-line grain and rolled up, so discounts applied at order level were counted against each line. And because the director could see all regions, nobody noticed that the same query, asked by a regional manager, would also have returned rows outside that manager's scope.

The model didn't hallucinate a table or invent a column. It wrote valid SQL against a real schema. The schema simply didn't carry the business meaning the question depended on.

What are the risks of text-to-SQL for AI agents?

The main risk is wrong answers that look right: valid SQL that duplicates rows, mixes units, aggregates at the wrong grain or reads outside the user's scope, with no error to warn anyone.

Most public discussion of text-to-SQL focuses on whether the generated query matches an expected one. That's a useful benchmark for models. It isn't the question a risk owner asks, which is: did this answer apply our definition of revenue, for the records this person may see, at the grain the decision needs?

FailureWhat happensWhy nobody notices
Fan-out joinA one-to-many join repeats parent rows, inflating sumsEvery row is "real"; the total is just too big
Mixed unitsAmounts in different currencies or units are addedThe column is called amount
Wrong grainA metric defined per order is computed per line, or per day instead of per monthGrouping looks reasonable
Wrong definitionGross used where net was meant; cancelled orders includedThe schema doesn't encode the business rule
Scope leakRows or columns outside the requester's permission are readThe agent's database credential could see them
Cost and loadUnbounded scans on production tablesIt works fine in testing

Each of these is a semantics problem, not a syntax problem. A better model reduces the rate. It doesn't remove the class, because the information needed to avoid them isn't in the schema.

Why does valid SQL answer the wrong question?

Because a database schema describes storage, not meaning. It says which columns exist and how tables link, but not which joins are safe, which units can be summed, or what grain a metric is defined at.

Business meaning lives elsewhere: in finance policy, in a data team's dashboards, in the head of whoever built the revenue report. An analyst who has done this for years knows that payments fan out and that currency needs converting at the booking-date rate. A model given only the schema has to guess, and the guesses that produce plausible numbers are the dangerous ones.

Typed collections, not raw tables

The first step is to stop pointing agents at physical tables. Expose business entities instead (customers, orders, invoices, cases) as typed collections with declared fields.

A typed field carries meaning the schema lacks. Amount is a money value with a currency. Status is one of a fixed set of values, and cancelled is excluded from "open" by definition. Region is a scope attribute, checked against the requester. When the agent works against collections like these, a whole category of guessing disappears.

Declare joins and results as contracts

Two contracts prevent most silent errors.

Join contracts state how collections relate and with what cardinality: an order has many lines, a line belongs to one order, an order has zero or more payments. A query that would fan out across two one-to-many relationships before aggregating is flagged before it runs.

Result contracts state what a query returns: the grain (one row per region per month), the units (amounts in reporting currency, converted at a declared rate), the definition (net revenue excludes cancelled and refunded orders), and the shape (field names and types). An agent consuming the result knows exactly what each number means, and so does the person reviewing the decision later.

Diagram of orders, order lines and payments collections with declared cardinality, a flagged fan-out path, and a result contract card showing grain, units and definition
Join contracts catch fan-out before it inflates a total; result contracts say exactly what each number means.

Scope belongs in the query, at field and record level

The agent's database credential is usually broader than any one user. If the query runs with that credential, the agent can see everything, and every answer is a potential disclosure. OWASP's guidance on excessive agency is direct about this: give an LLM-driven tool only the permissions the task needs.

Apply the requester's authority inside every query, at two levels:

  • Record level. Only rows the person may see: their tenant, legal entity, region, accounts or cases.
  • Field level. Only columns they may see: margins, salaries and personal data are masked or omitted for people without access.

The scope comes from the person the agent acts for, not from the agent's own service account, and it's checked when the query runs, not when the agent was configured. See taxonomy-scoped authorization for how scope can follow business structure such as regions and product lines.

How should AI agents query business data safely?

Give agents reviewed, named queries to call as tools, rather than asking them to write SQL. Teams author each query in SQL or visually, review it, and publish it with its contracts and scope.

This doesn't mean giving up flexibility. A query can take parameters (region, period, account), and a library of reviewed queries covers most operational questions. The agent's job shifts from writing SQL to choosing the right query and filling in parameters, which models do far more reliably.

ApproachWho writes the queryMeaningScopeReviewable
Free-form text-to-SQLThe model, per requestGuessed from schemaAgent's credentialAfter the fact, if logged
Text-to-SQL with a semantic layerThe model, constrainedPartly declaredOften still the agent's credentialPartially
Governed queriesPeople, in SQL or visuallyDeclared in contractsRequester's, per runBefore any agent uses it

Where an agent does need an ad hoc question answered, treat the generated query as a proposal: check it against join and result contracts, apply scope, and route anything novel and consequential to a person before its result drives an action.

Every answer needs a query receipt

When an agent's number feeds a decision, you'll eventually be asked where it came from. A query receipt answers that in one record:

  • which query and version ran, with which parameters;
  • on whose behalf, with what scope applied;
  • against which data, at what time or snapshot;
  • what it returned, including row count and totals.

That turns "the agent said EMEA was $10.3 million" into evidence you can check and reproduce. It also links into the wider decision record. See audit trails versus evidence.

Flow from an agent's question to a reviewed query tool, through a scope check, to typed collections, returning a result with a query receipt
The agent picks a reviewed query and parameters; the runtime applies scope, runs it and records a receipt.

Common anti-patterns

Anti-patternWhy it failsWhat to do instead
Point the agent at raw production tablesThe schema has no business meaningExpose typed collections with declared fields
Trust SQL because it executesFan-out, mixed units and wrong grain never errorCheck against join and result contracts
Run agent queries with a shared service credentialEvery user gets the agent's full viewApply the requester's record and field scope per run
Put "only show permitted data" in the promptInstructions aren't access controlEnforce scope inside the query
Let each agent invent its own revenue definitionThe same question gets different answersPublish one reviewed query per business metric
Log the SQL text onlyYou can't tell what data or scope it ran againstRecord a full query receipt
Let ad hoc generated queries drive actions directlyNovel, unreviewed logic decides consequential outcomesTreat them as proposals; review before use

Ten rules for governed agent queries

  1. Don't give agents raw tables; give them typed collections.
  2. Declare joins with cardinality, and flag fan-out before aggregation.
  3. Declare each result's grain, units, definition and shape.
  4. Store money with its currency and convert at a declared rate.
  5. Apply the requester's record- and field-level scope inside every query.
  6. Use the delegating person's authority, not the agent's service account.
  7. Author queries in SQL or visually, and review them before agents use them.
  8. Let agents choose queries and parameters, not write production SQL.
  9. Treat any generated query as a proposal until it's checked.
  10. Record a receipt for every run: query, version, parameters, scope, data and result.

The result: answers that mean what they say

Text-to-SQL made it easy for anyone to ask a database a question. For agents that act on the answer, that ease is the problem: the question gets answered, just not quite the one that was asked. Governed queries move business meaning out of the model's guesswork and into contracts people can read and review.

The agent still does the useful part: understanding the request, picking the right query, explaining the result. The definition of revenue, the safe joins, the scope and the record of what ran stay where they belong, with the people accountable for them.


Frequently asked questions

What are the risks of text-to-SQL for AI agents?

Wrong answers that look right, plus access risk. Generated SQL can duplicate rows through joins, sum mixed currencies, aggregate at the wrong grain, read columns or records outside the user's scope, or run expensive queries against production. None of these raise an error.

Is text-to-SQL accurate enough for business decisions?

It works for exploration, not for decisions on its own. Accuracy benchmarks measure whether generated SQL matches an expected query, not whether a business definition such as net revenue was applied correctly. For decisions, agents should call reviewed queries with declared meaning, grain and scope.

What is governed data access for AI agents?

It's an approach where agents query business data only through typed collections and reviewed queries, with the requester's field- and record-level scope applied inside the query, declared result contracts, and a receipt recording what ran, for whom and what it returned.

How does this work for agents we already run?

Route the agent's data requests through a governed runtime over MCP or HTTPS. Instead of sending SQL, the agent calls reviewed queries as tools; scope is applied for the person it acts for, and every result carries a query receipt.

With Frozion

How Frozion governs agent queries

In Frozion, agents query typed operational collections through Collections & Query Builder. Join and result contracts declare how entities relate and what each result means, and every run leaves a query receipt. Teams author queries in SQL or in the Visual Query Builder, and review them before any agent uses them. Authorization combines roles, conditions, taxonomy scope, purpose and record-level checks, so each query runs with the authority of the person the agent acts for. Any workflow that runs a query can be exposed as an MCP tool for agents you already run.


Sources

  1. OWASP Top 10 for LLM Applications 2025Excessive agency, sensitive information disclosure and improper output handling.
  2. OWASP LLM06:2025 Excessive AgencyLimit what an LLM-driven tool can do to what the task needs.
  3. OWASP Top 10 for Agentic Applications (2026)ASI02 tool misuse and ASI03 identity and privilege abuse.
  4. NIST SP 800-162, Guide to Attribute Based Access ControlPer-request access decisions from subject, object and environment attributes.
  5. NIST SP 800-53 Rev. 5AC-3 access enforcement, AC-6 least privilege, AU audit records.
  6. W3C PROV-ONeutral model for recording what produced a result.
  7. EY survey on AI governance, September 202672% worry they can't trace the lineage behind critical AI decisions.
More in Data & context

Data & context

Context assembly 2
Retrieval & data access 3
State, memory & features 2

Other topics

Pick up where you left off: