Skip to main content

Memory Guide

Since: v9.12.0 | Status: Stable | Availability: SDK

Overview

NeuroLink includes a memory engine powered by the @juspay/hippocampus SDK. Unlike conversation memory (which tracks recent turns in a session), memory maintains a condensed summary of durable facts about each user across all conversations.

Key characteristics:

  • Per-user: Each user gets an independent memory store keyed by userId
  • Condensed: Memory is kept to a configurable word limit (default 50 words) via LLM-powered condensation
  • Persistent: Stored in S3, Redis, or SQLite — survives server restarts
  • Non-blocking: Memory storage happens in the background after each generate/stream call
  • Crash-safe: Every SDK method is wrapped in try-catch — errors are logged, never thrown

How It Works

User prompt arrives


┌─────────────┐
│ memory.get() │ ← Retrieve condensed memory for this userId
└──────┬──────┘
│ Prepend memory context to prompt

┌─────────────┐
│ LLM call │ ← generate() or stream() as normal
└──────┬──────┘


┌──────────────┐
│ memory.add() │ ← In background: condense old memory + new turn via LLM
└──────────────┘

On each generate() or stream() call:

  1. Retrieve: memory.get(userId) fetches the user's condensed memory (if any)
  2. Inject: The memory is prepended to the user's prompt as context
  3. Generate: The LLM processes the enhanced prompt normally
  4. Store: After the response completes, memory.add(userId, content) runs in the background. The SDK sends the old memory + new conversation turn to an LLM which produces a new condensed summary

Quick Start

import { NeuroLink } from "@juspay/neurolink";

const neurolink = new NeuroLink({
conversationMemory: {
enabled: true,
memory: {
enabled: true,
storage: {
type: "s3",
bucket: "my-memory-bucket",
prefix: "memory/condensed/",
},
neurolink: {
provider: "google-ai",
model: "gemini-2.5-flash",
},
maxWords: 50,
},
},
});

// Memory is automatically retrieved and stored on each call
const result = await neurolink.generate({
input: { text: "My name is Alice and I run a Shopify store." },
context: { userId: "user-123" },
});

// Next call — the AI already knows about Alice
const result2 = await neurolink.generate({
input: { text: "What platform do I use?" },
context: { userId: "user-123" },
});
// → "You use Shopify."

Configuration

The memory field on conversationMemory accepts a Memory object:

type Memory = HippocampusConfig & { enabled?: boolean };

Required Fields

FieldTypeDescription
enabledbooleanSet true to activate memory
storage.typestringStorage backend: "s3", "redis", or "sqlite"
neurolink.providerstringAI provider for condensation LLM calls
neurolink.modelstringModel for condensation LLM calls

Optional Fields

FieldTypeDefaultDescription
maxWordsnumber50Maximum words in the condensed memory
promptstringbuilt-inCustom condensation prompt (supports {{OLD_MEMORY}}, {{NEW_CONTENT}}, {{MAX_WORDS}} placeholders)
storage.bucketstringS3 bucket name (required for S3 storage)
storage.prefixstringS3 key prefix for memory objects
storage.urlstringRedis connection URL (required for Redis storage)
storage.pathstringSQLite file path (required for SQLite storage)

Storage Backends

memory: {
enabled: true,
storage: {
type: "s3",
bucket: "my-bucket",
prefix: "memory/condensed/",
},
neurolink: { provider: "google-ai", model: "gemini-2.5-flash" },
}

Each user's memory is stored as a single S3 object at {prefix}{userId}.

Redis

memory: {
enabled: true,
storage: {
type: "redis",
url: "redis://localhost:6379",
},
neurolink: { provider: "openai", model: "gpt-4o-mini" },
}

SQLite (Development)

memory: {
enabled: true,
storage: {
type: "sqlite",
path: "./memory.db",
},
neurolink: { provider: "google-ai", model: "gemini-2.5-flash" },
}

Note: SQLite requires the better-sqlite3 optional peer dependency. Install it manually: pnpm add better-sqlite3

Custom Condensation Prompt

The condensation prompt controls how the LLM merges old memory with new conversation turns. You can provide a custom prompt using the prompt field:

memory: {
enabled: true,
storage: { type: "s3", bucket: "my-bucket" },
neurolink: { provider: "google-ai", model: "gemini-2.5-flash" },
prompt: `You are a memory engine. Merge the old memory with new facts into a summary of at most {{MAX_WORDS}} words.

OLD_MEMORY:
{{OLD_MEMORY}}

NEW_CONTENT:
{{NEW_CONTENT}}

Condensed memory:`,
maxWords: 100,
}

Placeholders

PlaceholderReplaced With
{{OLD_MEMORY}}The user's existing condensed memory (may be empty)
{{NEW_CONTENT}}The new conversation turn: "User: ...\nAssistant: ..."
{{MAX_WORDS}}The configured maxWords value

Integration with generate() and stream()

Memory integrates automatically with both generate() and stream():

  • Before the LLM call: Memory is retrieved and prepended to the input text
  • After the LLM call: The conversation turn is stored in the background via setImmediate()
  • Timeouts: Retrieval has a 3-second timeout; storage has a 10-second timeout (includes LLM condensation)
  • Errors are non-blocking: If memory retrieval or storage fails, the generate/stream call continues normally

Requirements

For memory to activate on a call, all three conditions must be met:

  1. memory.enabled is true in the config
  2. options.context.userId is provided in the generate/stream call
  3. The response has non-empty content (for storage)

Relationship to Mem0

NeuroLink supports two complementary memory systems:

FeatureMemoryMem0
ArchitectureIn-process SDKCloud API (mem0ai)
StorageS3, Redis, or SQLite (you control)Mem0 cloud
Memory modelSingle condensed summary per userStructured memories with categories
LLM callsUses your configured providerUses Mem0's infrastructure
LatencyLower (in-process storage)Higher (cloud API calls)
CostYour LLM costs onlyMem0 API pricing

Both can be enabled simultaneously — they operate independently.

Environment Variables

The @juspay/hippocampus SDK reads these environment variables:

VariableDefaultDescription
HC_LOG_LEVELwarnSDK log level: debug, info, warn, error
HC_CONDENSATION_PROMPTbuilt-inDefault condensation prompt (overridden by config prompt)

Error Handling

The memory SDK is designed to never crash the host application:

  • Every public method (get(), add(), delete(), close()) is wrapped in try-catch
  • Errors are logged via logger.warn() and safe defaults are returned
  • get() returns null on error
  • add() silently fails on error
  • Storage initialization errors result in memory being disabled (returns null from ensureMemoryReady())

Type Exports

NeuroLink re-exports the memory types for use in host applications:

import type { Memory } from "@juspay/neurolink";

// Memory = HippocampusConfig & { enabled?: boolean }

See Also