Guide
June 20, 2026
8 min read

How to Give an AI Agent Safe Access to Your Production Database

A layered, database-agnostic approach to giving AI agents production access: static grants plus a runtime control plane that classifies, gates, and records every action.

#AI agents#Database security#Guardrails#Production databases#Postgres

Access is not a one-time grant

When a teammate asks for production database access, you do not just hand over a password. You decide what they can read, what they can change, and which actions need a second pair of eyes. You assume that judgment will be applied continuously, on every action, not approved once and forgotten.

An AI agent breaks that assumption. It does not get tired, it does not pause to reconsider, and it will happily act on whatever it reads, including text that arrives from a ticket, a webpage, or a row in your own database. The question is not whether to give an agent access. For most teams running coding agents, support copilots, and analytics assistants, that decision is already made. The real question is how to grant access so that every action stays inside a boundary you defined, no matter what the agent was told to do.

The honest answer is that no single setting solves this. Safe access is two layers working together: static controls inside the database engine, and a runtime control plane in front of it. This guide walks through both, why each is necessary, and where the line between them sits. The examples use Postgres because it is concrete, but the same model applies to MySQL, MongoDB, and any other engine your agents touch.

Layer one: static controls

Start with what the database already gives you. These are the table stakes, and you should configure all of them before an agent connects.

  • A dedicated, least-privilege role. Never let an agent reuse an application or admin account. Create a role scoped to exactly the schemas and operations it needs. In Postgres, the predefined pg_read_all_data role grants read access without write, which is a reasonable starting point for a read-only agent. (Postgres docs)
  • Read replicas. Point analytics and exploratory agents at a replica so their queries cannot contend with production write traffic or hold locks on hot tables.
  • Row-level security. If an agent should only see a tenant's data, enforce it at the table with CREATE POLICY rather than trusting the agent to add the right WHERE clause. (Postgres docs)
  • Statement timeouts. Set statement_timeout so a runaway query (an agent generating an unbounded join, for example) is aborted by the server instead of saturating it. (Postgres docs)
  • Network and connection allowlists. Restrict which hosts can connect and from where.

This layer is necessary. Skipping it is negligence. But it is not sufficient, and it is worth being precise about why.

What static access cannot do

Static controls operate on identity and permission. They answer "is this role allowed to run this class of statement on this object." They cannot answer the questions that matter most once an autonomous agent is in the loop.

They cannot judge intent. A read-only role allows SELECT * FROM users. That is the same grant whether the agent is counting active accounts or exfiltrating every email address in the table. The grant sees a permitted read. It does not see purpose, and it does not see volume or sensitivity unless you have built something extra to look.

They cannot stop injected instructions. Prompt injection is the top entry in the OWASP Top 10 for LLM Applications, and the reason is structural: an LLM processes instructions and data on the same channel, so untrusted content (a support ticket, a scraped page, a comment field) can be interpreted as a command. (OWASP) A read-only grant survives that attack, but the moment the agent has any write ability, an injected "now delete the stale records" can ride straight through a valid permission. We unpack this failure mode in detail in read-only is not enough.

And they cannot avoid the eventual write. Read-only is a comfortable place to start, but it is rarely where teams stay. The point of an agent is usually to fix something: apply a migration, backfill a column, drop an unused index. The instant you grant write or DDL, the static layer's protection drops to "this role is allowed to do this," which is exactly the protection that injected or simply mistaken instructions can abuse.

Layer two: a runtime control plane

The gap is everything that happens between "the agent decided to act" and "the engine executed it." Static permissions check identity at that boundary. What you also need is a layer that inspects the actual action, in context, every time, and decides whether it proceeds.

That layer is a runtime control plane: a checkpoint that sits in the data path, in front of the database, and intercepts each statement or operation before it reaches the engine. Because it lives in the connection path rather than inside the model, it sees the real query the agent is about to run, not the agent's stated plan. It is engine-agnostic by design. The same plane governs a Postgres UPDATE, a MySQL ALTER TABLE, and a MongoDB deleteMany, because it reasons about the operation rather than depending on one vendor's permission model.

The four jobs of the control plane

A control plane worth deploying does four things on every action.

  1. Classify. Parse the incoming operation and label it: read or write, DDL or DML, which objects, how much data is in scope, whether it touches anything tagged sensitive. Classification is what turns an opaque statement into something a policy can reason about.
  2. Enforce a default-deny policy. Start from deny and allow specific, named operations. This inverts the usual posture. Instead of blocking the dangerous things you thought of, you permit only the things you explicitly sanctioned, and everything novel is stopped by default.
  3. Gate risky actions behind human approval. Some operations should never run autonomously. Schema changes, bulk deletes, anything touching financial or personal data: these pause and wait for a person. OWASP's guidance for LLM and agentic systems repeatedly lands on the same control, requiring human approval for high-risk operations. (OWASP) We cover how to design that gate without grinding work to a halt in human-in-the-loop database migrations.
  4. Record immutably. Every action, every decision (allowed, denied, approved by whom), written to an append-only log. This is what lets you answer "what did the agent do, and who said yes" after the fact, and it is the subject of audit trails as an immutable ledger.

Why enforcement must live outside the agent's context

This is the part that is easy to get wrong. A natural instinct is to put the rules in the prompt: "you may only run SELECT statements, never DELETE without confirmation." That is a guideline, not a guardrail.

Instruction-based guardrails fail for the same reason prompt injection works. They live in the same context window as the untrusted input, so a crafted instruction can talk the model out of them, and even without an attacker, a model can simply reason its way around a rule it was given. A guardrail the agent can read is a guardrail the agent can ignore.

Enforcement in the data path cannot be argued with. The control plane is not a participant in the conversation. It does not read the agent's reasoning, and the agent cannot send it a message. The agent emits a query, the plane classifies and checks it against policy, and an injected "ignore your previous instructions" never reaches the component making the decision. That separation, keeping the enforcer out of the context the agent and its inputs can influence, is the whole point.

A concrete Postgres walkthrough

Picture a coding agent assigned to fix a slow endpoint. It connects through the control plane, not directly to the database.

  • The agent runs EXPLAIN and several SELECTs to find the slow query. Each is classified as a read, matches an allowed rule, runs, and is logged.
  • It decides the fix is a new index and issues CREATE INDEX CONCURRENTLY. The plane classifies this as DDL, a category default-deny does not auto-allow. The action pauses and a request lands in your approval channel with the exact statement, the target table, and the agent's stated reason.
  • An engineer approves. The index builds. The approval, the approver, and the timestamp are written to the immutable log alongside the statement.
  • Later, a poisoned comment in a Jira ticket tries to steer the agent into DROP TABLE audit_log. The agent, misled, emits the statement. The plane classifies it as a destructive DDL on a protected object and denies it outright. The attempt is recorded. Nothing is dropped.

Swap Postgres for MySQL and the DDL is an ALTER TABLE; swap in MongoDB and the destructive call is a dropCollection. The classify, enforce, gate, record loop is identical. That engine-independence is the reason a control plane scales across a real fleet of databases instead of needing a bespoke ruleset per engine.

Checklist: from a read-only grant to a governed path

Use this to move from the bare minimum to a genuinely governed access path.

  • [ ] Dedicated least-privilege role per agent, never a shared or admin account
  • [ ] Read traffic pointed at a replica where possible
  • [ ] Row-level security for any tenant or sensitivity boundary
  • [ ] Statement timeouts and connection allowlists configured
  • [ ] All agent traffic routed through a runtime control plane, not direct connections
  • [ ] Every operation classified before it reaches the engine
  • [ ] Default-deny policy: explicit allows, everything else blocked
  • [ ] Human approval required for DDL, bulk writes, and sensitive-data access
  • [ ] Immutable audit log of every action and approval decision
  • [ ] Enforcement outside the agent's context, so it survives prompt injection

The first four lines are the database doing its job. The rest is the control plane doing what the engine cannot. You need both.

Where Datapace fits

Datapace is the runtime control plane for AI agents working on production databases. It sits in the data path across Postgres, MySQL, MongoDB, and more, classifying every action, enforcing default-deny policy, gating risky operations behind human approval, and recording everything in an immutable audit log, all outside the agent's context so the controls hold even under prompt injection. If you are giving an agent production access, see the safe AI database access use case or compare approaches, and when you are ready to design your access path, book a call.

Sources

Frequently asked questions

Is a read-only database user enough to make an AI agent safe?
No. A read-only role prevents writes, but it cannot judge intent or data volume, so it does not stop an agent from reading and exfiltrating sensitive data through otherwise valid queries. It also offers no protection once you grant any write or schema access, which most useful agents eventually need. Read-only is a sound starting point, not a complete safety boundary.
Why can't I just tell the agent in its prompt not to run dangerous queries?
Instructions in the prompt share the same context window as untrusted input, so a prompt injection or even the model's own reasoning can override them. Prompt injection is the top risk in the OWASP Top 10 for LLM Applications precisely because models cannot reliably separate trusted instructions from injected ones. Enforcement has to live outside the agent's context, in the data path, where the agent cannot argue with it.
Does a runtime control plane work across different databases like MySQL and MongoDB?
Yes. A control plane sits in front of the engine and reasons about the operation itself, such as whether it is a read, a write, or a destructive schema change, rather than depending on one vendor's permission model. The same classify, enforce, gate, and record loop applies whether the action is a Postgres UPDATE, a MySQL ALTER TABLE, or a MongoDB dropCollection.
Which agent actions should require human approval?
Operations that are irreversible or high-impact: schema changes (DDL), bulk deletes and updates, and anything touching financial or personal data. OWASP guidance for LLM and agentic systems consistently recommends a human-in-the-loop gate before high-risk actions. A default-deny policy makes this practical by auto-allowing only routine, low-risk operations and pausing the rest for review.

Keep reading

Ready to let agents touch production, safely?

Bring a use case. We will show you what agents can do on your live data, inside your guardrails.