Core concepts

Agent identity

Creating, managing, and rotating agent identities in KavachOS.

What is an agent identity

AgentIdentity is the primary entity in KavachOS. It represents a single AI agent, a process acting on behalf of a human user.

Agents are not users. No passwords, sessions, or OAuth flows. Just tokens and permissions.

Prop

Type

Agent types

Lifecycle

Creating an agent

const agent = await kavach.agent.create({
  ownerId: 'user-123',   // ID from your auth provider
  name: 'github-reader',
  type: 'autonomous',
  permissions: [
    { resource: 'mcp:github:*', actions: ['read'] },
  ],
  expiresAt: new Date(Date.now() + 7 * 24 * 3_600_000), // optional
  metadata: { purpose: 'nightly PR review' },
});

console.log(agent.token); // kv_a3f8c2e1...  — only shown here

The token is returned once at creation. KavachOS stores only the SHA-256 hash, so the plaintext cannot be recovered later. Save it immediately or rotate to get a new one.

Tokens

Tokens use the kv_ prefix followed by 32 cryptographically random bytes encoded as 64 hex characters:

kv_a3f8c2e1d4b5...   (64 hex chars after the prefix)

Authenticate by passing the token as a Bearer credential:

Authorization: Bearer kv_a3f8c2e1d4b5...

The hash-only storage model means a full database dump cannot reveal active tokens. There are no secrets to rotate after a DB breach, only the tokens themselves.

Token rotation

Rotation issues a new token and immediately invalidates the old one. The operation is atomic: there is no window where both tokens are valid.

const rotated = await kavach.agent.rotate(agentId);
// rotated.token is the new plaintext token
// The old token is rejected on all subsequent calls

Rotate tokens on a schedule, or any time you suspect a token has been exposed.

Token-based authorization

When a caller only has a raw bearer token (for example, in HTTP middleware), use authorizeByToken instead of authorize:

const token = request.headers.get('Authorization')?.replace('Bearer ', '');
if (!token) return new Response('Unauthorized', { status: 401 });

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

if (!result.allowed) {
  return new Response(result.reason ?? 'Forbidden', { status: 403 });
}

This performs a single database lookup (hash comparison), then evaluates permissions in memory. No JWTs, no network calls.

Listing and filtering agents

// All agents owned by a user
const agents = await kavach.agent.list({ userId: 'user-123' });

// Only active autonomous agents
const active = await kavach.agent.list({
  userId: 'user-123',
  status: 'active',
  type: 'autonomous',
});

Updating an agent

const updated = await kavach.agent.update(agentId, {
  name: 'github-reader-v2',
  permissions: [
    { resource: 'mcp:github:*', actions: ['read', 'comment'] },
  ],
});

Permission updates take effect immediately. In-flight requests that have already passed authorization are not affected.

Revoking an agent

await kavach.agent.revoke(agentId);
// All future authorize() or authorizeByToken() calls return allowed: false
// The agent's token is also invalidated immediately

Revocation is permanent. There is no un-revoke. To restore access, create a new agent.

Agent limits

The default limit is 10 active agents per user. Raise it at initialization:

const kavach = createKavach({
  database: { provider: 'sqlite', url: 'kavach.db' },
  agents: {
    maxPerUser: 50,
  },
});

Attempts to create agents beyond the limit return an error with code AGENT_LIMIT_EXCEEDED.

On this page