How to build a reliable text-to-SQL agent in production

How to build a reliable text-to-SQL agent in production

What months of connecting AI agents to real company databases taught us: the production pitfalls, security, access rights, and when to build or buy.

Guide
7 min read

Connecting an AI agent to a database, known as text-to-SQL, lets it answer far more questions. With our customers, the typical example is a troubleshooting agent for a complex product. When the technical documentation isn't enough, it searches the ticket database for a case close to the user's and helps them solve the problem. It can then draft the documentation update and submit it to someone for approval.

The model translates the question into a SQL query, the platform runs it, and the model reads the result. You can code an agent that queries a database fairly quickly, but getting good answers in production, across a wide range of questions, takes a significant investment, just like taking RAG from POC to production.

We learned this by iterating on this kind of agent for months, with customers who each brought their own use cases, schemas and engines, including MariaDB and PostgreSQL, sometimes on databases with several hundred tables. At one of them, after several iterations, about 84% of calls to our database tool succeeded. Since moving to an agentic approach, where the agent works in several steps, more than 99% of queries succeed on the first try. If you work in IT, this is the path to cost out before starting an in-house project: months of iteration to get from a demo to a reliable tool, then maintenance that never stops.

Here is what our agent does, in 40 seconds. We then go through the pitfalls one by one, followed by the options for building or buying.

Two LLMs that have to understand each other

In most architectures, two models work together:

  • the main agent talks to the user, decides when to query the database, then writes the answer;
  • a SQL generator, called as a tool, receives a question and the database structure and writes the query; the platform runs it and returns the result to the main agent.

The split makes sense: the main agent doesn't need to know 600 columns to hold a conversation, and the generator can be a fast, specialized model.

But every handoff adds friction. The main agent rephrases the user's question before passing it on, and sometimes rephrases it badly. Above all, it sometimes invents plausible column names ("filter on contract_type = 'Premium'") that the generator takes at face value, when the column is actually called contract_tier and the value is PREMIUM.

The cost of round trips

When a query fails, the error goes back to the main agent, which rephrases and calls the generator again, which rewrites the query, and the database runs it again. Each round adds several seconds of waiting and uses up model calls.

If the error sent back doesn't help the model correct itself, the loop spins for nothing. In one bug we had at a customer, a single question triggered around twenty failed calls in a row: on each column error, we were sending the model the columns of a different table.

That is what pushed us toward the agentic approach. Instead of routing every attempt through the main agent, a data analyst leads the investigation itself, with the real database structure in front of it, and only hands back once it has a result. At the customer mentioned above, we went from nearly three tool calls per answer to just over one.

Maintaining the database description

To write correct SQL quickly, the generator has to know the database: the tables, the columns, and above all what they mean. In a real database, the billed customer column is called cd_cust_2, the status is 1 or 2, and revenue is "net of credit notes".

Usually an administrator writes a description of the database, which is passed to the generator with every question. It works, but it takes a long time to write, and only two or three people in the company know how. Above all, it is hard to maintain: every field added, renamed or removed makes the description wrong, and nobody is told. On a large database, the full description also no longer fits in what you can send the model with each question, so you have to choose what to show.

When the description is wrong or incomplete, the model makes mistakes without knowing it. It writes a valid query on the wrong column, and the answer displayed is wrong, from a model that is perfectly sure of itself. No error comes back, and nobody notices until a user spots a number that looks off.

The fix is to regularly read the structure from the database itself: the actual list of tables and columns, and the comments your teams have sometimes already written there. This dictionary updates when the database changes, and people only fill in what is missing.

Query results that don't fit in the answer

A query that returns 5,000 rows can't be sent to the model as is. You have to store the result separately, show the model only a preview, and let it page through the rest. In our case, the model sees at most 20 rows of the result and reads the rest on demand.

This split creates a very concrete risk: the model calculates on the preview. It is shown 20 rows, counts them, takes an average, and confidently announces a wrong number. You have to explicitly forbid it from calculating on a sample and send it back to the database for any aggregate (COUNT, SUM, AVG on the full table).

Then come user expectations, because nobody wants a raw table in the chat:

  • a readable chart, built from the right dataset;
  • a full Excel export (up to 50,000 rows in our case), not just the visible rows;
  • follow-ups on the same result ("and just for the North region?") without querying the database again for nothing.

Each of these features looks simple. Together, they add up to a small product.

Security: an agent that must only read

The risk with an agent that writes SQL is that it changes your data: by mistake, or because someone manipulates it, with an instruction slipped into a user's question or into content it reads. The Postgres MCP server case shows that a protection that looks solid can give way.

MCP lets you connect a database to Claude, ChatGPT or Cursor in a few lines of configuration. The reference Postgres server wrapped each query in a read-only transaction. Datadog showed in August 2025 that a simple COMMIT; followed by another statement was enough to break out and run any command. The server has since been deprecated and archived.

The lesson applies to every project:

  • read-only access must come from a database account with no write privileges, not from a filter added on top;
  • every query must be validated before it runs: a single statement, no writes, no system tables;
  • the model must not be able to get around these rules, even if a user asks it to.

Access rights: not everyone should see everything

Another issue often discovered late: a sales rep in the South shouldn't see revenue for the North, and a technician has no business reading salaries.

With an MCP server or a homemade script, the agent connects with a single account: every user who talks to it sees everything that account can see. Restricting by user means knowing who is asking the question, passing that identity through to the query, and filtering accordingly. It can be done, but it is a full architecture component in its own right, and it touches your application's authentication.

Building it yourself: what your IT team will have to maintain

If you want to build it yourself, Vanna is one of the leading open-source text-to-SQL libraries. Version 2.0, under the MIT license, was rewritten around an agent, with per-user permissions and output as tables and charts.

But the preparation is still up to you: to get correct answers, you have to "train" it with the database structure, business documentation, and example questions paired with the right SQL query. You also have to host it, integrate it with your authentication, connect it to your documents, and maintain it every time the database or the models change. It is a good starting point, provided you have a team for it over the long term.

Because the initial development is only the beginning. Once the agent is in production, someone on your teams will have to keep:

  • tracking the schema: every table added or column renamed has to reach the description, or the agent gives wrong answers;
  • tracking the models: providers release new versions every few months and retire old ones, and changing models can change how the agent writes its SQL;
  • monitoring errors: reviewing failed queries and disputed answers, working out why, fixing them;
  • rerunning a set of reference questions after each change, to check that nothing has regressed;
  • keeping the guardrails up to date: read-only account, query validation, per-user permissions.

One example: in mid-October, a provider changed overnight how one of its models complied with an enforced response format, and one of our components had to move to another provider. This is our job, so we handle it. In an IT department, your teams will spend more time maintaining an AI system than innovating on your core business, and that time almost never appears in the project budget.

Deploying without development: Ask This Guy

We built what we would have wanted to find: it is the agent in the video at the top of this article. A database connects without development, in a few minutes, and each pitfall described above has its answer:

  • On connection, the agent reads the tables, views and columns, and picks up the comments already in the database. Your teams only clarify the obscure codes ("cd_cust_2 is the billed customer"), without writing documentation, and the dictionary follows changes to the database.
  • In agentic mode, it investigates in several steps: it looks up what the question means, reads the relevant columns, checks the values, then runs its queries, within fixed limits (45 seconds, six queries at most). Each step is displayed in the conversation.
  • It only reads: read-only account, one statement per query, system tables refused.
  • Its results stay usable: datasets kept in the conversation, charts, Excel export.
  • The same agent searches your documents (SharePoint, Notion, websites) and queries your databases in the same answer.

Maintenance is on our side: tracking models, guardrails, product updates. Your teams focus on the business questions.

If you have a project where an agent needs access to your data, book a meeting: in a few clicks, we set up the agent on your own data, and you see right away whether it is the right approach. For the full picture, see our Talk to Data page and the article Your databases are a gold mine.

Frequently asked questions about text-to-SQL

What is text-to-SQL?

Text-to-SQL means translating a question asked in natural language into a SQL query, using a large language model (LLM). The query runs on the database and the result is turned into an answer. It is the technique that lets people "talk to their data" without knowing SQL.

Why does a text-to-SQL agent give wrong answers?

Most often because it doesn't understand the database: obscure column names, unexplained codes, a table description that is incomplete or out of date. The model then writes a valid query on the wrong column, and the answer is wrong without any error showing. Calculating a total from a mere preview of the result is the other common cause.

Is a Postgres MCP server enough for enterprise use?

For exploring your own data, yes. For dozens of employees, the essentials are missing: read-only access guaranteed by an account with no write privileges, per-user permissions, a business understanding of the database, handling of large results, and the ability to combine data with documents.

Should you build a text-to-SQL agent or use an existing solution?

Building makes sense if you have a team to maintain the engine, the database description, the guardrails and the interface over the long term. Expect months to make the agent reliable, then ongoing maintenance that ties up developers instead of leaving them free to work on your core business. If your questions span several databases and your documents, or you want results within days, an existing solution saves you from rediscovering the pitfalls of production one by one.


If you are starting the project yourself, two things come before the first prompt: create a read-only database account, and list the columns nobody on the team can explain. The account protects you, and the length of the list tells you how much description work lies ahead.

Partager :

Related Articles

Enterprise AI agents: use cases and real costsGuide

Enterprise AI agents: use cases and real costs

Enterprise AI agents: the definition, what an agent can really do, the method that gets it into production, and what it actually costs.

SaaS chatbot: product support, data, and AI actionsGuide

SaaS chatbot: product support, data, and AI actions

A chatbot built into a SaaS product cuts tickets, limits churn, and surfaces upsell opportunities. Product support, data, and actions: a guide by maturity level.

Data analysis tools: which family for which need in 2026?Guide

Data analysis tools: which family for which need in 2026?

Excel, Power BI, Python, conversational AI: a comparison of data analysis tool families to help you pick the right one for your needs.

6 min

Interested in our solutions?

Discover how Ask This Guy can help you accelerate with AI

Book a Demo