Skip to main content

Evidence & Audit

The Agent SDK provides built-in helpers for producing audit-grade evidence. Every governed request flows through the Keeptrusts trail system — the SDK makes it simple to collect, verify, and export that evidence programmatically.

Why evidence matters

Regulated industries and enterprise compliance teams require proof that AI systems:

  1. Applied the correct policies at the time of the request
  2. Recorded an immutable decision record
  3. Can demonstrate chain integrity across any time window
  4. Produce verifiable cryptographic digests

The Keeptrusts trail system provides all of this. The Agent SDK wraps the trail APIs into ergonomic helpers.

Evidence bundles

An evidence bundle is a self-contained audit package for one or more requests:

const bundle = await agent.createEvidenceBundle({
requestId: result.requestId,
});

A bundle contains:

ComponentWhat it is
eventThe decision event (policy outcome, cost, tokens, model)
trailTrail record(s) linked to the request
digestCryptographic digest covering the trail window
publicKeyThe verification key active at the time
verificationChain integrity check result

Full bundle example

const bundle = await agent.createEvidenceBundle({
requestId: result.requestId,
});

console.log("=== Event ===");
console.log(`ID: ${bundle.event.event_id}`);
console.log(`Outcome: ${bundle.event.policy_outcome}`);
console.log(`Cost: ${bundle.event.event_cost_attribution.total_cost}`);

console.log("\n=== Trail ===");
console.log(`Records: ${bundle.trail.length}`);
console.log(`First: ${bundle.trail[0]?.created_at}`);

console.log("\n=== Verification ===");
console.log(`Chain integrity: ${bundle.verification.chain_integrity}`);
console.log(`Records verified: ${bundle.verification.records_verified}`);

console.log("\n=== Digest ===");
console.log(`Storage key: ${bundle.digest.storage_key}`);
console.log(`Algorithm: ${bundle.digest.hash_algorithm}`);

console.log("\n=== Public Key ===");
console.log(`Key ID: ${bundle.publicKey.kid}`);
console.log(`Algorithm: ${bundle.publicKey.algorithm}`);

Multi-request bundles

Collect evidence for a batch of requests:

const bundle = await agent.createEvidenceBundle({
requestIds: [
"req_001",
"req_002",
"req_003",
],
});

Time-window bundles

Collect evidence for all requests in a time range:

const bundle = await agent.createEvidenceBundle({
startTime: "2026-05-31T00:00:00Z",
endTime: "2026-05-31T23:59:59Z",
});

Trail verification

Verify that the trail has not been tampered with:

const verification = await agent.verifyTrail({
startTime: "2026-05-31T00:00:00Z",
endTime: "2026-05-31T23:59:59Z",
});

Response:

{
"chain_integrity": true,
"records_verified": 1247,
"start_time": "2026-05-31T00:00:00Z",
"end_time": "2026-05-31T23:59:59Z",
"verified_at": "2026-05-31T23:59:59Z"
}

Deep verification

For compliance audits that require full re-computation:

const verification = await agent.verifyTrail({
startTime: "2026-05-01T00:00:00Z",
endTime: "2026-05-31T23:59:59Z",
deepVerify: true, // re-computes all hashes
});
note

Deep verification is computationally intensive. Use it for periodic compliance checks, not per-request validation.

Verification failures

If chain integrity is broken:

if (!verification.chain_integrity) {
console.error("Trail integrity violation detected");
console.error(`First broken record: ${verification.first_broken_record}`);
console.error(`Expected hash: ${verification.expected_hash}`);
console.error(`Actual hash: ${verification.actual_hash}`);

// Alert your compliance team
alertCompliance(verification);
}

Cryptographic digests

Digests are periodic cryptographic summaries of the trail. They enable offline verification without replaying the full trail.

List digests

const digests = await agent.listDigests({
startTime: "2026-05-01T00:00:00Z",
endTime: "2026-05-31T23:59:59Z",
});

for (const digest of digests) {
console.log(`${digest.id}${digest.period_start} to ${digest.period_end}`);
}

Download a digest

const digest = await agent.downloadDigest("digest-id");

console.log(digest.storage_key);
console.log(digest.hash_algorithm); // e.g., "SHA-256"
console.log(digest.hash_value);
console.log(digest.record_count);

Public keys

Verification keys are used to validate trail signatures:

const publicKey = await agent.getPublicKey();

console.log(publicKey.kid); // key ID
console.log(publicKey.algorithm); // e.g., "Ed25519"
console.log(publicKey.publicKey); // PEM or JWK
console.log(publicKey.active_since);

Key rotation

Keeptrusts supports key rotation. When verifying historical records, the correct key is selected by kid:

const historicalKey = await agent.getPublicKey({ kid: "key-2025-q4" });

Export for external auditors

Create an export package suitable for sharing with external auditors:

const exportResult = await agent.exportEvidence({
startTime: "2026-05-01T00:00:00Z",
endTime: "2026-05-31T23:59:59Z",
format: "zip", // "zip" | "json"
includeDigests: true,
includePublicKeys: true,
});

// exportResult.downloadUrl — presigned URL for the export
// exportResult.expiresAt — when the download link expires

Compliance patterns

SOC 2 evidence collection

// Monthly SOC 2 evidence job
async function collectSoc2Evidence(month: string) {
const startTime = `${month}-01T00:00:00Z`;
const endTime = endOfMonth(month);

const verification = await agent.verifyTrail({ startTime, endTime, deepVerify: true });

if (!verification.chain_integrity) {
throw new Error("Trail integrity violation — halt audit");
}

const bundle = await agent.createEvidenceBundle({ startTime, endTime });
const exportResult = await agent.exportEvidence({
startTime,
endTime,
format: "zip",
includeDigests: true,
includePublicKeys: true,
});

return { verification, bundle, exportUrl: exportResult.downloadUrl };
}

Per-request audit trail

// Attach to every agent response for downstream audit
async function auditableChat(messages: Message[]) {
const result = await agent.chat({ model: "gpt-5.4-mini", messages });

const events = await agent.listEvents({ requestId: result.requestId });
const event = events[0];

return {
response: result.choices[0]?.message?.content,
audit: {
requestId: result.requestId,
agentId: result.agentId,
eventId: event.event_id,
policyOutcome: event.policy_outcome,
cost: event.event_cost_attribution.total_cost,
model: event.model,
timestamp: event.created_at,
},
};
}

Continuous verification

// Run every hour to catch integrity issues early
async function continuousVerification() {
const now = new Date();
const oneHourAgo = new Date(now.getTime() - 3600_000);

const verification = await agent.verifyTrail({
startTime: oneHourAgo.toISOString(),
endTime: now.toISOString(),
});

if (!verification.chain_integrity) {
await alertOnCall("Trail integrity violation in the last hour");
}
}