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

# Ephemeral sessions

> Short-lived, auto-expiring agent credentials for single-task computer-use agents.

## What ephemeral sessions are

An ephemeral session is a temporary agent identity that expires on its own. You create one, hand the token to an AI agent, and the token stops working when the TTL runs out or the agent exhausts its action budget, whichever comes first.

The pattern is designed for computer-use agents (Claude computer use, GPT browsing, operator loops) that need just enough access to complete one task without holding persistent credentials across invocations.

Key differences from a regular agent:

|               | Regular agent         | Ephemeral session            |
| ------------- | --------------------- | ---------------------------- |
| Lifetime      | Indefinite by default | Bounded TTL (default 5 min)  |
| Token         | Rotatable, persistent | Single-use window            |
| Cleanup       | Manual revocation     | Automatic                    |
| Action budget | None                  | Optional hard cap            |
| Audit         | Per-agent             | Grouped under one session ID |

## Setup

No extra configuration is needed, ephemeral sessions are part of the `kavachos` core package and share the same database as the rest of KavachOS.

```typescript theme={"system"}
import { createKavach } from 'kavachos';
import { createEphemeralSessionModule } from 'kavachos/auth';

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

const ephemeral = createEphemeralSessionModule({
  db: kavach.db,
  defaultTtlSeconds: 300,   // 5 minutes
  maxTtlSeconds: 3600,      // 1 hour ceiling
  autoRevokeOnExpiry: true, // revoke underlying agent on expiry
  auditGrouping: true,      // group all actions under one audit session ID
});
```

## Creating a session for a computer-use agent

Call `createSession` right before you hand control to the agent. The token is shown exactly once.

```typescript theme={"system"}
const result = await ephemeral.createSession({
  ownerId: 'user-abc',          // the human who owns this task
  name: 'fill-checkout-form',   // optional label
  permissions: [
    { resource: 'tool:browser', actions: ['navigate', 'click', 'type'] },
  ],
  ttlSeconds: 120,              // 2 minutes for this particular task
  maxActions: 20,               // hard cap: fail after 20 actions
});

if (!result.success) throw new Error(result.error.message);

const { token, expiresAt, auditGroupId } = result.data;
// Pass `token` to the agent. Never store it or log it.
```

The returned `token` starts with `kveph_` to distinguish it from long-lived agent tokens (`kv_`).

## Validating a session

Each time the agent makes a request, validate the token before granting access.

```typescript theme={"system"}
const check = await ephemeral.validateSession(token);

if (!check.success) {
  // error.code is one of:
  // SESSION_NOT_FOUND, SESSION_EXPIRED, SESSION_EXHAUSTED, SESSION_REVOKED
  return new Response('Unauthorized', { status: 401 });
}

const { sessionId, agentId, remainingActions, expiresIn, auditGroupId } = check.data;
```

`expiresIn` is in seconds. `remainingActions` is `null` when no action cap was set.

## Tracking actions

Call `consumeAction` once per agent action to decrement the budget counter.

```typescript theme={"system"}
const consumed = await ephemeral.consumeAction(token);

if (!consumed.success) {
  // SESSION_EXHAUSTED when the budget runs out
  return new Response('Budget exhausted', { status: 429 });
}

const { actionsRemaining } = consumed.data;
// actionsRemaining is null when no maxActions was configured
```

When `actionsRemaining` hits zero, the session transitions to `exhausted` and the underlying agent is automatically revoked.

## Action limits

`maxActions` is a hard cap on how many times `consumeAction` can succeed. It is independent of the TTL, a session can expire by time with actions remaining, or exhaust its action budget before the TTL lapses.

Set a tight budget for tasks with a well-known scope and leave it as `null` for tasks where the step count is unpredictable.

```typescript theme={"system"}
// A session with both a time limit and an action cap
await ephemeral.createSession({
  ownerId: userId,
  permissions: [{ resource: 'tool:search', actions: ['query'] }],
  ttlSeconds: 60,
  maxActions: 5,
});
```

## Revoking early

If the agent completes the task before the TTL expires, revoke the session manually.

```typescript theme={"system"}
await ephemeral.revokeSession(sessionId);
```

Revocation is idempotent, calling it on an already-revoked session returns success.

## Listing active sessions

Useful for dashboards or for building kill-switch UI.

```typescript theme={"system"}
const result = await ephemeral.listActiveSessions('user-abc');

if (result.success) {
  for (const session of result.data) {
    console.log(session.sessionId, session.expiresAt, session.actionsUsed);
  }
}
```

The returned objects have `token` set to `""`, the token is never readable after the initial `createSession` response.

## Cleanup strategies

Two approaches to cleaning up expired sessions:

### Scheduled background job

Run `cleanupExpired()` on a cron schedule, every minute for busy systems, every 5 minutes for lighter loads.

```typescript theme={"system"}
// With node:timers/promises or any scheduler
setInterval(async () => {
  const result = await ephemeral.cleanupExpired();
  if (result.success && result.data.count > 0) {
    console.log(`Cleaned up ${result.data.count} expired sessions`);
  }
}, 60_000);
```

### On-demand at validate time

`validateSession` already detects and transitions expired sessions. For low-traffic systems, this is enough, no background job needed.

## Audit grouping

When `auditGrouping: true` (the default), all actions within a session share the same `auditGroupId`. This makes it trivial to reconstruct the full activity trace for a single task.

```typescript theme={"system"}
const validated = await ephemeral.validateSession(token);
if (validated.success) {
  // Attach to every audit entry for this action
  const { auditGroupId } = validated.data;
}
```

## Session status lifecycle

```
created → active → exhausted (maxActions reached)
                 → expired   (TTL elapsed)
                 → revoked   (manual revocation)
```

Once a session leaves `active`, it cannot be reactivated. Create a new session for a new task.

## Error codes

| Code                | Meaning                                                 |
| ------------------- | ------------------------------------------------------- |
| `SESSION_NOT_FOUND` | Token does not match any session                        |
| `SESSION_EXPIRED`   | TTL has elapsed                                         |
| `SESSION_EXHAUSTED` | Action budget is fully consumed                         |
| `SESSION_REVOKED`   | Manually revoked                                        |
| `TTL_EXCEEDS_MAX`   | Requested TTL is above `maxTtlSeconds`                  |
| `VALIDATION_ERROR`  | Input failed schema validation (e.g. empty permissions) |
