πΎ Store Memories
Store information durably with remember. Both engines share the same call shape - what happens underneath differs.
const result = await memory.remember(
'Customer ACME is on the enterprise plan; escalations go to the sev-1 channel.',
{
tags: ['customer', 'escalation'], // optional, used for filtered recall
metadata: { source: 'support-bot' }, // optional structured payload
}
)
console.log(result)
Batched engine: buffering + flushingβ
Memories buffer locally as pending and upload in batches - one blob per flushEvery memories (default 10):
import '@lighthouse-ai/store-lighthouse'
import '@lighthouse-ai/embed-local'
import { createEmbedder, createStorage } from '@lighthouse-ai/core'
import { BatchedEngine } from '@lighthouse-ai/engine-batched'
const storage = await createStorage('lh-ipfs-filecoin', { apiKey: process.env.LIGHTHOUSE_API_KEY })
const embedder = await createEmbedder('local') // or `null` for keyword-only
const memory = new BatchedEngine(storage, { namespace: 'demo', embedder, flushEvery: 10 })
const res = await memory.remember('Customer ACME is on enterprise.', { tags: ['customer'] })
// { id: '80cc2055-β¦', flushed: false, pendingCount: 1 }
// when this write trips flushEvery: { id, flushed: true, pendingCount: 0, cid, gatewayUrl }
Pending memories are searchable immediately but live only on the local machine until flushed:
const flushed = await memory.flush()
// { flushedMemories: 3, cid: 'bafβ¦', gatewayUrl: 'https://gatewayβ¦/ipfs/bafβ¦' }
// { flushedMemories: 0 } when nothing was pending
Flush happens automatically once flushEvery memories are pending. Tune it with the constructor option or MEMORY_FLUSH_EVERY - 1 uploads on every write (maximum durability), higher values pack more memories per blob (maximum quota efficiency).
Walrus erasure-codes every blob, so each upload counts ~63 MB against your account quota regardless of its actual size. One batch blob holding many memories costs the same quota as one holding a single memory.
Memwal engine: direct writes, no flushβ
Every remember goes straight to the relayer (embed + SEAL-encrypt + Walrus + vector index) and returns immediately usable addresses:
import { MemwalMemory } from '@lighthouse-ai/engine-memwal'
const memory = await MemwalMemory.fromEnv() // MEMWAL_PRIVATE_KEY + MEMWAL_ACCOUNT_ID
const res = await memory.remember('Customer ACME is on enterprise.', { tags: ['customer'] })
// { id, blobId, cid, pinned, gatewayUrl?, walrusUrl, network, namespace }
There is no flush() on memwal. LIGHTHOUSE_API_KEY (unless MEMWAL_IPFS_PIN=off) pins a public IPFS mirror of each record; without it you still get a locally computed CID. memory.analyze(text) extracts discrete facts via the relayer and stores each as its own memory.
Configurationβ
| Env var | Default | Purpose |
|---|---|---|
MEMORY_ENGINE | batched | batched or memwal (MCP server / factory) |
MEMORY_STORAGE | lh-ipfs-filecoin | lh-ipfs-filecoin (filecoin alias), lh-ipfs-walrus (walrus alias), local-fs, s3 |
MEMORY_EMBEDDER | local | local (MiniLM semantic) or keyword (word-match only; = embedder: null) |
LIGHTHOUSE_API_KEY | - (required for lh-*) | Lighthouse API key |
MEMORY_NAMESPACE / MEMORY_AGENT | default / agent | Isolates memories per agent/project; agent id recorded on each memory |
MEMORY_FLUSH_EVERY | 10 | Batch size before automatic flush (batched only) |
MEMORY_DIR | ./.memory-sdk | Batched index + local-fs blob location |
MEMWAL_PRIVATE_KEY / MEMWAL_ACCOUNT_ID | - (required for memwal) | Relayer delegate key + account |
MEMWAL_NETWORK | mainnet | mainnet or testnet (staging relayer; creds are per-network) |
MEMWAL_NAMESPACE / MEMWAL_AGENT / MEMWAL_MEMORY_DIR | default / agent / ./.memory-sdk/memwal | Memwal namespace, agent tag, state dir |
MEMWAL_IPFS_PIN | (pin) | off skips IPFS pinning (local CIDs only) |
S3_BUCKET, S3_REGION (AWS_REGION), S3_ENDPOINT, S3_PREFIX, S3_FORCE_PATH_STYLE, S3_PUBLIC_BASE_URL, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY | - | S3 / R2 / MinIO adapter |
What gets storedβ
Batched memories are JSON records inside the batch blob (plus per-record vectors in the local index):
{
"v": 1,
"id": "80cc2055-9256-40b9-af83-5ecf8ea522ce",
"namespace": "default",
"agent": "support-bot",
"content": "Customer ACME is on the enterprise plan; β¦",
"tags": ["customer", "escalation"],
"metadata": { "source": "support-bot" },
"createdAt": "2026-07-22T14:59:03.427Z",
"embedding": [0.0123, -0.0456, "β¦"],
"embeddingModel": "local:Xenova/all-MiniLM-L6-v2",
"origin": "batched"
}
Memwal records carry blobId (the SEAL-encrypted Walrus blob) plus a local CID mirror. Blobs are content-addressed: same content = same CID.
Anyone with a batch CID, snapshot CID, or pinned memwal CID can read it from the gateway - do not store secrets in batched memory or memwal mirrors.