Memory model.
PAMbase is a shared memory layer for a person that any app they trust can read from and write to. The memory model is the heart of it: the rules for how a fact about a user gets in, what shape it takes once stored, and how it comes back out. This page explains those rules from scratch.
Why it matters
Most apps start every user from zero — a blank profile, a cold assistant, a “tell us about yourself” form. With PAMbase, the things a user has already told other apps are available to yours (within the permissions they grant), so your product can feel like it already knows them on first launch. You report what happens in your app; PAMbase turns that into durable, searchable knowledge you can pull back later — or that a completely different app can benefit from.
How it works: memory is natural language
A memory is just text, categorized. You write one directly with remember() — no event pipeline, no LLM required to write (it's only text). Each memory has a kind (an advisory structural hint) and a scope (its domain) — the scope is what other apps' agents match on to find it later.
// 1. The user saves a highlight.await pambase.remember({content: "Backpressure is how a system says 'slow down' instead of falling over.",kind: "event",scope: "note.reading",});// 2. Margin notices a taste over time.await pambase.remember({content: "Enjoys long-form essays on systems design.",kind: "preference",scope: "preference",});// 3. The user sets a reading goal.await pambase.remember({content: "Wants to read 24 books this year.",kind: "goal",scope: "goal",});
A scope namespaces a memory — like a folder — and it's the unit that permissions are granted over. Its top-level namespace must come from the standard scope taxonomy (so apps interoperate); sub-scopes like note.reading are free. Omit it and the memory lands in general.
remember(). Either way, the result is the same natural-language memory.What a memory looks like
Every memory PAMbase stores has the same fields, regardless of which app or event created it:
| Field | Meaning |
|---|---|
id | Stable identifier for this memory. |
type | An advisory structural hint (the kind) — commonly fact, preference, event, relationship, emotion, goal, world, or summary, but free-form. |
scope | The domain namespace from the scope taxonomy (e.g. note.reading) that permissions are granted over. |
content | Natural-language text — what your LLM reads to understand and react. Also drives semantic search. |
importance | 0–100. How much this should weigh in what comes back. |
confidence | 0–100. How sure PAMbase is the statement is true. |
pinned | Boolean. If true, the memory is always retrievable. |
occurredAt | When the underlying thing happened (drives recency). |
sourceApp | Which app reported the event behind this memory. |
kind and a scope. Any app can remember() something — it doesn't need an LLM to write. To read usefully you bring an LLM: recall() returns the relevant memories as natural language for your agent to interpret and act on. Pick the right scope so other apps' agents can recall across domains.How importance, confidence, and pinned affect retrieval
When you ask PAMbase for relevant memories (via context, search, or a hosted chat turn), it ranks candidates by combining four signals, in plain English:
- Semantic similarity — how close the memory's meaning is to your query.
- Keyword match — literal word overlap with your query.
- Recency — newer memories rank higher, on a 14-day half-life (a memory's weight roughly halves every two weeks).
- Importance — higher-importance memories rank higher.
Confidence tells you how much to trust a memory once it comes back; treat low-confidence statements with caution. Pinned is a hard override: a pinned memory is always retrievable, regardless of how it scores — users pin the things that should never be forgotten. The semantic and graph mechanics behind ranking are covered in Vector + graph.
Margin in practice
After the three memories above, Margin can find the highlight again — bring an LLM to interpret what comes back — without remembering exactly how it was worded:
const { memories } = await pambase.recall({query: "rate limiting",scope: "note",});// Returns the backpressure highlight — "rate limiting" and// "backpressure" are semantically close, even with no shared words.// memories[0].content → "Backpressure is how a system says 'slow down'…"// memories[0].type → "event"// memories[0].scope → "note.reading"
The cross-app payoff: if the user later connects a newsletter app that holds memory:read:preference, its agent can recall that same long-form-essays preference and curate without ever asking the user a single onboarding question — and without integrating with Margin at all.
Next
- Permissions — what controls which memories you may read and write.
- Remember & recall — the full read/write loop.
- Signals & reacting — notify and react across apps.
- Catalog — the memory kinds and the scope taxonomy.