> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kavachos.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Install KavachOS, create your first AgentIdentity, and run an authorization check. Scaffold a full Next.js SaaS app with create-kavachos-app in one command.

<Columns cols={2}>
  <div>
    Two paths. Pick whichever fits your day.

    <CardGroup cols={1}>
      <Card title="Start from a template" icon="wand-magic-sparkles" href="#start-from-a-template">
        One command, a running Next.js SaaS, KavachOS wired up.
      </Card>

      <Card title="Add to an existing app" icon="screwdriver-wrench" href="#your-first-agent">
        Install, create, authorize, audit. Six steps.
      </Card>
    </CardGroup>
  </div>

  ```bash theme={"system"}
  pnpm create kavachos-app my-app
  cd my-app && pnpm install && pnpm db:push && pnpm dev
  ```
</Columns>

## Start from a template

The fastest path is the scaffolder. One command, three prompts, a running Next.js SaaS with KavachOS wired up.

<Tabs>
  <Tab title="pnpm">
    ```bash title="terminal" theme={"system"}
    pnpm create kavachos-app
    ```
  </Tab>

  <Tab title="npm">
    ```bash title="terminal" theme={"system"}
    npm create kavachos-app
    ```
  </Tab>

  <Tab title="yarn">
    ```bash title="terminal" theme={"system"}
    yarn create kavachos-app
    ```
  </Tab>

  <Tab title="bun">
    ```bash title="terminal" theme={"system"}
    bun create kavachos-app
    ```
  </Tab>
</Tabs>

The CLI asks for a directory, a template, a package manager, and a database driver. Only the Next.js SaaS template is shipping today; the Hono MCP and Expo templates print a coming-soon note and exit. Placeholders in the template (`__APP_NAME__`, `__DB_DRIVER__`, `__DB_URL__`) are replaced on copy.

Next steps are printed at the end: `cd`, install, `db:push`, `dev`.

Prefer to wire up an existing app? Keep reading.

## Your first agent

<Steps>
  <Step>
    ### Install

    <Tabs>
      <Tab title="pnpm">
        ```bash title="terminal" theme={"system"}
        pnpm add kavachos
        ```
      </Tab>

      <Tab title="npm">
        ```bash title="terminal" theme={"system"}
        npm install kavachos
        ```
      </Tab>

      <Tab title="yarn">
        ```bash title="terminal" theme={"system"}
        yarn add kavachos
        ```
      </Tab>
    </Tabs>
  </Step>

  <Step>
    ### Create an instance

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

    ```ts theme={"system"}
    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',
      },
    });
    ```

    <Info>
      For in-memory storage (useful in tests), pass `url: ':memory:'` instead.
    </Info>

    <Info>
      Set `requireVerification: false` during development so you can sign in without verifying email. Remove this in production.
    </Info>
  </Step>

  <Step>
    ### Create an agent

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

    ```ts theme={"system"}
    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);
    ```

    <Warning>
      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.
    </Warning>

    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.                            |
  </Step>

  <Step>
    ### Authorize an action

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

    ```ts theme={"system"}
    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:

    ```ts theme={"system"}
    const result = await kavach.authorizeByToken(bearerToken, {
      action: 'read',
      resource: 'mcp:github:repos',
    });
    ```
  </Step>

  <Step>
    ### Check the audit trail

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

    ```ts theme={"system"}
    // 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' });
    ```
  </Step>
</Steps>

## 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.

```ts theme={"system"}
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);
```

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

## Full working example

<Expandable title="Self-contained script: create, authorize, rotate, delegate, export">
  Covers agent creation, authorization by ID and token, token rotation, delegation, and audit export.

  ```ts theme={"system"}
  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' });
  ```
</Expandable>

## Cloudflare Workers

KavachOS runs on Workers with no changes. Pass a D1 binding as the database and use the Hono adapter.

```typescript theme={"system"}
import { createKavach } from 'kavachos';
import { Hono } from 'hono';

type Env = { KAVACH_DB: D1Database };

const app = new Hono<{ Bindings: Env }>();

app.get('/health', async (c) => {
  const kavach = await createKavach({
    database: { provider: 'd1', binding: c.env.KAVACH_DB },
  });

  const agent = await kavach.agent.create({
    ownerId: 'user-1',
    name: 'my-agent',
    type: 'autonomous',
    permissions: [{ resource: 'mcp:github:*', actions: ['read'] }],
  });

  return c.json({ agent });
});

export default app;
```

Bind a D1 database in your `wrangler.toml`:

```toml theme={"system"}
[[d1_databases]]
binding = "KAVACH_DB"
database_name = "kavach"
database_id = "<your-database-id>"
```

Run `npx wrangler d1 execute kavach --file=./kavach-schema.sql` to apply the schema, or set `skipMigrations: false` to let KavachOS run migrations on first boot.

<Info>
  `createKavach` is async when using D1. Workers and Deno both support top-level await, so you can also initialize outside the handler if you use a module worker.
</Info>

## Troubleshooting

### "Invalid email or password" after sign-up

Sign-in requires email verification by default. Either:

1. Verify the email using the token from the sign-up response
2. Set `requireVerification: false` in the `emailPassword()` config

### "FOREIGN KEY constraint failed" when creating agents

You need a user in the `kavach_users` table before creating agents. Sign up via the email auth plugin, or seed a user manually:

```typescript theme={"system"}
kavach.db.insert(users).values({
  id: 'user-1',
  email: 'test@example.com',
  name: 'Test',
  createdAt: new Date(),
  updatedAt: new Date(),
}).run();
```

### Session not persisting after page reload

The React hooks store sessions in `localStorage`. Make sure your app is wrapped in `<KavachProvider>`. If using SSR (Next.js), wrap the provider in a `"use client"` component.

## Next steps

<CardGroup cols={2}>
  <Card title="Permission engine" icon="shield-halved" href="/permissions">
    Wildcards, rate limits, time windows, IP allowlists, approval gates.
  </Card>

  <Card title="Delegation chains" icon="link" href="/delegation">
    Sub-agent delegation with depth limits and cascading revocation.
  </Card>

  <Card title="MCP OAuth 2.1" icon="globe" href="/mcp">
    Set up the authorization server for MCP tool servers.
  </Card>

  <Card title="Framework adapters" icon="puzzle-piece" href="/adapters">
    Drop-in middleware for ten frameworks.
  </Card>

  <Card title="Coming from another library" icon="arrow-right-arrow-left" href="/migrate">
    Migration guides from better-auth and Clerk.
  </Card>

  <Card title="Configuration" icon="gear" href="/configuration">
    All `createKavach()` options and environment patterns.
  </Card>
</CardGroup>
