Skip to main content

How audit logging works

Every call to kavach.authorize() or kavach.authorizeByToken() writes an entry to the audit log, regardless of outcome. Allowed, denied, and rate-limited calls are all recorded. The log is append-only: entries are never updated or deleted. authorize() returns an auditId linking the decision to its log entry:
const result = await kavach.authorize(agent.id, {
  action: 'read',
  resource: 'mcp:github:repos',
});

console.log(result.auditId); // "aud_3f8a..."

Querying logs

AuditEntry type

id
string
Unique entry identifier, prefixed aud_.
agentId
string
The agent that triggered the authorization check.
userId
string
The user who owns the agent.
action
string
The action the agent attempted (e.g. read, write, delete).
resource
string
The resource the action was attempted on.
parameters
Arguments passed to the tool at the time of the call.
result
'allowed' | 'denied' | 'rate_limited'
The outcome of the authorization check.
durationMs
number
Time taken to evaluate the decision, in milliseconds.
tokensCost
number
Optional token usage from the agent’s LLM call, if provided.
timestamp
Date
When the authorization check occurred.

Filtering

All filter fields are optional and combinable. Without filters, the query returns all entries up to the limit.
const logs = await kavach.audit.query({
  agentId: 'agt_...',
  userId: 'user-123',
  result: 'denied',
  since: new Date('2025-01-01'),
  until: new Date('2025-02-01'),
  actions: ['write', 'delete'],
  limit: 100,
  offset: 0,
});
agentId
string
Filter to a specific agent.
userId
string
Filter to all agents owned by a user.
since
Date
Include entries on or after this timestamp.
until
Date
Include entries before this timestamp.
actions
string[]
Filter to specific action names.
result
'allowed' | 'denied' | 'rate_limited'
Filter by outcome.
limit
number
Maximum entries to return. Default is 1000.
offset
number
Pagination offset.

Exporting logs

// JSON export
const json = await kavach.audit.export({ format: 'json' });

// CSV export, suitable for spreadsheets and compliance tools
const csv = await kavach.audit.export({ format: 'csv' });

// Export a specific time range
const q4 = await kavach.audit.export({
  format: 'csv',
  since: new Date('2024-10-01'),
  until: new Date('2025-01-01'),
});
The CSV export includes a header row with field names matching the AuditEntry interface. Each row is one authorization decision.
Both since and until are optional on exports. Omitting both exports the entire log.

Compliance references

Article 12 requires high-risk AI systems to log events automatically throughout the system lifecycle, including the period of activity and data used. KavachOS records every authorization decision with agent identity, resource, action, parameters, outcome, and timestamp.
The NIST AI Risk Management Framework calls for documented accountability mechanisms and the ability to trace AI actions to specific identities. The append-only audit trail links every decision to a named agent and user.
SOC 2 trust services criteria for logical access controls and system monitoring require evidence that access is granted only to authorized identities and that access events are logged. The allowed/denied/rate_limited result field satisfies CC6.1–CC6.3. The tamper-evident, append-only structure satisfies CC7.2.
ISO 42001 recommends documenting the behavior of AI systems in production. Exporting the audit log as JSON or CSV gives auditors a machine-readable record of every decision the system made.

Usage patterns

Monthly access report for a user
const entries = await kavach.audit.query({
  userId: 'user-123',
  since: new Date('2025-03-01'),
  until: new Date('2025-04-01'),
});
Agents with repeated denials today
const denied = await kavach.audit.query({
  result: 'denied',
  since: new Date(new Date().setHours(0, 0, 0, 0)),
});

const countsByAgent = denied.reduce<Record<string, number>>((acc, entry) => {
  acc[entry.agentId] = (acc[entry.agentId] ?? 0) + 1;
  return acc;
}, {});
High-frequency agent detection
const highActivity = await kavach.audit.query({
  agentId: 'agt_...',
  since: new Date(Date.now() - 3_600_000), // last hour
});

console.log(`${highActivity.length} calls in the last hour`);
A sudden spike in call volume from a single agent often indicates a runaway loop. Use kavach.agent.revoke() to suspend the agent while you investigate.

Next steps

Compliance

Map audit data to EU AI Act, NIST, SOC 2, and ISO 42001.

REST API

Query audit logs via HTTP endpoints.

Admin dashboard

Visual audit log viewer with filters and export.