kavachOS

Prisma adapter

Use PrismaClient as the KavachOS database backend.

KavachOS ships a Drizzle-based database layer by default. If your project already uses Prisma, the @kavachos/prisma adapter lets you query every KavachOS table through your existing PrismaClient — no Drizzle installation required.

The Prisma adapter is a standalone query layer. It does not replace or wrap the core KavachOS instance. Use it to read and write KavachOS data from the parts of your codebase that already work with Prisma.

When to use it

  • You have an existing Prisma project and want to avoid running two ORM clients.
  • You need to query KavachOS tables inside Prisma transactions that span your own models.
  • You prefer generated Prisma types over Drizzle's schema for editor autocomplete.
  • Your team finds Prisma's DSL easier to maintain than raw SQL DDL.

The adapter covers agents, users, sessions, audit logs, permissions, delegation chains, OAuth, API keys, organizations, trust scores, approval requests, and every other KavachOS table.

Installation

pnpm add @kavachos/prisma @prisma/client

The adapter has no runtime dependency on kavachos itself — @prisma/client is the only peer dep.

Setup

Add the KavachOS models to your Prisma schema

Copy the models from node_modules/@kavachos/prisma/src/schema.prisma into your prisma/schema.prisma, or use it as a reference to add only the tables you need.

The schema targets Postgres by default. Switch the datasource provider to sqlite or mysql as appropriate.

// prisma/schema.prisma
generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

// ... your existing models ...

model KavachUser {
  id                 String    @id
  email              String    @unique
  name               String?
  banned             Boolean   @default(false)
  createdAt          DateTime  @map("created_at")
  updatedAt          DateTime  @map("updated_at")
  // ... (see full schema in @kavachos/prisma/src/schema.prisma)

  @@map("kavach_users")
}

model KavachAgent {
  id          String    @id
  ownerId     String    @map("owner_id")
  name        String
  type        String
  status      String    @default("active")
  tokenHash   String    @map("token_hash")
  tokenPrefix String    @map("token_prefix")
  expiresAt   DateTime? @map("expires_at")
  createdAt   DateTime  @map("created_at")
  updatedAt   DateTime  @map("updated_at")

  @@map("kavach_agents")
}

// ... add remaining models from schema.prisma ...

Run migrations

npx prisma migrate dev --name add-kavachos

Or push to an existing database without a migration file:

npx prisma db push

Create the adapter

import { PrismaClient } from '@prisma/client';
import { createPrismaAdapter } from '@kavachos/prisma';

const prisma = new PrismaClient();
export const kavachDb = createPrismaAdapter(prisma);

Usage

Agent operations

import { kavachDb } from './lib/kavach-db';

// Look up an agent by ID
const agent = await kavachDb.findAgentById('agent-123');

// Look up by token hash (for auth middleware)
const agent = await kavachDb.findAgentByTokenHash(tokenHash);

// List all active agents owned by a user
const agents = await kavachDb.listAgents({
  ownerId: 'user-456',
  status: 'active',
});

// Create an agent
const agent = await kavachDb.createAgent({
  id: crypto.randomUUID(),
  ownerId: 'user-456',
  name: 'my-agent',
  type: 'autonomous',
  tokenHash: hash,
  tokenPrefix: prefix,
  createdAt: new Date(),
  updatedAt: new Date(),
});

// Revoke an agent
await kavachDb.updateAgent('agent-123', { status: 'revoked' });

User operations

// Find by email (for sign-in)
const user = await kavachDb.findUserByEmail('alice@example.com');

// Create a user
const user = await kavachDb.createUser({
  id: crypto.randomUUID(),
  email: 'alice@example.com',
  name: 'Alice',
  createdAt: new Date(),
  updatedAt: new Date(),
});

// Update user (e.g., link Stripe customer)
await kavachDb.updateUser(userId, {
  stripeCustomerId: 'cus_abc123',
});

Session management

// Create a session
const session = await kavachDb.createSession({
  id: crypto.randomUUID(),
  userId: 'user-456',
  expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
  createdAt: new Date(),
});

// Validate a session
const session = await kavachDb.findSessionById(sessionId);
if (!session || session.expiresAt < new Date()) {
  throw new Error('Session expired');
}

// Clean up expired sessions
const deleted = await kavachDb.deleteExpiredSessions();

Audit log queries

// Query recent actions for an agent
const logs = await kavachDb.queryAuditLogs({
  agentId: 'agent-123',
  since: new Date(Date.now() - 24 * 60 * 60 * 1000),
  limit: 50,
});

// Query denied actions for investigation
const denials = await kavachDb.queryAuditLogs({
  userId: 'user-456',
  result: 'denied',
  since: new Date('2025-01-01'),
});

// Write an audit log entry
await kavachDb.createAuditLog({
  id: crypto.randomUUID(),
  agentId: 'agent-123',
  userId: 'user-456',
  action: 'execute',
  resource: 'mcp:github:create_issue',
  result: 'allowed',
  durationMs: 42,
  timestamp: new Date(),
});

Permissions

// Get all permissions for an agent
const perms = await kavachDb.findPermissionsByAgentId('agent-123');

// Grant a permission
await kavachDb.createPermission({
  id: crypto.randomUUID(),
  agentId: 'agent-123',
  resource: 'mcp:github:*',
  actions: ['read', 'write'],
  createdAt: new Date(),
});

// Revoke all permissions for an agent
await kavachDb.deletePermissionsByAgentId('agent-123');

Transactions

The adapter wraps Prisma's $transaction to let you compose KavachOS operations with your own Prisma queries:

import { PrismaClient } from '@prisma/client';
import { createPrismaAdapter } from '@kavachos/prisma';

const prisma = new PrismaClient();
const kavachDb = createPrismaAdapter(prisma);

// KavachOS operations inside a transaction
await kavachDb.transaction(async (tx) => {
  const agent = await tx.createAgent({ ... });
  await tx.createPermission({ agentId: agent.id, ... });
});

// Mix with your own Prisma models
await prisma.$transaction(async (tx) => {
  const kavach = createPrismaAdapter(tx);
  await kavach.createAgent({ ... });
  // Your own model:
  await tx.subscription.create({ data: { ... } });
});

Trust scores

// Get the trust score for an agent
const trust = await kavachDb.findTrustScore('agent-123');
console.log(trust?.level); // "trusted" | "limited" | ...

// Upsert after recomputing
await kavachDb.upsertTrustScore({
  agentId: 'agent-123',
  score: 85,
  level: 'trusted',
  factors: { successRate: 0.99, age: 30 },
  computedAt: new Date(),
});

Approval requests

// List pending approvals for a human to review
const pending = await kavachDb.listPendingApprovals('agent-123');

// Approve a request
await kavachDb.updateApprovalRequest(requestId, {
  status: 'approved',
  respondedAt: new Date(),
  respondedBy: 'user-456',
});

Migration from Drizzle

If you started with the built-in Drizzle backend and want to switch to Prisma:

  1. Keep the same table names — all KavachOS tables use the kavach_ prefix and the same column names in both Drizzle and Prisma.
  2. Run npx prisma introspect against your existing database to generate a Prisma schema from the Drizzle-created tables.
  3. Replace calls to the Drizzle db directly with createPrismaAdapter(prisma).
  4. Set database.skipMigrations: true in createKavach(...) if the core KavachOS instance is still used for other features (agents, MCP, etc.), so Drizzle does not conflict with Prisma.
const kavach = await createKavach({
  database: {
    provider: 'postgres',
    url: process.env.DATABASE_URL,
    skipMigrations: true, // Prisma owns the schema now
  },
});

// Use the Prisma adapter for direct table access
const db = createPrismaAdapter(prisma);

The core KavachOS instance (createKavach) still uses Drizzle internally for agent creation, authorization, MCP flows, and other built-in features. @kavachos/prisma gives you a Prisma-native way to read and write the same tables — it does not replace createKavach.

Reference schema

The full reference schema is in node_modules/@kavachos/prisma/src/schema.prisma. It includes all 30+ KavachOS models with correct column mappings, indexes, and default values.

Every model name follows KavachPascalCase and maps to a kavach_snake_case table, keeping your Prisma namespace clean and your SQL tables clearly scoped.

On this page