Quickstart
Get KavachOS running in five minutes.
Your first agent
Install
pnpm add kavachosnpm install kavachosyarn add kavachosCreate 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:
| Type | When to use |
|---|---|
autonomous | Runs without human involvement. Default for most agents. |
delegated | Receives permissions from another agent via a delegation chain. |
service | Long-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 entryIf 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' });