ExamplesClinical trials
Export the audit trail
Export the whole workspace as a portable bundle, and write one audit line per study record.
Set SMARTMEMORY_API_KEY, SMARTMEMORY_WORKSPACE_ID and optionally SMARTMEMORY_BASE_URL (default https://api.smartmemory.ai). See the overview for setup.
What it uses
client.export_okfandclient.exportOkfdownload the workspace as a gzipped OKF bundle. They need workspace admin.client.explainandclient.memories.explainreturn the audit answer for one memory: when it was recorded, when it was valid, its version history, and the decisions that cite it.chain_verifiedisnullwhen a record has no edits to verify. That is not a warning.
Python
"""Export the workspace: a portable OKF bundle, plus one audit line per memory."""
import io
import json
import os
import tarfile
from smartmemory_client import SmartMemoryClient
client = SmartMemoryClient(
base_url=os.environ.get("SMARTMEMORY_BASE_URL", "https://api.smartmemory.ai"),
api_key=os.environ["SMARTMEMORY_API_KEY"],
workspace_id=os.environ["SMARTMEMORY_WORKSPACE_ID"],
)
# 1. The whole workspace as a gzipped bundle. Needs workspace admin.
bundle = client.export_okf()
with open("clinical-trial-demo.okf.tar.gz", "wb") as out:
out.write(bundle)
with tarfile.open(fileobj=io.BytesIO(bundle)) as archive:
print("bundle:", len(bundle), "bytes,", len(archive.getnames()), "files")
# 2. The audit answer for every study memory: when it was recorded, when it was valid,
# its version history, and the decisions that cite it.
lines = 0
offset = 0
with open("clinical-trial-demo.audit.jsonl", "w") as out:
while True:
page = client.list_memories(
metadata_key="study", metadata_value="KVR-417-201", limit=50, offset=offset
)
for item in page["items"]:
audit = client.explain(item["item_id"])
row = {
"record_id": item["metadata"]["record_id"],
"recorded_at": audit["item"]["transaction_time"],
"valid_from": audit["item"]["valid_start_time"],
"versions": len(audit["versions"]),
"chain_verified": audit["chain_verified"],
"cited_by": [d["decision_id"] for d in audit["decision_provenance"]["citing_decisions"]],
}
out.write(json.dumps(row) + "\n")
lines += 1
offset += len(page["items"])
if not page["items"] or offset >= page["total"]:
break
print("audit lines:", lines)Output:
bundle: 37048 bytes, 75 files
audit lines: 61JavaScript
// Export the workspace: a portable OKF bundle, plus one audit line per memory.
import { writeFileSync, createWriteStream } from "node:fs";
import { gunzipSync } from "node:zlib";
import { SmartMemoryClient } from "@smartmemory/sdk-js";
const client = new SmartMemoryClient({
apiBaseUrl: process.env.SMARTMEMORY_BASE_URL ?? "https://api.smartmemory.ai",
apiKey: process.env.SMARTMEMORY_API_KEY,
storage: "memory", // a script has no browser storage
});
client.setWorkspaceId(process.env.SMARTMEMORY_WORKSPACE_ID);
// 1. The whole workspace as a gzipped bundle. Needs workspace admin.
const bundle = Buffer.from(await client.exportOkf());
writeFileSync("clinical-trial-demo.okf.tar.gz", bundle);
// A tar archive is 512-byte blocks: a header block, then the file body padded to a block.
// Extended-attribute headers (type x) describe the next entry, they are not files.
const tar = gunzipSync(bundle);
let files = 0;
for (let at = 0; at + 512 <= tar.length && tar[at] !== 0; ) {
const size = parseInt(tar.toString("ascii", at + 124, at + 135).trim(), 8) || 0;
if (tar[at + 156] !== 0x78) files += 1;
at += 512 + Math.ceil(size / 512) * 512;
}
console.log("bundle:", bundle.length, "bytes,", files, "files");
// 2. The audit answer for every study memory: when it was recorded, when it was valid,
// its version history, and the decisions that cite it.
const out = createWriteStream("clinical-trial-demo.audit.jsonl");
let lines = 0;
for (let offset = 0; ; ) {
const page = await client.memories.list({
metadataKey: "study", metadataValue: "KVR-417-201", limit: 50, offset,
});
for (const item of page.items) {
const audit = await client.memories.explain(item.item_id);
out.write(JSON.stringify({
record_id: item.metadata.record_id,
recorded_at: audit.item.transaction_time,
valid_from: audit.item.valid_start_time,
versions: audit.versions.length,
chain_verified: audit.chain_verified,
cited_by: audit.decision_provenance.citing_decisions.map((d) => d.decision_id),
}) + "\n");
lines += 1;
}
offset += page.items.length;
if (!page.items.length || offset >= page.total) break;
}
out.end();
console.log("audit lines:", lines);Output:
bundle: 40625 bytes, 75 files
audit lines: 61Audit line
Both scripts write clinical-trial-demo.okf.tar.gz and clinical-trial-demo.audit.jsonl to the current directory. One audit line, from the local run:
{
"record_id": "CT-DEC-02",
"recorded_at": "2026-11-02T19:38:35.236241+00:00",
"valid_from": "2026-02-10T00:00:00+00:00",
"versions": 0,
"chain_verified": null,
"cited_by": [
"dec_4df2ad5d51e2"
]
}The local workspace had 61 study records, 18 of them cited by a decision.
The output below is from a real run against a local test stack seeded with the demo dataset. It shows record ids and dates only.