Skip to main content

What tenants are

A tenant represents an organization or workspace that shares one KavachOS deployment. Each tenant has its own agents, audit log, and policy settings. Data is isolated by tenantId: agents in one tenant cannot be seen or authorized against by another. This is useful for SaaS products where each customer gets their own isolated agent environment without you running a separate database per customer.
tenantId is nullable everywhere it appears. Existing agents, policies, and audit entries created before you enable multi-tenancy continue to work without modification.

Data model

id
string
Stable identifier with a tnt_ prefix, e.g. tnt_acme.
name
string
Display name for the tenant.
slug
string
URL-safe identifier. Lowercase letters, numbers, and hyphens only. Must be unique.
settings
TenantSettings
Per-tenant configuration overrides.
status
'active' | 'suspended'
Suspended tenants cannot authorize requests.
createdAt
Date
When the tenant was created.
updatedAt
Date
When the tenant was last modified.

TenantSettings

maxAgents
number
default:"undefined (uses global limit)"
Maximum active agents allowed in this tenant. Overrides the global default.
maxDelegationDepth
number
default:"undefined"
How deep delegation chains can go. Defaults to the global setting.
auditRetentionDays
number
default:"undefined (no automatic pruning)"
How long audit entries are kept for this tenant, in days.
allowedAgentTypes
string[]
default:"undefined (all types allowed)"
Restrict which agent types can be created. E.g. [‘autonomous’] to disallow delegated agents.

Creating a tenant

Slugs must be unique and match ^[a-z0-9]+(?:-[a-z0-9]+)*$. KavachOS rejects duplicate slugs at creation time.
const tenant = await kavach.tenant.create({
  name: 'Acme Corp',
  slug: 'acme',
  settings: {
    maxAgents: 200,
    auditRetentionDays: 365,
    allowedAgentTypes: ['autonomous', 'service'],
  },
});

console.log(tenant.id);   // tnt_...
console.log(tenant.slug); // acme

Creating an agent inside a tenant

Pass tenantId when creating an agent. The agent is then scoped to that tenant.
const agent = await kavach.agent.create({
  ownerId: 'user-456',
  name: 'acme-data-bot',
  type: 'autonomous',
  tenantId: tenant.id,
  permissions: [
    { resource: 'reports:*', actions: ['read', 'export'] },
  ],
});
Authorization checks respect the tenant boundary: an agent in tnt_acme cannot be authorized against resources in tnt_other.

Listing agents by tenant

const agents = await kavach.agent.list({
  tenantId: tenant.id,
  status: 'active',
});

Fetching and updating a tenant

// By ID
const t = await kavach.tenant.get('tnt_abc123');

// By slug (useful when the slug comes from a URL path)
const t2 = await kavach.tenant.getBySlug('acme');

// Update settings
const updated = await kavach.tenant.update(tenant.id, {
  settings: {
    maxAgents: 500,
    auditRetentionDays: 730,
  },
});
Settings are merged, not replaced. Fields you omit in the update keep their existing values.

Listing all tenants

const tenants = await kavach.tenant.list();
Useful for admin dashboards. Returns all tenants regardless of status.

Suspending and reactivating

When a tenant is suspended, all authorize() calls for agents in that tenant return allowed: false. Existing tokens are not revoked; they fail authorization until the tenant is reactivated.
// Suspend
await kavach.tenant.suspend(tenant.id);

// Reactivate
await kavach.tenant.activate(tenant.id);

Budget policies per tenant

Attach a budget policy to a tenant to apply spending limits across all agents in it. See Budget policies for the full policy reference.
await kavach.policy.create({
  tenantId: tenant.id,
  limits: {
    maxTokensCostPerMonth: 5000,
    maxCallsPerMonth: 100_000,
  },
  action: 'block',
});

Next steps

Budget policies

Apply cost limits at the tenant, agent, or user level.

Agent identity

Create agents scoped to a tenant.

Audit log

Filter the audit trail by tenant.
Last modified on April 18, 2026