Give your AI agents database access without the risk.
OrmAI wraps your existing ORM models in a policy-enforced runtime. Your agents get typed tools for querying and writing data — while you keep control over what they can see and do. No raw SQL. No prompt injection into your database. Just safe, auditable, tenant-scoped database tools.
Available for Python and TypeScript/Node.js.
Why OrmAI?
Building AI agents that interact with your database? You have probably thought about:
- "What if the agent reads sensitive data?" → Field-level policies hide or mask PII automatically.
- "What if it runs wild queries?" → Query budgets and row limits prevent runaway costs.
- "How do I audit what it did?" → Every operation is logged with full context.
- "What about multi-tenant isolation?" → Tenant scoping is built-in, not bolted on.
- "Which ORM do we use?" → Works with SQLAlchemy, Prisma, Drizzle, TypeORM, Tortoise, Django, SQLModel, and Peewee.
OrmAI solves these at the ORM layer — not the prompt layer.
Pick Your Stack
| Python | TypeScript / Node.js | |
|---|---|---|
| Package | pip install ormai |
npm install @ormai/core |
| ORMs | SQLAlchemy, Tortoise, Django, SQLModel, Peewee | Prisma, Drizzle, TypeORM |
| Integrations | OpenAI, LangChain, LlamaIndex, MCP, FastAPI | Vercel AI SDK, LangChain.js, OpenAI, Anthropic, LlamaIndex.ts, Mastra, MCP |
| Quickstart | ormai.quickstart |
@ormai/utils |
| Docs | Python Guide | TS Guide |
Python Quick Start
# With your ORM of choice pip install ormai[sqlalchemy] # or pip install ormai[prisma]
from ormai.quickstart import mount_sqlalchemy from ormai.utils import DEFAULT_DEV # Your existing SQLAlchemy models + session toolset = mount_sqlalchemy( engine=engine, session_factory=Session, policy=DEFAULT_DEV ) # Done. Your agent now has: db.query, db.get, db.aggregate, db.describe_schema
TypeScript Quick Start
# Core (required) npm install @ormai/core # Choose your ORM adapter npm install @ormai/prisma
import { PrismaClient } from '@prisma/client'; import { PrismaAdapter } from '@ormai/prisma'; import { PolicyBuilder, createContext } from '@ormai/core'; import { createGenericTools } from '@ormai/tools'; const prisma = new PrismaClient(); const adapter = new PrismaAdapter({ prisma }); const schema = await adapter.introspect(); const policy = new PolicyBuilder('prod') .registerModels(['Customer', 'Order']) .tenantScope('tenantId') .denyFields('*password*') .maskFields('*email*') .build(); const tools = createGenericTools({ adapter, policy, schema }); const ctx = createContext({ tenantId: 'tenant-123', userId: 'user-456', db: prisma, roles: ['admin'], }); // Your agent now has safe database tools const result = await tools[0].execute({ model: 'Order', where: [{ field: 'status', op: 'eq', value: 'pending' }], take: 10, }, ctx);
What You Get Out of the Box
| Feature | What It Does |
|---|---|
| Read-safe tools | db.query, db.get, db.aggregate, db.describe_schema — no raw SQL |
| Write-safe tools | db.create, db.update, db.delete, db.bulk_update — gated by policy |
| Field-level policies | Hide passwords, mask emails, deny sensitive columns automatically |
| Tenant scoping | .tenantScope('tenant_id') auto-filters every query per user |
| Query budgets | Max rows, max includes depth, statement timeouts per model |
| Audit logging | Every call logged with principal, tenant, trace ID, input, output |
| Human approval gates | Require reason or approval for writes on sensitive models |
| Schema introspection | Auto-discovers models, fields, relations, primary keys |
| Multi-framework | LangChain, OpenAI, Vercel AI SDK, LlamaIndex, Mastra, FastAPI, MCP |
Architecture
┌─────────────────────────────────────────────────────────────┐
│ Your Agent │
└──────────────────────────┬──────────────────────────────────┘
│ calls tools
┌──────────────────────────▼──────────────────────────────────┐
│ OrmAI Runtime │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐│
│ │ Policy │ │ Audit │ │ Tenant Scope ││
│ │ Enforcer │ │ Logger │ │ Filter ││
│ └─────────────┘ └─────────────┘ └─────────────────────┘│
└──────────────────────────┬──────────────────────────────────┘
│ parameterized queries only
┌──────────────────────────▼──────────────────────────────────┐
│ Your ORM (SQLAlchemy / Prisma / Drizzle / ...) │
└─────────────────────────────────────────────────────────────┘
OrmAI sits between your agent and your ORM. It compiles agent requests into type-safe ORM queries, enforces policies, logs everything, and returns structured results. Your database never sees raw SQL from the agent.
Documentation
docs.neullabs.com/ormai — Full guides, API reference, and examples.
Installation
Python
pip install ormai[sqlalchemy]
pip install ormai[tortoise]
pip install ormai[peewee]
pip install ormai[django]
pip install ormai[sqlmodel]
# Or all adapters
pip install ormai[all]TypeScript / Node.js
# Core (required) npm install @ormai/core # ORM adapters npm install @ormai/prisma npm install @ormai/drizzle npm install @ormai/typeorm # Optional packages npm install @ormai/tools # Generic database tools npm install @ormai/store # Audit logging npm install @ormai/mcp # MCP server npm install @ormai/integrations # Framework adapters npm install @ormai/utils # PolicyBuilder and helpers
Policy Configuration
Python
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() )
TypeScript
import { PolicyBuilder } from '@ormai/core'; const policy = new PolicyBuilder('prod') .registerModels(['Customer', 'Order', 'Product']) .tenantScope('tenantId') .denyFields('*password*') .maskFields('*email*') .allowRelations('Order', ['customer', 'items']) .enableWrites(['Order'], { allowCreate: true, allowUpdate: true, allowDelete: false, maxAffectedRows: 10, }) .defaultBudgetConfig({ maxRows: 100, maxIncludesDepth: 2, statementTimeoutMs: 5000, }) .build();
Presets: DEFAULT_DEV (permissive), DEFAULT_INTERNAL (moderate), DEFAULT_PROD (strict)
Agent Framework Integrations
| Framework | Python Package | TypeScript Package |
|---|---|---|
| OpenAI | ormai |
@ormai/integrations |
| LangChain | ormai |
@ormai/integrations |
| Vercel AI SDK | — | @ormai/integrations |
| LlamaIndex | ormai |
@ormai/integrations |
| Mastra | — | @ormai/integrations |
| Anthropic | — | @ormai/integrations |
| FastAPI | ormai |
— |
| MCP | ormai |
@ormai/mcp |
Supported ORMs
| ORM | Python | TypeScript |
|---|---|---|
| SQLAlchemy | ✅ | — |
| Prisma | — | ✅ |
| Drizzle | — | ✅ |
| TypeORM | — | ✅ |
| SQLModel | ✅ | — |
| Django ORM | ✅ | — |
| Tortoise ORM | ✅ | — |
| Peewee | ✅ | — |
Benchmark: OrmAI vs Text-to-SQL
We benchmarked against the Spider dataset — 1034 natural language queries:
| Metric | OrmAI | Text-to-SQL |
|---|---|---|
| SQL Injection possible | No | Yes |
| Unsafe ops executed | 0 | 23 |
| Full audit trail | Yes | No |
# Try it yourself
pip install ormai[benchmark]
python examples/spider_demo.py run --limit 20Examples
examples/spider_demo.py— Benchmark demoexamples/fastapi-sqlalchemy/— FastAPI + SQLAlchemy integrationormai-ts/— TypeScript monorepo with Prisma, Drizzle, and TypeORM examples
More examples at docs.neullabs.com/ormai/examples.
Contributing
git clone https://github.com/neul-labs/ormai.git cd ormai # Python uv sync --dev uv run pytest # TypeScript cd ormai-ts npm install npm run build npm run test
See contributing guide for development setup and guidelines.