OrmAI
NEW Spider benchmark — 0 unsafe ops vs. 23 for text-to-SQL

Safe database access for AI agents.

A policy-enforced runtime on top of your ORM. Redaction, tenant scoping, query budgets, and audit logs — built in.

$ uv add ormai[sqlalchemy]

MIT licensed · Python & TypeScript · v0.2.0 (beta)

from ormai.quickstart import mount_sqlalchemy
from ormai.utils import PolicyBuilder, DEFAULT_PROD

policy = (
    PolicyBuilder(DEFAULT_PROD)
    .register_models([Customer, Order])
    .deny_fields("*password*", "*secret*", "*token*")
    .mask_fields(["email", "phone"])
    .tenant_scope("tenant_id")
    .enable_writes(models=["Order"], require_reason=True)
    .build()
)

toolset = mount_sqlalchemy(engine=engine, session_factory=Session, policy=policy)
# Your agent now has db.query, db.get, db.aggregate — safely.

One policy, every tool. No raw SQL ever leaves the policy boundary.

Built for production agents

Six hard problems, solved on day one.

Most teams reinvent these poorly. OrmAI gives you the same primitives that real-world security teams demand from data infrastructure — declaratively.

🛡️

Field-level redaction

Mask, hash, or deny sensitive columns. Agents see what policy allows — never raw PII.

🏢

Automatic tenant scoping

Every query is filtered by tenant_id by default. Cross-tenant access becomes structurally impossible.

⏱️

Query budgets & timeouts

Row caps, statement timeouts, and join-depth limits keep runaway agents from melting your DB.

📜

Immutable audit log

Every read and write is logged with principal, tenant, trace ID, sanitized inputs, and policy decisions.

✍️

Gated writes

Approve which models can be mutated, require a reason on writes, and cap rows-per-statement.

🔌

Works with your ORM

SQLAlchemy, Tortoise, Peewee, Django, SQLModel — and Prisma, Drizzle, TypeORM on the TS side.

Side-by-side

Raw SQL gives the agent a loaded gun.

OrmAI gives it a curated, typed toolbox — same expressiveness, none of the foot-guns.

LLM tool: execute_sql(query)
# The model can write any SQL it wants
def execute_sql(query: str) -> list[dict]:
    return db.execute(query).fetchall()

# Hope nobody ever asks it to:
#   "show me all rows in users WHERE 1=1"
#   "DROP TABLE invoices"
#   "show all rows where tenant_id != 42"
LLM tool: db.query(model, where, ...)
# The agent calls a typed, policy-checked tool
result = await toolset.execute("db.query", {
    "model": "Order",
    "where": {"status": "pending"},
    "limit": 50,
}, ctx=run_ctx)

# Policy enforced automatically:
#  • tenant_id auto-injected from RunContext
#  • forbidden columns redacted in response
#  • row limit capped at policy max
#  • full audit row written before return

Benchmark

1,034 natural-language queries.
Zero unsafe operations.

We replayed the entire Spider text-to-SQL benchmark through OrmAI. The result: 0 SQL injections, 0 unscoped queries, 0 destructive operations. The text-to-SQL baseline produced 23.

Read the methodology →
OrmAI
0
unsafe ops
Text-to-SQL
23
unsafe ops

Plays well with

SQLAlchemyPrismaDrizzleTortoisePeeweeDjango ORMTypeORMFastAPILangGraphVercel AI SDKAnthropic SDKMCP

FAQ

Frequently asked.

Is OrmAI an ORM? +

No. OrmAI is a policy-enforced runtime layer that wraps the ORM you already use (SQLAlchemy, Prisma, Drizzle, etc.). The ORM still owns schemas and migrations; OrmAI controls what your AI agent can do with it.

How is this different from text-to-SQL? +

Text-to-SQL asks the LLM to generate SQL strings. OrmAI exposes a small, typed tool surface (db.query, db.get, db.aggregate, db.create, db.update, db.delete) that compiles to parameterized ORM operations. SQL injection is structurally impossible. Our Spider benchmark recorded zero unsafe operations vs. 23 for a text-to-SQL baseline.

Will it slow my agent down? +

Policy evaluation is in-process and adds well under a millisecond per call. Query budgets are checked at compile time — they reject expensive queries before they hit the database, which usually makes agents faster.

Is it production ready? +

OrmAI is in beta (v0.2.0) and is in production at Neul Labs and partner companies. v0.2 added rate limiting, health checks, structured logging, and audit retention.

What languages are supported? +

Python (SQLAlchemy, Tortoise, Peewee, Django, SQLModel) and TypeScript (Prisma, Drizzle, TypeORM). Both share the same policy model.

Does OrmAI store my data? +

Never. OrmAI runs entirely inside your application process. There is no SaaS component, no telemetry, no external calls.