Quickstart
Install the fishmem engine and run your first add and search in your own code.
This page gets the fishmem engine
running inside your own application — no hosted API, no API key. You construct a
Memory instance, add a memory, and search it back.
The method surface (add, search, get, update, delete, history)
matches the hosted FishMem Cloud API, so code you write against the
engine moves to the cloud as a client change, not a rewrite.
Install
npm i fishmemSet provider keys
The engine needs an LLM provider (for fact extraction and reconciliation) and an embedding provider (to turn facts into vectors). Both default to OpenAI-style APIs. Set your key in the environment:
export OPENAI_API_KEY="sk-..."If your LLM and embeddings live behind different keys or endpoints, set them explicitly in the config object — see Configuration.
Instantiate Memory
Construct a Memory instance with your providers, a graph store, and a vector
index. The example below uses the bundled local stores, which are the simplest
way to get running; swap them for D1 + Vectorize or other backends in
Configuration.
import { Memory } from 'fishmem'
export const memory = new Memory({
llm: {
provider: 'openai',
model: 'gpt-4o-mini',
apiKey: process.env.OPENAI_API_KEY,
},
embedder: {
provider: 'openai',
model: 'text-embedding-3-small',
apiKey: process.env.OPENAI_API_KEY,
},
graphStore: { provider: 'local', path: './fishmem.db' },
vectorStore: { provider: 'local', path: './fishmem.vec' },
})from fishmem import Memory
memory = Memory(config={
"llm": {"provider": "openai", "model": "gpt-4o-mini"},
"embedder": {"provider": "openai", "model": "text-embedding-3-small"},
"graph_store": {"provider": "local", "path": "./fishmem.db"},
"vector_store": {"provider": "local", "path": "./fishmem.vec"},
})Add a memory
Pass conversation messages and a scope. The engine extracts the durable facts — it does not store the raw text. The result lists what changed.
import { memory } from './memory'
const result = await memory.add(
[{ role: 'user', content: 'I prefer dark mode and write TypeScript.' }],
{ userId: 'alex' },
)
console.log(result)
// [{ id: 'mem_...', memory: 'Prefers dark mode', event: 'ADD' },
// { id: 'mem_...', memory: 'Writes TypeScript', event: 'ADD' }]Scope every memory with at least one of userId, agentId, or runId. Scopes
keep one user's memories from leaking into another's search. See
Scoping.
Search it back
Search runs hybrid recall — vector similarity, keyword match, temporal ordering, and graph diffusion — and returns the relevant facts for the same scope.
import { memory } from './memory'
const hits = await memory.search('what does alex like?', {
userId: 'alex',
topK: 5,
})
console.log(hits)
// [{ id: 'mem_...', memory: 'Prefers dark mode', score: 0.82 }, ...]That is the whole loop: add during a conversation, search before you
answer. Pass infer: false on add when you want to store content verbatim
instead of extracting facts — see
How memory works.