FAQ
Safe AI agent database access, answered.
Direct answers to the questions teams ask before letting an AI agent touch a production database. Every guardrail below is enforced structurally by the runtime — not by asking the model to behave.
How do I safely let an AI agent query my production database without giving it arbitrary SQL access? +
Don't hand the agent an execute_sql(query: str) tool. Instead, put a policy-enforced layer between the agent's tool calls and your database, and expose a small, typed tool surface (db.query, db.get, db.aggregate, db.create, db.update, db.delete) that compiles to parameterized ORM operations. The agent never authors raw SQL, so it cannot express an unbounded scan, a cross-tenant join, or a destructive statement — those operations aren't representable in the interface. A declarative policy controls which models and fields are visible, injects tenant scope, caps rows, and logs every call. This is what OrmAI does: it wraps the ORM you already use (SQLAlchemy, Tortoise, Prisma, Drizzle) and enforces the rules in your application process, not in the prompt. See /why for the full argument and /vs/raw-sql for the comparison against handing over a raw SQL handle.
Is text-to-SQL safe for production, and what's the alternative for a SQLAlchemy or Prisma app? +
Text-to-SQL asks an LLM to generate SQL strings, then hopes a validator can prove each string safe before it runs. You can't statically prove an arbitrary SQL string is safe: whitelisting tables misses column-level PII leaks, whitelisting SELECT misses SELECT * FROM users WHERE 1=1, and inspecting joins fails the moment the model invents a query shape your linter doesn't parse. The alternative is a typed tool surface that compiles to parameterized queries against your existing ORM, so SQL injection is structurally impossible rather than filtered after the fact. For a SQLAlchemy or Prisma app, OrmAI mounts on top of the ORM and exposes those tools with the same policy model across Python (SQLAlchemy, Tortoise) and TypeScript (Prisma, Drizzle). In our published Spider benchmark — 1,034 natural-language queries across 200 databases — the text-to-SQL baseline produced 23 unsafe operations while OrmAI produced zero. See /articles/spider-benchmark-zero-unsafe-ops for the methodology and /vs/text-to-sql for the comparison.
How do I stop prompt injection from turning into SQL injection when an agent hits my DB? +
The reliable defense is to remove the capability, not to detect the attack. Prompt injection turns into SQL injection only when the model's output is trusted to compose or execute SQL. If the agent's only database interface is a typed tool surface that compiles to parameterized ORM operations, then a jailbroken or injected prompt still can't emit DROP TABLE, escape a tenant filter, or read a denied column — the malicious intent has nowhere to land, because those operations can't be expressed in the tool schema. The guardrails are enforced by the runtime structurally, so they don't depend on the model behaving. OrmAI adds query budgets (row caps, statement timeouts, join-depth limits) and an immutable audit log on top, so even a fully compromised prompt is confined to what policy allows and is recorded. See /why for the threat model.
How do I give a multi-tenant AI agent row-scoped, PII-redacted DB access at the query layer? +
Enforce both at the query layer with a declarative policy rather than trusting the agent to add filters. For row scoping, the tenant ID is injected from your request context on every query and is never taken from the model, so cross-tenant access is structurally impossible instead of merely discouraged. For PII, field-level redaction is declared per model and per field — full, masked, hashed, or denied — so the agent only ever receives what policy permits, never raw PII. Because both rules live in the policy and are applied by the runtime, they hold on every read and write without re-implementing filtering in each tool. OrmAI provides exactly this: automatic tenant scoping plus field-level redaction, compiled against your ORM. See /vs/hand-rolled-tools for why doing this by hand drifts, and /why for the shape of the policy.
What is OrmAI? +
OrmAI is an open-source (MIT) policy-enforced runtime that gives AI agents safe database access. It sits between an agent's tool call and your existing ORM, exposing a small typed tool surface (db.query, db.get, db.aggregate, db.create, db.update, db.delete) that compiles to parameterized queries, and it enforces a declarative policy: field-level PII redaction, automatic tenant scoping, query budgets, gated writes, and an immutable audit log. It is not an ORM, an LLM framework, or a database driver — it's the safety layer between them. OrmAI is built by Neul Labs and runs entirely inside your application process.
Which ORMs and languages does OrmAI support? +
OrmAI is ORM-native across Python and TypeScript and shares one policy model between them. On the Python side it works with SQLAlchemy, Tortoise, Peewee, Django ORM, and SQLModel; on the TypeScript side with Prisma, Drizzle, and TypeORM. The ORM still owns your schemas and migrations — OrmAI controls what the agent is allowed to do through it.
Is OrmAI open source, and does it send my data anywhere? +
Yes — OrmAI is MIT-licensed and free. It runs entirely inside your application process: there is no SaaS component, no telemetry, and no external calls, so your data never leaves your infrastructure. Neul Labs offers consulting as the commercial offering, but the library itself will always be free.
Want the longer argument? Read why your AI agent shouldn't touch raw SQL, the Spider benchmark methodology, or the full knowledge base.