Skip to main content
Version: v0.9.0a2
Integrator

TypeScript SDK Reference

5 min readTypeScript / Node integratorstigmem-ts

What this page covers

stigmem-ts is the official TypeScript client for the Stigmem REST API. It covers facts, conflicts, federation, lint, recall, memory cards, and subscriptions. Targets Node 20+ and is bundler-compatible (esbuild, Rollup, Webpack, Vite).

Audience: TypeScript / Node.js developers integrating with a Stigmem node.

Installation

npm install stigmem-ts
# or
pnpm add stigmem-ts

Quick start

import { StigmemClient, sv, tv } from "stigmem-ts";

const client = new StigmemClient({
url: "http://localhost:8000",
apiKey: process.env.STIGMEM_API_KEY,
});

// Assert a fact
const fact = await client.assertFact(
"user:alice",
"memory:role",
sv("engineer"),
"agent:assistant",
{ scope: "local" },
);

// Hybrid recall
const recall = await client.recall("Alice's current role", { token_budget: 500 });
for (const sf of recall.facts) {
console.log(`[${sf.score.toFixed(3)}] ${sf.fact.relation}`);
}

// Entity memory card
const card = await client.getCard("user:alice");
console.log(card.summary);

StigmemClient

new StigmemClient(opts: {
url: string;
apiKey?: string;
timeoutMs?: number;
fetch?: typeof fetch; // inject a custom fetch (e.g. undici, node-fetch, test mocks)
})

All methods return promises and throw StigmemHTTPError subclasses on non-2xx responses.

Facts

client.assertFact(entity, relation, value, source, opts?: AssertOptions): Promise<Fact>
client.retract(entity, relation, scope, source, value?): Promise<Fact>
client.getFact(factId: string): Promise<Fact>
client.query(opts?: QueryOptions): Promise<FactPage>

AssertOptions:

Field
Default
Type
confidence
1.0
number
scope
"company"
FactScope
valid_until
string

QueryOptions:

Field
Default
Type
entity / relation / source
string
scope
FactScope
min_confidence
number
include_contradicted
false
boolean
include_expired
false
boolean
cursor / after
string
limit
50
number

Use page.cursor from the response for cursor-based pagination.

Recall

client.recall(query: string, opts?: RecallOptions): Promise<RecallResponse>

RecallOptions:

Field
Default
Type
scope
"local"
FactScope
token_budget
4000
number
depth
2
number
weights
server defaults
RecallWeights
min_confidence
0.1
number
include_neighbors
true
boolean
limit
100
number

RecallResponse fields:

Field
Type
Description
recall_id
string
UUID for this recall call.
query_hash
string
SHA-256 of the query string.
facts
ScoredFact[]
Ranked, token-budget-packed facts.
total_scored
number
Candidates scored before packing.
token_budget / tokens_used
number
Requested vs actual budget.
truncated
boolean
True when budget was exhausted.

RecallWeights defaults: { lexical: 0.35, semantic: 0.35, graph: 0.15, source_trust: 0.10, recency: 0.05 }.

Memory cards

client.getCard(entityUri: string, opts?: CardOptions): Promise<MemoryCard>

CardOptions: scope (default "local"), refresh (default false).

import { StigmemNotFoundError } from "stigmem-ts";

try {
const card = await client.getCard("user:alice", { scope: "local" });
console.log(card.summary);
} catch (err) {
if (err instanceof StigmemNotFoundError) {
console.log("Entity has no live facts");
}
}

MemoryCard fields:

Field
Type
Description
entity_uri
string
Entity the card describes.
scope
string
Scope materialised from.
summary
string
Structured text summary.
fact_hashes
string[]
SHA-256(fact_id) for each contributing fact.
avg_confidence
number
Source-trust-weighted mean confidence.
refreshed_at
string?
ISO 8601 UTC timestamp.
is_stale
boolean
New fact asserted since last refresh.
has_contradictions
boolean
Two live facts share the same relation.

Conflicts · Lint · Federation · Node info

client.listConflicts(opts?: ConflictListOptions): Promise<ConflictPage>
client.resolveConflict(conflictId: string, opts?: ResolveOptions): Promise<ConflictResolution>

client.lint(scope: FactScope, opts?: LintOptions): Promise<LintResult>

client.federationStatus(): Promise<Peer[]>
client.nodeInfo(): Promise<NodeInfo> // GET /.well-known/stigmem (no auth)

Subscribe (polling, async generator)

client.subscribeScope(
scope: FactScope,
opts?: SubscribeOptions,
): AsyncGenerator<Fact[]>

SubscribeOptions: intervalMs (default 30000), signal (AbortSignal).

const ac = new AbortController();
setTimeout(() => ac.abort(), 60_000);

for await (const batch of client.subscribeScope("local", { intervalMs: 5_000, signal: ac.signal })) {
console.log(`${batch.length} new fact(s)`);
}

The generator tracks a cursor internally.

Each batch contains only facts newer than the previous poll.

Value constructors

import { sv, tv, nv, bv, dtv, rv, nullv } from "stigmem-ts";

sv("hello") // StringValue { type: "string", v: "hello" }
tv("long text...") // TextValue { type: "text", v: "..." }
nv(3.14) // NumberValue { type: "number", v: 3.14 }
bv(true) // BooleanValue { type: "boolean", v: true }
dtv("2026-05-04T00:00:00Z") // DatetimeValue { type: "datetime", v: "..." }
rv("stigmem://company.example/x") // RefValue { type: "ref", v: "..." }
nullv() // NullValue { type: "null" }

Errors

Class
HTTP
When raised
StigmemHTTPError
any non-2xx
Base class.
StigmemAuthError
401 / 403
Invalid or missing API key.
StigmemNotFoundError
404
Resource does not exist.
StigmemConflictError
409
Conflicting resource state.
import {
StigmemAuthError,
StigmemNotFoundError,
StigmemConflictError,
StigmemHTTPError,
} from "stigmem-ts";

try {
await client.getFact("unknown-id");
} catch (err) {
if (err instanceof StigmemNotFoundError) {
console.log("not found");
} else if (err instanceof StigmemAuthError) {
console.log("auth failed — check STIGMEM_API_KEY");
} else if (err instanceof StigmemHTTPError) {
console.log(`HTTP ${err.statusCode}: ${err.detail}`);
}
}

Custom fetch

import { StigmemClient } from "stigmem-ts";
import { fetch } from "undici";

const client = new StigmemClient({
url: "http://localhost:8000",
fetch: fetch as unknown as typeof globalThis.fetch,
});

Bundler smoke (esbuild)

cd sdks/stigmem-ts
pnpm smoke

Regenerating types from the OpenAPI spec

make sdk-ts-generate # just generation
make sdk-ts # full pipeline: generate → build → test → pack

The ergonomic types in src/types.ts (tagged-union FactValue, value constructors) are hand-authored on top of the generated layer to match the Stigmem wire format described in spec §2.1.

Advanced features

Content-addressed fact IDs (§25)

const factByUuid = await client.getFact("550e8400-e29b-41d4-a716-446655440000");
const factByCid = await client.getFact("sha256:a3f2b8c901d4...");

Asserting the same (entity, relation, value, source, scope) tuple twice returns the existing fact.

CID-based deduplication is automatic.

Time-travel queries (§24)

The experimental as_of parameter is available on the fact query and recall endpoints only when stigmem-plugin-time-travel is registered and the corresponding operator gate is enabled. Default installs fail closed. Use the HTTP client directly:

const res = await fetch(
`${url}/v1/facts?entity=user:alice&as_of=2026-04-15T00:00:00Z`,
{ headers: { Authorization: `Bearer ${apiKey}` } },
);
const { facts } = await res.json();

See also

Tutorial: SDK Quickstart

Assert, recall, and subscribe in Python / TS / Go.

Recall guide

Hybrid recall, weight tuning, fast-path.

Python SDK Reference

Equivalent Python client.

Go SDK Reference

Experimental Go client.