Skip to main content

TypeScript SDK

The Z3rno TypeScript SDK is a thin fetch-based client with Zod runtime validation on every response. Dual ESM + CJS build, native fetch — no axios, no node-fetch, no undici. Current version: @z3rno/sdk 0.7.0 on npm. Requires Node.js 18+ or any runtime with fetch (Deno, Bun, Cloudflare Workers).

Install

npm install @z3rno/sdk
# pnpm add @z3rno/sdk
# yarn add @z3rno/sdk

Client

import { Z3rnoClient } from "@z3rno/sdk";

const client = new Z3rnoClient({
  baseUrl: "http://localhost:8000",
  apiKey: "z3rno_sk_test_localdev",   // default dev key on a fresh local server
});
OptionDefaultNotes
baseUrlrequiredz3rno-server URL. Local dev: http://localhost:8000.
apiKeyrequiredAPI key. Default dev: z3rno_sk_test_localdev.
timeoutMs30000Per-request timeout.
maxRetries3Retries on transient failures.

Method reference

The TS client mirrors the Python SDK’s surface. Method names are camelCase; the API contract is identical.

Memory primitives

// store / batch
const memory = await client.store({
  agentId: "agent-1",
  content: "User prefers dark mode and TypeScript",
  memoryType: "semantic",                 // working | episodic | semantic | procedural
  metadata: { category: "preferences" },
  importance: 0.85,
});

const batch = await client.storeBatch([{ agentId: "...", content: "..." }]);

// retrieve a single memory + temporal history
const m = await client.getMemory(memoryId);
const history = await client.getMemoryHistory(memoryId);   // SCD-2 versions

// update in place (writes a new SCD-2 version)
await client.updateMemory(memoryId, {
  content: "...",
  metadata: { /* ... */ },
  importance: 0.9,
});

// recall — defaults to AUTO strategy router
const results = await client.recall({
  agentId: "agent-1",
  query: "What does the user prefer?",
  topK: 5,
  memoryType: "semantic",                 // optional filter
  timeRange: { start: "2026-03-01", end: "2026-03-31" },  // optional
  asOf: "2026-03-15T12:00:00Z",          // optional point-in-time
  filters: { category: "preferences" },
  conversationId: "conv_abc",            // scope to one conversation (Phase G)
  strategy: "VECTOR",                    // override AUTO; see verbs page
  role: "support_agent",                 // for redaction filter (Phase F slice 2)
});

// forget — soft (default) or hard
await client.forget({ agentId: "agent-1", memoryId: "mem_xyz" });
await client.forget({ agentId: "agent-1", memoryId: "mem_xyz", hardDelete: true });

// audit
const events = await client.audit({ agentId: "agent-1", operation: "store", limit: 50 });

Conversation memory (Phase G slice 2)

const conv = await client.createConversation({
  agentId: "agent-1",
  userId: "user_abc",
  title: "Allergy intake",
  summaryCadence: 10,
});

// Append a turn — server bumps turn_count, returns turnIndex + needsSummary
const turn = await client.addTurn(conv.id, {
  role: "user",
  content: "I'm allergic to penicillin",
});

// List turns (paginated by afterTurn + limit)
const turns = await client.listTurns(conv.id, { afterTurn: 0, limit: 50 });

// Scope recall to this conversation
const scoped = await client.recall({
  agentId: "agent-1",
  query: "allergies",
  conversationId: conv.id,
});

// Soft-delete (turn Memos stay queryable via standard recall)
await client.deleteConversation(conv.id);
await client.getConversation(conv.id);  // 404 once deleted

Forge — ingest, distill, refine

// ingest (auto-chains into forge_distill when INGEST_AUTO_DISTILL=true server-side)
const job = await client.ingestText({ content: "...", agentId: "agent-1", datasetId: "ds_abc" });
const j2  = await client.ingestUrl({ url: "https://example.com/article", agentId: "agent-1" });
const state = await client.getIngestStatus(job.jobId);

// distill manually
const dj = await client.distill({ memoryIds: ["mem_1", "mem_2"], agentId: "agent-1" });
const ds = await client.getDistillStatus(dj.jobId);

// refine the graph in place (admin-scoped)
const rj = await client.refine({ datasetId: "ds_abc" });
const rs = await client.getRefineStatus(rj.jobId);

Tenant self-management (v0.20.3)

// Read current resolved budgets (defaults + your overrides merged)
const view = await client.getMyBudgets();
console.log(view.resolved.dailyTokens, view.overrides.dailyTokens);

// Set partial overrides — fields you omit fall through to server defaults
await client.setMyBudgets({
  dailyTokens: 500_000,
  monthlyLlmCalls: 10_000,
});

Sessions

const session = await client.startSession({ agentId: "agent-1" });
// ... do work ...
await client.endSession(session.id);

Framework integrations

Two adapters ship in @z3rno/sdk and lazy-load their host runtimes — no extra install needed for the SDK itself.

Vercel AI SDK

import { Z3rnoVercelMemory } from "@z3rno/sdk";

const memory = new Z3rnoVercelMemory({
  client,
  agentId: "vercel-agent",
  conversationId: "conv_abc",
});

// Vercel AI shape — drops into useChat / streamText / etc.
const messages = await memory.messages();
await memory.appendUserMessage("hello");
await memory.appendAssistantMessage("hi");
await memory.appendToolMessage({ /* CoreToolMessage */ });

Mastra-JS

import { Z3rnoMastraMemory } from "@z3rno/sdk";

const memory = new Z3rnoMastraMemory({
  client,
  agentId: "mastra-agent",
  conversationId: "conv_abc",
});

const msgs = await memory.getMessages();
await memory.addMessage({ role: "user", content: "..." });
await memory.clear();  // no-op by design — audit history survives

Models

Zod schemas + inferred TypeScript types are exported by name:
import type {
  // memories
  MemoryResponse, MemoryHistoryResponse, MemoryVersion,
  StoreMemoryRequest, BatchStoreResponse,
  RecallResponse, RecallResultItem,
  ForgetResponse,
  // audit + sessions
  AuditEntry, AuditPageResponse,
  SessionResponse, EndSessionResponse,
  // conversations (Phase G)
  ConversationResponse, TurnResponse, TurnAddResponse, TurnListResponse,
  // Forge (ingest / distill / refine)
  IngestJobResponse, IngestJobStatusResponse,
  DistillJobResponse, DistillJobStatusResponse,
  RefineJobResponse, RefineJobStatusResponse,
  // budgets (v0.20)
  TenantBudgets, TenantBudgetsView,
  // enums
  MemoryType, RelationshipType, RetrievalStrategy,
} from "@z3rno/sdk";
Zod parses every response at runtime — you get both compile-time TypeScript types and immediate failure on unexpected server payloads instead of silent downstream issues.

Exceptions

All inherit from Z3rnoError:
ClassMaps toExtra
AuthenticationError401
ValidationError400 / 422
NotFoundError404
RateLimitError429retryAfter (seconds) parsed from header
ServerError5xxSurfaces the server error id for log correlation
Z3rnoConnectionErrornetworkUnderlying cause exposed
Z3rnoTimeoutErrortimeoutPer-request timeout exceeded
import { Z3rnoError, RateLimitError } from "@z3rno/sdk";

try {
  await client.store({ agentId: "agent-1", content: "..." });
} catch (e) {
  if (e instanceof RateLimitError) {
    console.log("retry after", e.retryAfter, "seconds");
  } else if (e instanceof Z3rnoError) {
    console.error("z3rno error:", e);
  }
}

Reference