Persistent, embeddings-backed memory for agents — store facts and entities, recall them semantically, in one import.
Install · Quick start · API · How it works · three.ws
@three-ws/agent-memoryis the official client for the three.ws Memory engine — the durable, embeddings-backed memory that gives an agent continuity across sessions. Your agentremember()s a fact, thenrecall()s it later by meaning, not keyword: a real semantic search over stored vectors. It wraps the live/api/agent-memoryand/api/memory/*endpoints — a tiered store (working / recall / archival), free-first embeddings, and an auto-mined entity graph of the mints, tickers, wallets, people, and strategies your agent has seen. It pairs with the talking-agent runtime: the same memories that feed the Brain Memory node power your agent's replies.
Every "agent memory" you reach for is either an in-process array that dies with the process, or a raw vector DB that leaves embedding, tiering, entity extraction, ownership, and the cross-model "different vectors, different space" trap to you. Memory is the whole pipeline, done once:
- One import, durable recall.
remember('User prefers SOL over EVM')writes a memory that's still there next session — andrecall('which chain?')finds it by meaning. - Free first. Embeddings default to NVIDIA NIM's
nv-embedqa-e5-v5(1024-dim, free with one key); OpenAItext-embedding-3-smallis the paid backstop. No vector DB to stand up. - No fabricated similarity. Each stored vector is tagged with the model that made it; queries are scored strictly within their own space. When no provider is configured, recall degrades to substring + salience — never a fake cosine score.
- It builds a graph for free. Every memory is mined (deterministically, no LLM call) for the entities it mentions, so you can ask "what does my agent remember about this mint?" and walk a co-occurrence graph.
This is the SDK twin of the three.ws Memory Studio — the same engine, exposed as plain functions instead of a UI.
npm install @three-ws/agent-memoryZero runtime dependencies. Works in Node 18+ and the browser (uses fetch).
Writes require a signed-in three.ws account or a bearer token (see
Auth); reads are owner-only.
Bind a client to one agent, then remember and recall:
import { AgentMemory } from '@three-ws/agent-memory';
const memory = new AgentMemory({ agentId: AGENT_ID, token: process.env.THREE_WS_TOKEN });
await memory.remember('User prefers Solana over EVM chains', { tags: ['preference'] });
const hits = await memory.recall('which blockchain does the user like?');
console.log(hits[0].content); // → "User prefers Solana over EVM chains"
console.log(hits[0].score); // → 0.83 (real cosine; null on a lexical fallback)Pin something to the always-in-context working core, then read what the agent carries into every reply:
await memory.remember('Never risk more than 2% per trade', {
tags: ['strategy'],
pinned: true, // → working tier, always in context
});
const ctx = await memory.context();
console.log(ctx.tokens, '/', ctx.budget, 'tokens in core'); // → 41 / 2000Walk the entity graph the store mined for you:
const { nodes, edges } = await memory.graph();
// nodes: [{ kind: 'strategy', label: 'Never risk more than 2%…', mentions: 1 }, …]| Option | Type | Default | Notes |
|---|---|---|---|
agentId |
string |
— | Required. The agent these memories belong to. |
token |
string |
— | Bearer token for writes (or use cookie session in-browser). |
baseUrl |
string |
https://three.ws |
Override for self-host / preview. |
fetch |
typeof fetch |
global fetch |
Inject a custom fetch (e.g. an x402 payer). |
Store (or upsert) a memory. Wraps POST /api/agent-memory { agentId, entry }.
| Option | Type | Default | Notes |
|---|---|---|---|
type |
'user' | 'feedback' | 'project' | 'reference' |
'project' |
Memory category. Invalid values fall back to project. |
tags |
string[] |
[] |
Topic tags — also mined into entity/topic nodes. |
context |
object |
{} |
Structured fields ({ mint, symbol, wallet }) extracted as entities. |
salience |
number |
0.5 |
Importance, 0..1. Drives ranking and tier. |
pinned |
boolean |
false |
Pin to the working core (forces tier: 'working'). |
tier |
'working' | 'recall' | 'archival' |
auto | Defaults: pinned → working, low-salience reference → archival, else recall. |
id |
string |
— | Pass to upsert an existing memory idempotently. |
expiresAt |
number | string |
— | Auto-expiry timestamp. |
Returns the stored Memory (see shape). Content is capped at
10,000 chars. Changing an existing memory's content resets its vector and mined
entities, so it re-indexes on the next read.
Semantic search over the agent's memories. Wraps POST /api/memory/search.
| Option | Type | Default | Notes |
|---|---|---|---|
topK |
number |
8 |
Max results, clamped 1..50. |
minScore |
number |
0.25 |
Min cosine similarity, 0..1. |
tiers |
string[] |
all | Restrict to e.g. ['working', 'recall']. |
type |
string |
all | Restrict to one memory type. |
Each result carries a score (cosine, 4-dp) and match of 'semantic' or
'lexical'. Results are semantic-first, then back-filled with salience-ranked
substring hits so a query is never empty just because a provider is down.
Recalling a memory bumps its accessCount and salience slightly — the
recency/reinforcement loop the tiers rely on.
The knowledge-graph nodes the agent's memories mention. Convenience over
graph() — returns nodes ranked by mention count.
The full temporal knowledge graph. Wraps GET /api/memory/graph. nodes are
entities (kind ∈ mint | ticker | wallet | person | strategy | topic);
edges are co-occurrence links weighted by how often two entities share a
memory. Lazily mines any not-yet-processed memories on read.
Memories that mention a given entity node. Wraps
GET /api/memory/graph?entityId=. Powers node drilldown ("what does my agent
remember about this mint?").
The "in-context now" working set: pinned + working-tier memories with a live
token budget. Wraps GET /api/memory/context.
type Context = {
entries: Memory[];
tokens: number; // estimated tokens in the working core
budget: number; // 2000 — the working-core token budget
overBudget: boolean; // tokens > budget
counts: { total, working, recall, archival, embedded };
};Every memory for the agent (newest, salience-first). Wraps
GET /api/agent-memory?agentId=. Options: type, since (ms), limit
(≤ 500, default 200).
Owner-only edits over POST /api/memory/curate:
| Method | Op | Effect |
|---|---|---|
pin(id) / unpin(id) |
pin / unpin |
Move in/out of the working core. |
retier(id, tier) |
tier |
Set working | recall | archival. |
setSalience(id, n) |
salience |
Set importance, 0..1. |
edit(id, { content?, tags? }) |
edit |
Re-embeds + re-mines on content change. |
merge([target, ...dupes]) |
merge |
Fold duplicates into one; re-indexes. |
forget(id) |
forget |
Delete a memory. |
type Memory = {
id: string;
type: 'user' | 'feedback' | 'project' | 'reference';
content: string;
tags: string[];
context: object;
salience: number; // 0..1
tier: 'working' | 'recall' | 'archival';
pinned: boolean;
embedder: string | null; // e.g. "nvidia/nv-embedqa-e5-v5@1024"
hasEmbedding: boolean;
accessCount: number;
tokens: number; // ~chars/4
createdAt: number; updatedAt: number;
lastAccessedAt: number | null; expiresAt: number | null;
// recall() only:
score?: number | null; // cosine, or null for a lexical hit
match?: 'semantic' | 'lexical';
};Three layers turn a string into durable, recall-able memory — a write path, a read-triggered indexing pass, and a query path:
remember(text) ──▶ POST /api/agent-memory ──▶ agent_memories (Postgres)
│
read of recall()/graph() triggers lazy indexing (best-effort, bounded)
▼
┌──────────────── embed ────────────────┐ ┌──────── mine ────────┐
│ NIM nv-embedqa-e5-v5 @1024 (free) │ │ deterministic entity │
│ → OpenAI text-embedding-3-small @256 │ │ extraction (no LLM) │
│ vector tagged with its embedder │ │ → entity nodes+links │
└────────────────────┬───────────────────┘ └──────────┬──────────┘
▼ ▼
recall(query) ──▶ cosine within the SAME vector space ──▶ ranked Memory[]
(lexical + salience fallback) graph(): nodes + edges
- Tiers (Letta/MemGPT model).
workingis the small, always-in-context core (pinned + active rules), token-budgeted at 2000 tokens.recallis recent, searchable interactions.archivalis the long-term store. A new memory's tier is chosen for you unless you set it. - Free-first embeddings. New writes embed with NVIDIA NIM
nv-embedqa-e5-v5(1024-dim, free with oneNVIDIA_API_KEY); OpenAItext-embedding-3-smallat 256 dims is the paid backstop. Embedding happens lazily on read, in bounded batches, so no write blocks on a provider. - One space, never crossed. Every vector is stored tagged with the exact
model that produced it. A query is embedded once per stored space and cosine
runs strictly within each — vectors of different dimensionality score
0, never a plausible-looking garbage similarity. - Auto-mined graph. Each memory is pattern-matched (deterministic, dependency-
free) for mints,
$TICKERcashtags, wallet addresses,@handles, and trading strategies. Entities become graph nodes; co-occurrence within a memory becomes a weighted edge.
Reads are owner-only: anonymous or non-owner requests get an empty result
(an empty array / zeroed context), never a leak and never a 401 that spams a
public embed console. Writes require auth and surface as a thrown
MemoryError with a code:
code |
HTTP | Meaning | Recovery |
|---|---|---|---|
unauthorized |
401 | Write with no session / token. | Pass a token, or sign in. |
forbidden |
403 | Agent isn't yours. | Use an agentId you own. |
not_found |
404 | Agent or memory doesn't exist. | Check the id. |
id_conflict |
409 | Upsert id already used by another agent. | Omit id to mint a new one. |
validation_error |
400 | Missing agentId / content / bad field. |
Fix the input. |
Browser writes also need a CSRF token (handled automatically by the three.ws
session cookie flow); server-to-server calls authenticate with a bearer
token.
Agent loop — remember every turn, recall before replying:
const memory = new AgentMemory({ agentId, token });
async function onUserMessage(text) {
const recalled = await memory.recall(text, { topK: 5 });
const reply = await llm(text, { memories: recalled.map((m) => m.content) });
await memory.remember(`User said: ${text}\nAgent: ${reply}`, { type: 'user' });
return reply;
}Record a trade with structured context — it extracts the entities for you:
await memory.remember('Sniped a fresh launch, took profit at 3x', {
tags: ['trade', 'lesson'],
salience: 0.8,
context: { mint: 'THREEsynthetic1111111111111111111111111111', symbol: '$THREE' },
});
const { nodes } = await memory.graph(); // mint + ticker nodes now linkedCurate the working core so it stays under budget:
const ctx = await memory.context();
if (ctx.overBudget) {
// demote the least-salient working memory to recall
const weakest = ctx.entries.sort((a, b) => a.salience - b.salience)[0];
await memory.retier(weakest.id, 'recall');
}@three-ws/forge— give your remembering agent a body: text/image → rig-ready 3D GLB.@three-ws/avatar— render and animate that agent in the browser.@three-ws/x402-fetch— inject a payingfetchfor paid three.ws lanes.
Built by three.ws · The only coin is $THREE
If agent-memory saves you time, star it on GitHub. Stars are how other developers and AI agents find the repositories worth trusting, and they cost you one click.
Know someone who would use it? Post on X · Share on Bluesky · Share on LinkedIn · Submit to Hacker News · Share on Reddit
Coding agents and LLM tooling can read this repo directly: AGENTS.md, llms.txt, llms-full.txt. Point an agent at https://github.com/nirholas/agent-memory and it has the context it needs.
- All repositories by nirholas: the full catalog, grouped by topic
- three.ws: the platform for 3D AI agents with Solana wallets, a skill marketplace and x402 payments
- Questions or ideas: open an issue or start a discussion
three.ws is a platform for 3D AI agents with Solana wallets: avatars, a skill marketplace, x402 payments and more than seventy MCP servers. @three-ws/agent-memory is one package from it.
- Documentation site: https://nirholas.github.io/agent-memory/
- npm: https://www.npmjs.com/package/@three-ws/agent-memory
- Canonical source: https://github.com/nirholas/three.ws (this repository is a generated mirror of
packages/agent-memory) - Agent-readable summary: llms.txt and AGENTS.md
- Issues and ideas: https://github.com/nirholas/agent-memory/issues