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:
- Applied the correct policies at the time of the request
- Recorded an immutable decision record
- Can demonstrate chain integrity across any time window
- 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:
| Component | What it is |
|---|---|
event | The decision event (policy outcome, cost, tokens, model) |
trail | Trail record(s) linked to the request |
digest | Cryptographic digest covering the trail window |
publicKey | The verification key active at the time |
verification | Chain 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
});
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");
}
}