@zensation/ai-sdk
Status: early release. The option shape may still change before 1.0. The memory
layers underneath are the ones the ZenBrain paper
describes and the
benchmarks measure.
ZenBrain as Vercel AI SDK middleware. Recall what is relevant before
the model call, store the turn after it. Works with any provider the AI SDK supports,
because it never touches the provider.
npm install @zensation/ai-sdk @zensation/core @zensation/adapter-sqlite ai @ai-sdk/openai
This package is ESM. require() loads it on Node 22.12 and later; on Node 22.0–22.11, use import.
import { generateText, wrapLanguageModel } from 'ai';
import { openai } from '@ai-sdk/openai';
import { MemoryCoordinator } from '@zensation/core';
import { SqliteAdapter } from '@zensation/adapter-sqlite';
import { zenbrainMemory } from '@zensation/ai-sdk';
const coordinator = new MemoryCoordinator({
storage: new SqliteAdapter({ filename: './memory.db' }),
});
const model = wrapLanguageModel({
model: openai('gpt-5'),
middleware: zenbrainMemory({ coordinator }),
});
await generateText({ model, prompt: 'Anna moved to Hamburg in March.' });
const { text } = await generateText({ model, prompt: 'Where does Anna live?' });
Between the two calls nothing was passed by hand. The second prompt arrives at the model
with a system message in front of it:
Relevant memories from earlier sessions:
- Anna moved to Hamburg in March.
Zero runtime dependencies
The middleware is a plain object; wrapLanguageModel is called by you. Nothing here is
imported from ai at runtime — only its types are. So this package installs nothing:
@zensation/ai-sdk | 0 |
@zensation/core | 1 (@zensation/algorithms) |
@zensation/algorithms | 0 |
That claim is checked in CI on every push
against the packed tarballs rather than the source tree.
Options
zenbrainMemory({
coordinator,
recall: {
limit: 5,
layers: ['semantic', 'core'],
minConfidence: 0.6,
taskType: 'coding',
},
store: {
user: true,
assistant: false,
context: 'work',
},
header: 'Relevant memories from earlier sessions:',
onError: (err, phase) => console.warn(`[zenbrain] ${phase} failed`, err),
});
Two defaults worth knowing
Replies are not stored by default. A model's answer is derived from the question and
cheap to regenerate; storing both sides doubles the volume and fills semantic memory with
your own model's phrasing. Turn it on with store: { assistant: true } when the answer
carries information the question does not.
Failures are swallowed. If recall or store throws, the call goes through anyway,
unmodified. A memory layer that breaks a chat is worse than one that forgets. Pass
onError to see what is being hidden — without it, failures are silent by design.
Where the memory lands
Routing on store is automatic: a general statement becomes a semantic fact, a narrated
event an episode, a sequence of instructions a procedure. Which layer a memory lands in
decides how it decays and whether it survives consolidation. The seven layers, their
retention rules and the algorithms behind them are documented in the
main README.
Consolidation does not run on its own. Call coordinator.consolidate() on a schedule that
suits your application.
What this release does not do
- No embedding provider is configured unless you pass one. Recall then ranks
lexically rather than semantically: folded token overlap, rarer words weighted higher,
a bonus for an adjacent phrase, over the most recent 500 entries per layer. It matches
wording, not meaning — synonyms need an
EmbeddingProvider, which is also the
configuration the published benchmarks were measured with.
- Streaming stores on flush. The reply is written once the stream completes. An aborted
stream stores the user's turn but not the partial answer.
- Only text is read. File and tool parts of a message are ignored when building the
recall query and when storing.
- One recall per call. There is no re-retrieval mid-generation.
Streaming
streamText works the same way and passes the stream through untouched:
const result = streamText({
model: wrapLanguageModel({
model: openai('gpt-5'),
middleware: zenbrainMemory({ coordinator, store: { assistant: true } }),
}),
prompt: 'Which theme should I use?',
});
for await (const chunk of result.textStream) process.stdout.write(chunk);
About ZenBrain
ZenBrain is a seven-layer, neuroscience-derived memory architecture for LLM agents, built as
zero-dependency TypeScript and published under Apache-2.0. The benchmark results, and the
configuration they were measured in, are reported in the paper; the reproduction packages
are on Zenodo.
Works out of the box without an embedding provider — lexical ranking, zero
dependencies. The paper's measurements used nomic-embed-text as the embedding provider.
License: Apache-2.0