Documentation Index
Fetch the complete documentation index at: https://docs.sense-lab.ai/llms.txt
Use this file to discover all available pages before exploring further.
TypeScript SDK
The TypeScript SDK (@senselab-ai/amfs) provides full parity with the Python SDK for Node.js and TypeScript applications — including ReadTracker, auto-causal linking, search, history, stats, scopes, transactions, integrity verification, and explainability.
Installation
npm install @senselab-ai/amfs
Quick Start
import { AgentMemory, OutcomeType } from "@senselab-ai/amfs";
const mem = new AgentMemory("review-agent");
// Write
mem.write("checkout-service", "retry-pattern", {
pattern: "exponential-backoff",
maxRetries: 3,
});
// Read — automatically tracked by ReadTracker
const entry = mem.read("checkout-service", "retry-pattern");
console.log(entry?.value); // { pattern: "exponential-backoff", ... }
console.log(entry?.version); // 1
// List all entries for an entity
const entries = mem.list("checkout-service");
// Search with filters
const results = mem.search({
entityPath: "checkout-service",
minConfidence: 0.7,
sortBy: "confidence",
limit: 10,
});
// Auto-causal outcome — uses ReadTracker (no explicit keys needed)
const updated = mem.commitOutcome("DEP-500", OutcomeType.SUCCESS);
Constructor
import { AgentMemory } from "@senselab-ai/amfs";
const mem = new AgentMemory(agentId: string, options?: AgentMemoryOptions);
interface AgentMemoryOptions {
sessionId?: string;
adapter?: AmfsAdapter;
config?: AMFSConfig;
}
By default, the SDK uses an in-memory adapter. Pass an HttpAdapter to connect to a remote AMFS server, or implement AmfsAdapter for custom storage.
ReadTracker & Auto-Causal Linking
The TypeScript SDK includes a ReadTracker that automatically logs every read() call and external context. When you call commitOutcome() without explicit causal keys, the SDK uses the read log to build the causal chain — identical to the Python SDK behavior.
// These reads are automatically tracked
mem.read("checkout-service", "retry-pattern");
mem.read("checkout-service", "pool-config");
// Record external context
mem.recordContext("pagerduty-status", "No active incidents", { source: "PagerDuty API" });
// Commit outcome — auto-links to everything read in this session
const updated = mem.commitOutcome("DEP-500", OutcomeType.SUCCESS);
// Explain the causal chain
const chain = mem.explain();
// → causalEntries: [retry-pattern, pool-config]
// → externalContexts: [{ label: "pagerduty-status", ... }]
// Clear the read log between tasks
mem.clearReadLog();
Agent-Scoped Memory
The SDK distinguishes between shared memory and agent-scoped memory. Use recall, myEntries, and readFrom for explicit agent-level operations.
// Recall your own memory for a key (only entries written by this agent)
const mine = mem.recall("checkout-service", "retry-pattern");
// List everything this agent has written
const allMine = mem.myEntries("checkout-service");
// Read from another agent's memory (cross-agent knowledge transfer)
const theirs = mem.readFrom("deploy-agent", "checkout-service", "deploy-config");
Scopes
A MemoryScope provides a focused view bound to a single entity path, reducing boilerplate when working with one service or module.
const checkout = mem.scope("checkout-service");
// All operations are scoped — no need to repeat the entity path
checkout.write("retry-pattern", { maxRetries: 5 }, { confidence: 0.9 });
const entry = checkout.read("retry-pattern");
const all = checkout.list();
const history = checkout.history("retry-pattern");
const scopeInfo = checkout.info();
// Readonly scopes prevent accidental writes
const readonlyScope = mem.scope("checkout-service", { readonly: true });
readonlyScope.write("key", "value"); // throws Error
// List all entity paths that contain entries
const scopes = mem.listScopes();
// Get summary info about a scope
const info = mem.info("checkout-service");
// → { path, entryCount, avgConfidence, keys, oldest, newest }
// Render entity paths as a tree
const tree = mem.tree();
Search
import { SearchOptions } from "@senselab-ai/amfs";
const results = mem.search({
query: "retry", // text query
entityPath: "checkout-service", // filter by entity
entityPaths: ["svc-a", "svc-b"],// multi-scope search
agentId: "review-agent", // filter by author
minConfidence: 0.5, // minimum confidence
maxConfidence: 1.0, // maximum confidence
since: "2026-03-01T00:00:00Z", // filter by time
patternRef: "retry-pattern", // filter by pattern reference
sortBy: "confidence", // "confidence" | "recency" | "version"
limit: 20, // max results
});
Composite Scoring with RecallConfig
Pass a recallConfig to get scored results with breakdown information:
import type { RecallConfig, ScoredEntry } from "@senselab-ai/amfs";
const scored: ScoredEntry[] = mem.search({
entityPath: "checkout-service",
recallConfig: {
semanticWeight: 0.4,
recencyWeight: 0.3,
confidenceWeight: 0.3,
recencyHalfLifeDays: 14,
},
});
scored.forEach(({ entry, score, breakdown }) => {
console.log(entry.key, score, breakdown);
});
Version History
const versions = mem.history("checkout-service", "retry-pattern");
// Returns all versions, ordered by version number
// Filter by time range (ISO date strings)
const recent = mem.history("checkout-service", "retry-pattern", {
since: "2026-03-01T00:00:00Z",
until: "2026-04-01T00:00:00Z",
});
Watch
Subscribe to changes on an entity path:
const handle = mem.watch("checkout-service", (entry) => {
console.log(`Updated: ${entry.key} v${entry.version}`);
});
// Later, cancel the subscription
handle.cancel();
console.log(handle.cancelled); // true
Transactions
Group multiple writes into an atomic commit:
const tx = mem.transaction("batch update retry configs");
tx.write("checkout-service", "retry-pattern", { maxRetries: 5 });
tx.write("checkout-service", "timeout-config", { timeoutMs: 3000 });
tx.write("payment-service", "retry-pattern", { maxRetries: 2 });
console.log(tx.pendingCount); // 3
// Commit all writes together
tx.commit();
Integrity Verification
Verify content hashes and integrity chains for stored entries:
const result = mem.verify("checkout-service");
// Or verify all: mem.verify()
console.log(result.totalChecked);
console.log(result.valid);
console.log(result.corrupted); // Array of corrupted entry info
console.log(result.chainBreaks); // Array of chain break info
Commit Log & DAG
Inspect the commit history and navigate the commit DAG:
// Get recent commits on the current branch
const commits = mem.commitLog(10);
commits.forEach((c) => {
console.log(c.id, c.message, c.entries.length);
});
// Find common ancestor of two commits
const ancestor = mem.commonAncestor(commitAId, commitBId);
Stats
const stats = mem.stats();
console.log(stats.totalEntries);
console.log(stats.totalEntities);
console.log(stats.totalAgents);
console.log(stats.confidenceAvg);
console.log(stats.outcomeLinkedCount);
console.log(stats.agents); // Record<string, number>
console.log(stats.entities); // Record<string, number>
Connecting to AMFS
Using the HttpAdapter
import { AgentMemory, HttpAdapter } from "@senselab-ai/amfs";
const adapter = new HttpAdapter({
url: "https://amfs.sense-lab.ai",
apiKey: process.env.AMFS_API_KEY,
});
const mem = new AgentMemory("review-agent", { adapter });
The HttpAdapter provides async methods for remote operations:
// Async read/write
const entry = await adapter.readAsync("checkout-service", "retry-pattern");
const written = await adapter.writeAsync({
entityPath: "checkout-service",
key: "retry-pattern",
value: { maxRetries: 3 },
confidence: 0.9,
});
// Async search and list
const results = await adapter.searchAsync({
entityPath: "checkout-service",
minConfidence: 0.7,
limit: 10,
});
const entries = await adapter.listAsync("checkout-service");
// Stats and health
const stats = await adapter.statsAsync();
const health = await adapter.healthAsync();
// Decision traces
const traces = await adapter.listTracesAsync({
entityPath: "checkout-service",
limit: 5,
});
const trace = await adapter.getTraceAsync(traces[0].id);
Direct REST calls
const response = await fetch("https://amfs.sense-lab.ai/api/v1/entries", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-AMFS-API-Key": process.env.AMFS_API_KEY!,
},
body: JSON.stringify({
entity_path: "checkout-service",
key: "retry-pattern",
value: { maxRetries: 3 },
}),
});
See the Connect to AMFS guide, MCP server, and REST API reference for details.
Rooms & Collaboration
The SDK includes room-based collaboration APIs for multi-agent knowledge sharing and negotiation. These require an HttpAdapter connection.
// List rooms available to this agent
const rooms = await mem.myRooms();
// Join a room
await mem.roomJoin("room-123");
// Get room details
const info = await mem.roomInfo("room-123");
// Get recent activity
const updates = await mem.roomUpdates("room-123", { since: "2026-05-01T00:00:00Z" });
// Post a discussion message
await mem.roomDiscuss("room-123", "I've updated the retry config based on recent incidents", {
messageType: "update",
addressedTo: "deploy-agent",
});
// Read discussions
const messages = await mem.roomDiscussions("room-123", { limit: 20 });
// Leave a room (snapshots are preserved)
await mem.roomLeave("room-123");
Negotiation
Rooms support structured negotiation sessions between agents:
// Create a negotiation session
const session = await mem.negotiateCreate("room-123", "Retry Config Agreement", {
description: "Agree on shared retry parameters",
maxRounds: 5,
});
// Make a proposal
await mem.negotiatePropose("room-123", session.id, {
action: "propose",
proposal: { maxRetries: 3, backoffMs: 1000 },
rationale: "Based on P99 latency data from last week",
});
// Respond to a proposal
await mem.negotiateRespond("room-123", session.id, "accept", {
rationale: "Aligns with our SLA requirements",
});
// Check negotiation status
const status = await mem.negotiateStatus("room-123", session.id);
Full API Reference
AgentMemory
Constructor
new AgentMemory(agentId: string, options?: AgentMemoryOptions)
read
mem.read(entityPath: string, key: string, options?: {
minConfidence?: number;
}): MemoryEntry | null;
write
mem.write(entityPath: string, key: string, value: unknown, options?: {
confidence?: number;
ttlAt?: string | null;
patternRefs?: string[];
shared?: boolean;
}): MemoryEntry;
list
mem.list(entityPath?: string, options?: {
includeSuperseded?: boolean;
}): MemoryEntry[];
search
// Standard search
mem.search(options?: SearchOptions): MemoryEntry[];
// With composite scoring
mem.search(options: SearchOptions & { recallConfig: RecallConfig }): ScoredEntry[];
history
mem.history(entityPath: string, key: string, options?: {
since?: string;
until?: string;
}): MemoryEntry[];
stats
mem.stats(): MemoryStats;
watch
mem.watch(entityPath: string, callback: (entry: MemoryEntry) => void): WatchHandle;
verify
mem.verify(entityPath?: string): {
totalChecked: number;
valid: number;
corrupted: Array<Record<string, unknown>>;
chainBreaks: Array<Record<string, unknown>>;
};
transaction
mem.transaction(message?: string): TransactionContext;
commitLog
mem.commitLog(limit?: number): Commit[];
commonAncestor
mem.commonAncestor(commitAId: string, commitBId: string): string | null;
recordContext
mem.recordContext(label: string, summary: string, options?: {
source?: string;
}): void;
explain
mem.explain(outcomeRef?: string): Record<string, unknown>;
commitOutcome
// Auto-causal (uses ReadTracker)
mem.commitOutcome(outcomeRef: string, outcomeType: OutcomeType): MemoryEntry[];
// Explicit causal keys
mem.commitOutcome(
outcomeRef: string,
outcomeType: OutcomeType,
causalEntryKeys: string[],
options?: { causalConfidence?: number },
): MemoryEntry[];
recall
mem.recall(entityPath: string, key: string, options?: {
minConfidence?: number;
}): MemoryEntry | null;
myEntries
mem.myEntries(entityPath?: string): MemoryEntry[];
readFrom
mem.readFrom(agentId: string, entityPath: string, key: string): MemoryEntry | null;
scope
mem.scope(entityPath: string, options?: { readonly?: boolean }): MemoryScope;
listScopes
mem.listScopes(): string[];
info
mem.info(entityPath: string): ScopeInfo;
tree
mem.tree(maxDepth?: number): string;
clearReadLog
mem.clearReadLog(): void;
MemoryScope
A scoped view bound to a fixed entity path. When readonly is true, writes throw an error.
scope.read(key: string, options?: { minConfidence?: number }): MemoryEntry | null;
scope.write(key: string, value: unknown, options?: {
confidence?: number;
ttlAt?: string | null;
patternRefs?: string[];
}): MemoryEntry;
scope.list(options?: { includeSuperseded?: boolean }): MemoryEntry[];
scope.search(options?: Omit<SearchOptions, "entityPath" | "entityPaths">): MemoryEntry[];
scope.history(key: string, options?: { since?: string; until?: string }): MemoryEntry[];
scope.info(): ScopeInfo;
TransactionContext
tx.write(entityPath: string, key: string, value: unknown, options?: Record<string, unknown>): void;
tx.setMessage(message: string): void;
tx.pendingCount: number;
tx.commit(): void;
Exports
import {
// Classes
AgentMemory,
MemoryScope,
CoWEngine,
CausalTagger,
ReadTracker,
OutcomeBackPropagator,
InMemoryAdapter,
HttpAdapter,
// Functions & constants
createWatchHandle,
defaultConfig,
OutcomeType,
OUTCOME_MULTIPLIERS,
// Types
type AgentMemoryOptions,
type SearchOptions,
type MemoryStats,
type AmfsAdapter,
type WatchHandle,
type HttpAdapterOptions,
type DecisionTrace,
type DecisionTraceSummary,
type ExternalContext,
type MemoryEntry,
type OutcomeRecord,
type Provenance,
type ArtifactRef,
type AMFSConfig,
type LayerConfig,
type RecallConfig,
type ScopeInfo,
type ScoredEntry,
} from "@senselab-ai/amfs";
OutcomeType Values
enum OutcomeType {
SUCCESS = "success",
MINOR_FAILURE = "minor_failure",
FAILURE = "failure",
CRITICAL_FAILURE = "critical_failure",
}
Notes
The TypeScript SDK uses an in-memory adapter by default. To persist data remotely, pass an HttpAdapter instance configured with your AMFS server URL and API key. The HttpAdapter provides both sync (stub) and async methods — use the async variants (readAsync, writeAsync, etc.) for remote operations.
Room and negotiation APIs require an HTTP connection to AMFS and return Promises. They are available on the AgentMemory instance when using an adapter that exposes a base URL.