Skip to main content

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();

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.