Memory Bank
The Memory Bank is the vault’s long-term memory: what its agents and workflows have learned, and how each run builds on the ones before it. It belongs to the vault, so it belongs to the customer. Agents come and go; the Memory Bank stays.
What it holds
A graph of records and relations.
| Record field | Meaning |
|---|---|
id |
Stable id you choose. Writing the same id again updates the record. |
type |
What kind of thing it is, e.g. fact, decision, principle, note. |
title, body |
The content. |
scope |
Where it lives: the vault scope that governs who may read it. |
privacy |
How sensitive it is: public, internal, private, or restricted. |
A relation is a directed, typed edge from one record (in) to another
(out). It carries its own scope and privacy, because a link can be more
sensitive than the records it joins.
Records also move through review states (proposed, accepted, rejected,
superseded). Reads return accepted records unless they ask for other states.
Two axes of access
Every read is gated twice:
- Scope decides where a reader may look. A reader sees only scopes their grants reach. An ungranted scope returns no rows, never an error.
- Privacy decides how sensitive a fact a reader may see. A vault member can hold a privacy ceiling (Public, Internal, Private, or Restricted).
A run reads with the permissions of the person who started it.
How data gets in
Writes come from agents and workflows only. Your app reads the Memory Bank but cannot write to it.
| Writer | How |
|---|---|
| A workflow | remember (file a record) and relate (link two records) steps. |
| A code agent | ctx.memory.upsert(record), .update(id, patch), .setPrivacy(id, privacy), .delete(id), .relation(edge). |
privacy is required on every write and never defaulted. Before filing
anything, answer: who reads this later, and does each row need its own
visibility?
await ctx.memory.upsert({ id: `decision:${ticketId}`, type: "decision", title: "Refunds over 500 need a second approver", body: "Agreed after the March audit.", scope: "finance", privacy: "internal",});await ctx.memory.relation({ in: `decision:${ticketId}`, out: "principle:four-eyes", type: "applies", scope: "finance", privacy: "internal",});Work in progress belongs in a cubby. File only what the organization should keep.
How agents and workflows read it
| Reader | How |
|---|---|
| A workflow | recall step: search, then read each hit’s body. |
| A code agent | ctx.memory.search(match, { limit }), .get(id), .neighbours(id, { limit }), .countByType(). Rows come back as plain objects. |
| A widget | A named query with tool: "search" | "get" | "neighbours" | "countByType". See Widgets. |
| Your app | vault.memory.search, .list, .get, .neighbours, .countByType in the Vault SDK. |
| An LLM agent | The vault’s MCP endpoint (below). |
const hits = await ctx.memory.search("refund approval", { limit: 5 });From your app
The Vault SDK returns rows exactly as the vault sends them: a columns list and
positional rows, plus a cursor when more rows exist.
const page = await vault.memory.search("refund approval", { scope: "finance", limit: 20 });// page.columns: id, type, title, scope, privacy, rank, snippetconst next = page.cursor ? await vault.memory.search("refund approval", { scope: "finance", cursor: page.cursor }) : undefined;Read neighbours rows by position: the far record’s type and the edge’s
type share a column name.
From an LLM agent: MCP
The vault serves its Memory Bank as read-only MCP tools at:
POST /api/v1/vaults/:vaultId/mcpIt is a stateless Streamable HTTP server, authenticated like any vault read. During a run, an LLM agent that receives the run’s execution token presents it, so it searches with the permissions of the person who started the run. See Authentication.
| Tool | Arguments | Limits |
|---|---|---|
search |
query, optional domains, types, statuses, limit |
limit default 10, at most 25 |
get |
ids, optional body_chars, offset |
1 to 10 ids; body_chars default 4000, at most 8000 |
neighbours |
id, optional edge_type, direction, limit |
limit default 10, at most 25 |
Search matches words of three or more letters by stem, ranks records that match
more and rarer words first, and returns ids, titles, and a snippet; call get
for full text. Tool failures come back as MCP tool errors the model can act on;
authentication failures stay HTTP 401 or 403.
In ROC
The Memory Bank page shows the vault behind the selected Agent Service, and only what your grants reach.
| Tab | Shows |
|---|---|
| Overview | Ask a question and get an answer drawn from the records only; knowledge and run counts, knowledge by type, recently changed records. |
| Journeys | Runs for one domain and subject, step by step, with key takeaways; compare a run with others. |
| Browse | Search and open records; filter to Needs review; Show run entries to include the runs’ own bookkeeping. |
| Outcomes | What a workflow wrote and what a person decided afterwards. |
