Memory

Give an end user context that persists across turns, and inspect or erase it.

Memory is what the agent carries from one turn to the next. Without it, every turn starts cold: your user restates that revenue means net revenue, that they only care about the EU region, that they want figures in millions — every single time.

Memory is scoped by a namespace you choose. Typically that is your own end-user id, so each of your users accumulates their own context.

How it works

Memory is written by the agent, during a turn — not by you through this API. You switch it on by naming a namespace on the turn:

{
  "projectId": 1,
  "question": "From now on, always show revenue in millions.",
  "memoryNamespace": "user-42"
}

Two things follow from that one field:

  1. The agent is given its memory tools, so it can save what it learns.
  2. Whatever that namespace already holds is injected into the agent's prompt at the start of the turn — so it starts the turn already knowing, rather than having to think to go look.

Omit memoryNamespace and memory is off entirely — the agent is not given the tools at all. That is the right default for stateless automation.

On the next turn with the same namespace, the preference is already in play:

{
  "projectId": 1,
  "threadId": 9,
  "question": "What was Q3 revenue?",
  "memoryNamespace": "user-42"
}
event: answer
data: {"block_id":3,"content":"Q3 revenue was $4.2M."}

Memory is not tied to a thread. The same namespace on a brand-new thread still recalls it.

Namespace rules

RuleDetail
FormatMust match ^[a-zA-Z0-9][a-zA-Z0-9_-]{0,127}$ — a single flat token, so / is not accepted. Anything else is rejected with 400 before the turn starts.
IsolationNamespaces are isolated from each other and from your workspace's own users. A namespace can never address a real Wren user's memory.
RolesAny role may write memory — viewer included. It is not a privileged operation.

Endpoints Overview

This surface is read and wipe only, mirroring what the web app exposes. Writing is the agent's job.

EndpointWhat it does
GET /v2/projects/{projectId}/memories/{namespace}Inspect a namespace — its MEMORY.md and file manifest.
GET /v2/projects/{projectId}/memories/{namespace}/fileRead one file out of the namespace.
DELETE /v2/projects/{projectId}/memories/{namespace}Erase the namespace.

Basic Usage

See what the agent has remembered about one of your users:

{
  "namespace": "user-42",
  "content": "- Revenue always means net revenue.\n- Show figures in millions.\n- Default region filter: EU.",
  "files": ["MEMORY.md", "notes/pricing-model.md"]
}

content is the namespace's MEMORY.md — the summary the agent actually reads. files is everything stored in the namespace; read any of them individually:

{
  "namespace": "user-42",
  "path": "notes/pricing-model.md",
  "content": "Enterprise tier is billed annually in advance..."
}

Erase it when the user asks you to, or when you delete their account:

{
  "namespace": "user-42",
  "wiped": true
}

The delete is scoped to one namespace and {namespace} is required — an unscoped wipe is refused with 400, so you cannot erase every user's memory by leaving a variable empty.

Using it in an embedded app

// Pass your own user id as the namespace on every turn for that user.
const memoryNamespace = `user-${currentUser.id}`;

await streamAgentAsk({ projectId, question, threadId, memoryNamespace });

// Let the user see what has been remembered about them...
const { content, files } = await get(
  `/v2/projects/${projectId}/memories/${memoryNamespace}`,
);

// ...and let them clear it.
await del(`/v2/projects/${projectId}/memories/${memoryNamespace}`);

Surfacing "what Wren remembers about me", with a way to clear it, is worth building. The namespace maps to one of your users, so DELETE is the operation you wire to their data-deletion request.

🔗

Learn more