Quickstart

Get KavachOS running in five minutes.

Your first agent

Install

pnpm add kavachos
npm install kavachos
yarn add kavachos

Create an instance

Pass a database config to createKavach. Use SQLite for local development and Postgres in production.

import { createKavach } from 'kavachos';

const kavach = createKavach({
  database: { provider: 'sqlite', url: 'kavach.db' },
  agents: {
    enabled: true,
    maxPerUser: 10,
    auditAll: true,    // record every authorize() call
    tokenExpiry: '24h',
  },
});

For in-memory storage (useful in tests), pass url: ':memory:' instead.

Create an agent

An agent always has an owner: the user ID from your existing auth system. KavachOS does not manage human authentication.

const agent = await kavach.agent.create({
  ownerId: 'user-123',          // from your auth provider
  name: 'github-reader',
  type: 'autonomous',
  permissions: [
    {
      resource: 'mcp:github:*',
      actions: ['read'],
    },
    {
      resource: 'mcp:deploy:production',
      actions: ['execute'],
      constraints: {
        requireApproval: true,   // human-in-the-loop gate
        maxCallsPerHour: 5,
      },
    },
  ],
});

// agent.token is the bearer token: "kv_..."
console.log(agent.token);

The token is shown exactly once, at creation time. Store it immediately in your secrets manager or pass it directly to the agent. It cannot be recovered after this point — only rotated.

There are three agent types:

TypeWhen to use
autonomousRuns without human involvement. Default for most agents.
delegatedReceives permissions from another agent via a delegation chain.
serviceLong-lived service account identity.

Authorize an action

Call kavach.authorize before any sensitive operation. It returns { allowed, reason?, auditId }.

const result = await kavach.authorize(agent.id, {
  action: 'read',
  resource: 'mcp:github:repos',
});

if (!result.allowed) {
  throw new Error(`Denied: ${result.reason}`);
}

// result.auditId links this decision to its audit log entry

If you only have the raw bearer token (from an incoming HTTP request, for example), use authorizeByToken instead:

const result = await kavach.authorizeByToken(bearerToken, {
  action: 'read',
  resource: 'mcp:github:repos',
});

Check the audit trail

Every authorization decision is logged. Query by agent, filter by result, or export for compliance.

// All decisions for an agent
const logs = await kavach.audit.query({ agentId: agent.id });

// Only the denials
const denied = await kavach.audit.query({
  agentId: agent.id,
  result: 'denied',
});

// Export everything as CSV
const csv = await kavach.audit.export({ format: 'csv' });

Delegation

An orchestrator agent can delegate a subset of its permissions to a sub-agent. The delegation has its own expiry and a maxDepth to prevent unbounded chains.

const sub = await kavach.agent.create({
  ownerId: 'user-123',
  name: 'sub-reader',
  type: 'delegated',
  permissions: [],  // starts empty; receives permissions via delegation
});

await kavach.delegate({
  fromAgent: agent.id,
  toAgent: sub.id,
  permissions: [{ resource: 'mcp:github:issues', actions: ['read'] }],
  expiresAt: new Date(Date.now() + 3_600_000),  // 1 hour
  maxDepth: 2,
});

// Resolves the full effective permission set, including delegated ones
const perms = await kavach.delegation.getEffectivePermissions(sub.id);

An agent cannot delegate permissions it does not hold itself. Attempts to escalate are rejected at the point of delegation, not at authorization time.

Full working example

A self-contained script covering agent creation, authorization by ID and token, token rotation, delegation, and audit export.

import { createKavach } from 'kavachos';

const kavach = createKavach({
  database: { provider: 'sqlite', url: ':memory:' },
  agents: { enabled: true, maxPerUser: 10, auditAll: true, tokenExpiry: '24h' },
});

// Create an agent with wildcard read on github resources
const agent = await kavach.agent.create({
  ownerId: 'user-123',
  name: 'github-reader',
  type: 'autonomous',
  permissions: [
    { resource: 'mcp:github:*', actions: ['read'] },
    { resource: 'mcp:github:issues', actions: ['read', 'comment'] },
  ],
});

// Allowed: mcp:github:repos matches mcp:github:*
const r1 = await kavach.authorize(agent.id, {
  action: 'read',
  resource: 'mcp:github:repos',
});
console.log(r1.allowed);  // true

// Denied: no write permission
const r2 = await kavach.authorize(agent.id, {
  action: 'write',
  resource: 'mcp:github:repos',
});
console.log(r2.allowed);  // false

// Authorize using the raw bearer token
const r3 = await kavach.authorizeByToken(agent.token, {
  action: 'read',
  resource: 'mcp:github:issues',
});
console.log(r3.allowed);  // true

// Rotate: old token is immediately invalid
const rotated = await kavach.agent.rotate(agent.id);
console.log(rotated.token);  // new kv_... token

// Delegate a subset to a sub-agent
const sub = await kavach.agent.create({
  ownerId: 'user-123',
  name: 'sub-reader',
  type: 'delegated',
  permissions: [],
});

await kavach.delegate({
  fromAgent: agent.id,
  toAgent: sub.id,
  permissions: [{ resource: 'mcp:github:issues', actions: ['read'] }],
  expiresAt: new Date(Date.now() + 3_600_000),
  maxDepth: 2,
});

const perms = await kavach.delegation.getEffectivePermissions(sub.id);
console.log(perms);
// [{ resource: 'mcp:github:issues', actions: ['read'] }]

// Export the full audit trail
const csv = await kavach.audit.export({ format: 'csv' });

On this page