# 🤖 Eleven's memory — remembered by the bot, owned by the member

*"What's your role?" — asked for the third time this week.* Without memory,
an AI helper's entire knowledge of a member is the last ~30 messages of the
current thread: every DM is groundhog day. This document describes the
memory that fixes it, and the property that makes it acceptable: **nothing
the bot remembers is ever invisible, uneditable, or unerasable.**

## What it is

A small set of durable facts (max 24, ≤ 280 chars each) an AI helper keeps
about a member — role, standing preferences, anything the member asked it to
keep. Two halves, one store:

- **The bot's half** (`internal/bot/memory.go`): `remember` / `forget` tools
  offered to the conversational brain in DMs only. What's remembered rides the
  DM's system context (after the cache breakpoint, like a bot-home thread's
  charter note), so the helper simply *knows* — and it's told to never claim a
  memory that isn't in the list.
- **The member's half** (`web/static/apps/memory.js`): the **scratchpad** — a
  command panel opened by `/memory`, the chat's ⋮ menu → Memory, or the chip
  every write attaches. It shows every fact and lets the member edit any of
  them, add their own, delete one, or erase everything. Memory the member
  can't inspect is creepy; memory they can is a feature.

## Where it lives (the trust model)

The `"memory"` slot of the **DM thread's state store** (`miniapps.go` —
`GET/PUT /api/threads/{id}/state`, optimistic versioning), encrypted under
the **DM's thread key**. That one choice does the heavy lifting:

- **E2EE to exactly two parties.** Only the member and that bot hold the DM
  key. Not the instance key (which every member holds) — things learned in a
  private conversation stay in that conversation's trust class. The server
  stores ciphertext, as ever.
- **Per relationship.** Your memory with Eleven is not your memory with
  Claude — each DM has its own slot under its own key. Retiring a helper (or
  ending the DM) strands nothing anywhere else.
- **No new server surface.** The slot machinery, versioning, and member
  gating already existed for app-state snapshots; memory is one more slot
  (`"memory"`, distinct from `"apps"`, so the two never contend).

Writes are whole-blob at the version read; a concurrent write 409s and the
loser reloads (the sidecar retries its op against the fresh copy; the
scratchpad shows the latest and the member redoes the edit). Both readers
re-clamp whatever they read (`clampMemory` in Go, `sanitizeMemory` on the
web — unsigned shared slot, so read-side clamping is the invariant).

## Transparency rules

- **Every write announces itself.** The sidecar — never the model — appends
  an `open_memory` chip to any reply whose turn performed a remember/forget
  ("✍️ Noted — see what I remember"). No silent writes.
- **DM-only.** The tools and the recall exist only in the DM where the memory
  lives. Group-Eleven never reads DM-derived memory — whether it ever should
  is a deliberate future decision, not a default.
- **Hygiene in the tool contract.** The `remember` description forbids
  secrets (passwords, keys, codes) and sensitive details (health, finances,
  other people's private business) unless the member explicitly asks, and the
  model is told to store one short third-person fact per call.
- **Bounded.** 24 facts × 280 chars keeps the whole memory a few hundred
  tokens of context and one small ciphertext blob.

## Scope

Web-first (stated): the scratchpad is a web command panel; native renders AI
DMs through the webview surfaces today. The `open_memory` chip type is
whitelisted on web (`ui.js CHIP_TYPES`) and unknown to native clients, which
drop unrecognised chips — the reply text still reads fine. Natural next
rungs: the panel's `side` placement everywhere (#816 ships it), surfacing
memory in the member's bot-home threads, and a deliberate design for whether
any of it may inform group replies.
