Skip to content

Library SDK

The library is the most direct surface: call the engine in your own process, no server required. It is first-class in TypeScript and Python, and the same verb set is reachable over HTTP and MCP.

The @bezial/sdk package is the full public API - the file-is-truth core, the derived graph, the engine, and the clients.

BezialEngine is one file-is-truth core wired to one derived graph. Bind it to a principal with .as() to get BezialClient, the identity-implicit verb surface.

import { BezialEngine } from '@bezial/sdk';
const engine = new BezialEngine({
rootDir: './memory', // local object store + change logs
permissions: 'acl', // enforce the ACL model (omit for allow-all)
});
const alice = engine.as({ id: 'alice' });
await alice.add('team', 'Alice uses Obsidian.');
const result = await alice.recall('team', 'What does Alice use?');

BezialClient exposes every verb, with the acting principal implicit:

interface BezialClient {
// writes (the only write path is a file)
add(space, text): Promise<WriteResult>;
write(space, path, content): Promise<WriteResult>;
restore(space, path, version): Promise<WriteResult>; // restore a document version
// authorized reads
read(space, path): Promise<DocumentContent>;
readVersion(space, path, version): Promise<DocumentContent>;
list(space, prefix?): Promise<string[]>;
history(space, path): Promise<VersionInfo[]>;
acl(space, path): Promise<DocumentAcl>;
audit(space, filter?): Promise<ChangeLogEntry[]>;
// recall + the two views (all permission-filtered per fact)
recall(space, query, options?): Promise<RecallResult>;
fileMap(space, options?): Promise<FileMapView>;
factGraph(space, options?): Promise<FactGraphView>;
// permissions (owner-checked frontmatter writes)
grant(space, path, granteeId): Promise<WriteResult>;
revoke(space, path, granteeId): Promise<WriteResult>;
setVisibility(space, path, visibility): Promise<WriteResult>; // 'private' | 'space'
// forgetting (derived-graph curation; write-gated per source document)
pin(space, factId): Promise<RecalledFact>;
unpin(space, factId): Promise<RecalledFact>;
forget(space, factId, reason): Promise<RecalledFact>;
restoreFact(space, factId): Promise<RecalledFact>; // reverse a forget
}

Note the two distinct restore verbs: restore reverses a document to a prior version (a file write), while restoreFact reverses a forget on a derived fact.

BezialClient is transport-portable. LocalBezialClient (what engine.as() returns) runs in-process; BezialHttpClient runs the same interface against the HTTP server:

import { BezialHttpClient } from '@bezial/sdk';
const remote = new BezialHttpClient({
baseUrl: 'http://localhost:8787',
token: 'bzk_...', // a Bezial API key or a signed principal
});
await remote.recall('team', 'What does Alice use?');

Consumer code is written once against BezialClient and swaps in-process for remote without change.

The bezial package is first-class alongside TypeScript. It ships two things:

  1. BezialHttpClient - the remote verb surface, at parity with the TypeScript client.
  2. A first-class in-process reference of the security-critical core - the bi-temporal fact model, ingest-time ACL stamping, contradiction handling, the permission-filtered recall path (with the zero-leak guarantee tested under pytest), the file-is-truth ACL resolution, and the salience model.
from bezial import BezialHttpClient
client = BezialHttpClient("http://localhost:8787", "bzk_...")
client.add("team", "Alice uses Obsidian.")
result = client.recall("team", "What does Alice use?", synthesize=True)
result.facts # cited, bi-temporal facts
result.answer # a written answer (when synthesize=True)

Python uses snake_case where TypeScript uses camelCase: set_visibility, restore_fact, read(path, version=...), and recall(space, query_text, *, as_of=..., scope=..., synthesize=..., limit=..., include_archived=...).

Both SDKs return the same R3 recall shape: structured facts, each with a source-file citation, valid-time, recorded-time, and confidence, plus an optional synthesized answer. On the JSON wire the time windows are nested (validTime.from, recordedTime.to); the Python dataclass flattens them to valid_from / valid_to / recorded_from / recorded_to.