Skip to content

API Reference

Klein Panic edited this page Apr 4, 2026 · 1 revision

API Reference

Memory-Spark exposes its functionality through two layers: the OpenClaw memory plugin tools (agent-facing) and the MemorySparkManager class (programmatic API). Additionally, the StorageBackend interface provides direct LanceDB operations.

Agent-Facing Tools

These are the tools available to OpenClaw agents via the memory plugin system.

memory_search

Semantically search agent memory files (MEMORY.md, memory/*.md, and optional session transcripts).

// Tool signature
{
  name: "memory_search",
  parameters: {
    query: string;         // Required. Search query text.
    maxResults?: number;   // Optional. Max results to return (default: 10)
    minScore?: number;     // Optional. Minimum relevance score [0, 1] (default: 0.75)
  }
}

// Return type
{
  results: Array<{
    path: string;          // Relative file path (e.g., "memory/2026-01-15.md")
    startLine: number;     // Start line in source file
    endLine: number;       // End line in source file
    score: number;         // Relevance score [0, 1]
    snippet: string;       // Matched text content
    source: "memory" | "sessions";
    citation?: string;     // "path:startLine" (when citations enabled)
  }>;
  provider: string;        // e.g., "spark:nvidia/llama-embed-nemotron-8b"
  model?: string;
  fallback?: { from: string; reason?: string };
  citations: "on" | "off" | "auto";
  mode?: string;           // Search mode (e.g., "search", "query")
}

// Error return
{
  results: [];
  disabled: true;
  unavailable: true;
  error: string;           // Error message
  warning: string;         // Human-readable explanation
  action: string;          // Suggested fix
}

Example usage:

Agent calls: memory_search({ query: "Klein's preferred coding style" })
→ Returns top snippets from MEMORY.md and memory/*.md mentioning coding preferences

Behavior notes:

  • Citations are auto-included in direct chats, suppressed in group/channel chats
  • Results are clamped by maxInjectedChars budget (default: 4000 chars for QMD backend)
  • Quota exhaustion returns unavailable: true with actionable fix suggestion

memory_get

Read a specific file or line range from agent memory. Use after memory_search to pull only needed lines.

// Tool signature
{
  name: "memory_get",
  parameters: {
    path: string;          // Required. Relative path (e.g., "MEMORY.md", "memory/2026-01-15.md")
    from?: number;         // Optional. Start line number (1-indexed)
    lines?: number;        // Optional. Number of lines to read (default: 50)
  }
}

// Return type
{
  text: string;            // File content (or line range)
  path: string;            // Resolved path
}

// Error return
{
  path: string;
  text: "";
  disabled: true;
  error: string;
}

Example usage:

memory_get({ path: "memory/2026-03-15.md", from: 10, lines: 20 })
→ Returns lines 10-30 of that daily memory file

Auto-Recall Hook

The before_prompt_build hook automatically injects relevant memories before each agent response. This is NOT a tool — it runs transparently.

// Hook interface
interface AutoRecallDeps {
  cfg: AutoRecallConfig;
  backend: StorageBackend;
  embed: EmbedProvider | EmbedQueue | EmbedLike;
  reranker: Reranker;
  hyde?: HydeConfig;
}

// Hook output (injected into agent system prompt)
type BeforePromptBuildResult = {
  systemPrompt?: string;      // Not used by recall
  prependContext?: string;    // XML-wrapped memories prepended to context
};

Format of injected memories:

<relevant-memories>
  <memory source="memory-spark:memory:MEMORY.md" score="0.92" updated="2026-03-15T10:30:00Z">
    Klein prefers concise, direct responses without excessive formatting.
  </memory>
  <memory source="memory-spark:capture:auto" score="0.87" updated="2026-04-01T14:22:00Z">
    DGX Spark runs llama-embed-nemotron-8b for embeddings on port 18091.
  </memory>
</relevant-memories>

Auto-Capture Hook

The after_message hook captures knowledge from assistant responses.

// Configuration
interface AutoCaptureConfig {
  enabled: boolean;
  agents: string[];              // ["*"] for all agents
  ignoreAgents: string[];        // Exclude specific agents
  categories: string[];          // ["fact", "preference", "decision", "code-snippet"]
  minConfidence: number;         // 0.6 — minimum classification confidence
  minMessageLength: number;      // 30 — skip trivial messages
  useClassifier: boolean;        // true — use Spark zero-shot classifier
}

MemorySparkManager API

The MemorySparkManager class (src/manager.ts) implements the MemorySearchManager interface.

Constructor

interface ManagerOptions {
  cfg: MemorySparkConfig;
  agentId: string;
  workspaceDir: string;
  backend: StorageBackend;
  embed: EmbedProvider;
  reranker: Reranker;
  queue?: EmbedQueue;
}

const manager = new MemorySparkManager(opts);

search(query, opts?)

Full pipeline search (hybrid merge → source weighting → temporal decay → MMR → rerank).

async search(
  query: string,
  opts?: { maxResults?: number; minScore?: number; sessionKey?: string }
): Promise<MemorySearchResult[]>

Graceful degradation: If Spark embedding is down, vector search is disabled and only FTS results are returned.

readFile(params)

Read file content — tries indexed chunks first, falls back to disk read.

async readFile(params: {
  relPath: string;
  from?: number;
  lines?: number;
}): Promise<{ text: string; path: string }>

status()

Returns backend status including provider, model, dimensions, and available sources.

status(): MemoryProviderStatus
// Returns: { backend: "builtin", provider: "spark:...", model: "...", ... }

probeEmbeddingAvailability()

Checks if the embedding provider is reachable.

async probeEmbeddingAvailability(): Promise<{ ok: boolean; error?: string }>

probeVectorAvailability()

Checks if the vector index is ready.

async probeVectorAvailability(): Promise<boolean>

close()

Closes the storage backend connection.

async close(): Promise<void>

StorageBackend Interface

The StorageBackend interface (src/storage/backend.ts) defines the contract for storage implementations.

vectorSearch(queryVector, opts)

ANN search using IVF_PQ index with cosine distance.

async vectorSearch(queryVector: number[], opts: SearchOptions): Promise<SearchResult[]>

interface SearchOptions {
  query: string;
  maxResults?: number;    // Default: 20
  minScore?: number;      // Default: 0 (no filter)
  agentId?: string;       // Filter by agent
  source?: string;        // Filter by source type
  contentType?: string;   // Filter by content_type
  pathContains?: string;  // Substring match on path
  pool?: string;          // Single pool filter
  pools?: string[];       // Multi-pool filter (OR logic)
}

ftsSearch(query, opts)

BM25 full-text search with sigmoid score normalization.

async ftsSearch(query: string, opts: SearchOptions): Promise<SearchResult[]>

upsert(chunks)

Insert or update chunks (merge by ID). Uses write mutex to prevent concurrent commit conflicts.

async upsert(chunks: MemoryChunk[]): Promise<void>
// Retries up to 3 times on commit conflict with exponential backoff

deleteByPath(path, agentId?)

Delete all chunks for a file path.

async deleteByPath(path: string, agentId?: string): Promise<number>  // returns deleted count

getByIds(ids)

Retrieve chunks by ID — used for parent-child context expansion.

async getByIds(ids: string[]): Promise<MemoryChunk[]>
// Arrow Vector objects are converted to plain JS number[] for cosine computation

listPaths(agentId?)

List all indexed file paths with chunk counts.

async listPaths(agentId?: string): Promise<Array<{
  path: string;
  agentId: string;
  updatedAt: string;
  chunkCount: number;
}>>

status()

Backend health check.

async status(): Promise<BackendStatus>

interface BackendStatus {
  backend: "lancedb";
  chunkCount: number;
  tableExists: boolean;
  ready: boolean;
  error?: string;
}

Reranker API

createReranker(cfg)

Factory function that creates a Spark reranker or passthrough fallback.

async function createReranker(cfg: RerankConfig): Promise<Reranker>

interface Reranker {
  rerank(query: string, candidates: SearchResult[], topN?: number, options?: RerankOptions): Promise<SearchResult[]>;
  probe(): Promise<boolean>;
}

Reranker Options

interface RerankOptions {
  alphaOverride?: number;              // Override blend alpha (0 = pure reranker)
  blendModeOverride?: "score" | "rrf"; // Override blend mode
  rrfKOverride?: number;               // Override RRF k constant
  vectorWeightOverride?: number;       // Override vector weight for RRF
  rerankerWeightOverride?: number;     // Override reranker weight for RRF
  gateOverride?: "off" | "hard" | "soft";  // Override gate mode
  gateThresholdOverride?: number;      // Override gate threshold
  gateLowThresholdOverride?: number;   // Override gate low threshold
}

Embedding API

EmbedProvider Interface

interface EmbedProvider {
  id: string;          // Provider identifier
  model: string;       // Model name
  dims: number;        // Vector dimensions (4096 for Nemotron-8B)
  
  embedQuery(text: string): Promise<number[]>;     // With instruction prefix
  embedDocument(text: string): Promise<number[]>;  // Without prefix
  probe(): Promise<boolean>;                       // Health check
}

EmbedQueue

Batched, queued embedding with automatic retry.

class EmbedQueue {
  constructor(provider: EmbedProvider);
  embedQuery(text: string): Promise<number[]>;
  embedDocument(text: string): Promise<number[]>;
}

Error Codes

Error Cause Resolution
insufficient_quota Embedding provider quota exhausted Top up quota or switch provider
memory search unavailable Provider unreachable or misconfigured Check Spark endpoint and API key
Commit conflict Concurrent LanceDB writes Automatic retry (up to 3x)
FTS index creation failure SQLite FTS5 not available Non-fatal; FTS search returns empty
Arrow schema error on mergeInsert Old table schema missing new columns Run scripts/rebuild-table.ts
SCOPE_MISMATCH Agent trying to access unauthorized pool Check agent scope configuration

Caching Behavior

Cache Scope Size TTL Eviction
Query embed cache Per-process 256 entries 30 min LRU
QMD manager cache Per-process (global singleton) Per agent+config Session lifetime On manager close
FTS index state Per-backend Boolean flag Permanent Reset on new table
Write mutex Per-backend 1 lock N/A Released on completion