Stop sharing API keys between agents
Shared API keys have no owner, no scope, and no audit trail. When one leaks, every agent using it is exposed. kavachOS gives each agent its own cryptographic identity -- with permissions and rotation built in.
700+
tests passing
9
OAuth providers
7
framework adapters
3
database backends
pnpm add kavachosHow tokens work
Shown once, stored as a hash
The raw token is returned at creation and never stored. Only the SHA-256 hash lives in your database. A breach exposes nothing usable.
kv_a3f8c2d91b4e7f05...returned once8d4f2a1c9b3e6d07f1a4b8c2d5e9f3a0b7c4d1e8f2a5b9c3d6e0f4a2...stored in db -- useless without the raw token
Agent types
Three roles, one identity model
Each type maps to a different operational pattern. The SDK enforces the constraints automatically -- no extra code on your end.
Autonomous
Acts independently within its granted permissions. No user in the loop. Good for scheduled tasks, background jobs, and pipelines that run unattended.
- Permissions locked at creation -- no scope creep
- Every action checked inline via authorize()
- Audit log entry per call, with result and latency
type: "autonomous"Delegated
Receives a subset of a parent agent's permissions. Useful when a root agent spins up sub-agents to handle parallel workloads.
- Cannot grant more than the parent holds
- Revoke the root, the whole chain dies
- Chain depth tracked and audited
type: "delegated"Service
Long-lived, for machine-to-machine calls. No session dependency. Typically no expiry -- rotation handles credential hygiene instead.
- No user session dependency
- Rotate without downtime -- atomic swap
- Rate-limited and budget-capped independently
type: "service"Permission engine
Six constraint types, evaluated inline
Every constraint is checked inside authorize() before your handler runs. No middleware stacks, no separate policy service.
Hard cap on request frequency. Exceeding it blocks the agent until the window resets.
maxCallsPerMinute, maxCallsPerDay{ maxCallsPerDay: 5000 }Restrict agents to business hours or a declared active period. Off-hours access is blocked and logged.
allowedHoursUTC{ allowedHoursUTC: "09:00-18:00" }Lock an agent to known infrastructure. Requests from unlisted IPs are denied before reaching your handler.
ipAllowlist{ ipAllowlist: ["10.0.0.0/8"] }High-risk actions pause for human review. The agent queues the request and waits for explicit approval.
requireApprovalFor{ requireApprovalFor: ["payments:write"] }Token cost limit enforced inline during authorize(). Agent is throttled at 80% and blocked at the cap.
budgetUsdPerDay, budgetUsdPerMonth{ budgetUsdPerDay: 2.00 }Regex patterns that argument values must match. Good for scoping file access or URL patterns.
argPatterns{ argPatterns: { path: "^/api/.*" } }Code example
Install, create, authorize
Everything below runs in under 50 ms. No token storage, no polling, no external service.
import { createKavach } from "kavachos";
const kavach = createKavach({ db, secret: process.env.KAVACH_SECRET });
// Step 1 — create an agent. Token shown once only.
const { agent, token } = await kavach.agents.create({
userId: "user_123",
name: "github-assistant",
type: "autonomous",
permissions: [{ resource: "mcp:github:*", actions: ["read", "write"] }],
constraints: { maxCallsPerDay: 5000, budgetUsdPerDay: 2.00 },
});
// token = "kv_a3f8c2..." — never stored, only the SHA-256 hash is
// Step 2 — authorize before every action
const result = await kavach.agents.authorize({
token: agentToken,
resource: "mcp:github:issues",
action: "write",
});
if (!result.allowed) return { error: result.reason };
// Step 3 — rotate. Old token invalidated atomically.
const { token: newToken } = await kavach.agents.rotate(agent.id);Token lifecycle
Create, use, rotate, revoke
Create
Agent created with type and permissions. Token returned once, never stored raw.
Authorize
Every action calls authorize(). Constraints evaluated inline -- no round-trips.
Rotate
New token issued, old hash deleted atomically. Zero downtime, no coordination.
Revoke
Agent disabled instantly. Cascades to all delegated sub-agents automatically.
Compared to API keys
Why agent tokens beat shared API keys
| Agent token | API key | |
|---|---|---|
| Scoped to one agent | × | |
| SHA-256 hashed at rest | × | |
| Wildcard resource permissions | × | |
| Atomic rotation | manual | |
| Delegation chains | × | |
| Per-agent audit trail | × | |
| Budget caps | × | |
| Trust scoring | × | |
| W3C DID portable identity | × | |
| Rate limit constraints | × |
What you get
Everything in one package
Give every agent its own identity
TypeScript-first, MIT licensed. Works with SQLite, Postgres, or MySQL. No cloud dependency, no vendor lock-in.