> ## 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

> Using AMFS from TypeScript and Node.js applications.

# 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

```bash theme={null}
npm install @senselab-ai/amfs
```

***

## Quick Start

```typescript theme={null}
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

```typescript theme={null}
import { AgentMemory } from "@senselab-ai/amfs";

const mem = new AgentMemory(agentId: string, options?: AgentMemoryOptions);
```

```typescript theme={null}
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.

```typescript theme={null}
// 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.

```typescript theme={null}
// 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.

```typescript theme={null}
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
```

```typescript theme={null}
// 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

```typescript theme={null}
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:

```typescript theme={null}
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

```typescript theme={null}
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:

```typescript theme={null}
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:

```typescript theme={null}
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:

```typescript theme={null}
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:

```typescript theme={null}
// 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

```typescript theme={null}
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

```typescript theme={null}
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:

```typescript theme={null}
// 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

```typescript theme={null}
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](/amfs/getting-started/saas-connection) guide, [MCP server](/amfs/guides/mcp), and [REST API reference](/amfs/guides/http-server) for details.

***

## Rooms & Collaboration

The SDK includes room-based collaboration APIs for multi-agent knowledge sharing and negotiation. These require an `HttpAdapter` connection.

```typescript theme={null}
// 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:

```typescript theme={null}
// 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

```typescript theme={null}
new AgentMemory(agentId: string, options?: AgentMemoryOptions)
```

#### read

```typescript theme={null}
mem.read(entityPath: string, key: string, options?: {
  minConfidence?: number;
}): MemoryEntry | null;
```

#### write

```typescript theme={null}
mem.write(entityPath: string, key: string, value: unknown, options?: {
  confidence?: number;
  ttlAt?: string | null;
  patternRefs?: string[];
  shared?: boolean;
}): MemoryEntry;
```

#### list

```typescript theme={null}
mem.list(entityPath?: string, options?: {
  includeSuperseded?: boolean;
}): MemoryEntry[];
```

#### search

```typescript theme={null}
// Standard search
mem.search(options?: SearchOptions): MemoryEntry[];

// With composite scoring
mem.search(options: SearchOptions & { recallConfig: RecallConfig }): ScoredEntry[];
```

#### history

```typescript theme={null}
mem.history(entityPath: string, key: string, options?: {
  since?: string;
  until?: string;
}): MemoryEntry[];
```

#### stats

```typescript theme={null}
mem.stats(): MemoryStats;
```

#### watch

```typescript theme={null}
mem.watch(entityPath: string, callback: (entry: MemoryEntry) => void): WatchHandle;
```

#### verify

```typescript theme={null}
mem.verify(entityPath?: string): {
  totalChecked: number;
  valid: number;
  corrupted: Array<Record<string, unknown>>;
  chainBreaks: Array<Record<string, unknown>>;
};
```

#### transaction

```typescript theme={null}
mem.transaction(message?: string): TransactionContext;
```

#### commitLog

```typescript theme={null}
mem.commitLog(limit?: number): Commit[];
```

#### commonAncestor

```typescript theme={null}
mem.commonAncestor(commitAId: string, commitBId: string): string | null;
```

#### recordContext

```typescript theme={null}
mem.recordContext(label: string, summary: string, options?: {
  source?: string;
}): void;
```

#### explain

```typescript theme={null}
mem.explain(outcomeRef?: string): Record<string, unknown>;
```

#### commitOutcome

```typescript theme={null}
// 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

```typescript theme={null}
mem.recall(entityPath: string, key: string, options?: {
  minConfidence?: number;
}): MemoryEntry | null;
```

#### myEntries

```typescript theme={null}
mem.myEntries(entityPath?: string): MemoryEntry[];
```

#### readFrom

```typescript theme={null}
mem.readFrom(agentId: string, entityPath: string, key: string): MemoryEntry | null;
```

#### scope

```typescript theme={null}
mem.scope(entityPath: string, options?: { readonly?: boolean }): MemoryScope;
```

#### listScopes

```typescript theme={null}
mem.listScopes(): string[];
```

#### info

```typescript theme={null}
mem.info(entityPath: string): ScopeInfo;
```

#### tree

```typescript theme={null}
mem.tree(maxDepth?: number): string;
```

#### clearReadLog

```typescript theme={null}
mem.clearReadLog(): void;
```

***

### MemoryScope

A scoped view bound to a fixed entity path. When `readonly` is true, writes throw an error.

```typescript theme={null}
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

```typescript theme={null}
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

```typescript theme={null}
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

```typescript theme={null}
enum OutcomeType {
  SUCCESS = "success",
  MINOR_FAILURE = "minor_failure",
  FAILURE = "failure",
  CRITICAL_FAILURE = "critical_failure",
}
```

***

## Notes

<Note>
  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.
</Note>

<Note>
  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.
</Note>
