# Memory (/docs/memory)

Memory preserves the part of an agent setup that should outlive a client or
conversation. A user can move from Claude Code to Codex—or replace the agent
entirely—without rebuilding stable preferences, facts, and project decisions.

The organization owns its memory. Each write is scoped as shared or private
inside that organization, and CoreSpeed derives the caller identity from auth;
the agent cannot supply a different user ID to cross the boundary. The
boundary is enforced in Postgres by row-level security, not only in
application code.

## Tools \[#tools]

Names below are the operations exposed on the unified MCP surface:

| Tool                        | Use it for                                                                                |
| --------------------------- | ----------------------------------------------------------------------------------------- |
| `memory__remember`          | Save one concise fact, preference, or decision.                                           |
| `memory__search`            | Find memories relevant to the current task.                                               |
| `memory__get`               | Read one memory in full by ID.                                                            |
| `memory__ingest`            | Save recent messages as memories, one memory per message (at most 4,000 characters each). |
| `memory__update`            | Correct an existing memory by ID — or, for a teammate's, propose the correction.          |
| `memory__delete`            | Remove one of your own memories.                                                          |
| `memory__list`              | List memories newest first, a page at a time.                                             |
| `memory__clear_all`         | Delete all memory after explicit confirmation.                                            |
| `memory__link`              | Link one of your memories to another one you can see.                                     |
| `memory__unlink`            | Remove one of those links.                                                                |
| `memory__list_links`        | List a memory's links, outbound or inbound.                                               |
| `memory__archive`           | Retire a stale memory, naming the one that supersedes it.                                 |
| `memory__restore`           | Bring an archived memory back.                                                            |
| `memory__list_proposals`    | List proposed changes to memories you can see.                                            |
| `memory__withdraw_proposal` | Take back a proposal you made.                                                            |

These fifteen are the whole public surface — eleven for an organization
without memory maintenance, which is served neither the last four nor the
proposal path of `memory__update` (see
[Keeping shared memory accurate](#keeping-shared-memory-accurate)). Retrieval underneath them is
hybrid — exact and relaxed lexical matching, entity aliases, and vector
similarity, fused into one ranking — but it is reached through
`memory__search` rather than exposed as separate knobs.

## Long memories come back as excerpts \[#long-memories-come-back-as-excerpts]

`memory__search` and `memory__list` return many memories at once,
so they bound how much text each one contributes. A memory of 1,200 characters
or fewer — the overwhelming majority — is returned whole. A longer one is
returned as an excerpt, marked in the result:

```json
{
  "id": "0b5f…",
  "memory": "Escalation runbook: page the on-call rotation first…",
  "truncated": true,
  "full_length": 5310
}
```

For a search hit the excerpt is the passage that actually matched the query,
not the head of the memory — the same chunk the ranking scored. `list_memory`
has no query to be relevant to, so it excerpts from the start.

Pass the `id` to `memory__get` to read the whole thing. That read follows
normal visibility: your own private memories plus the organization's shared
ones, whoever wrote them.

A whole result is bounded too, not just each row in it. If the memories that
matched would together exceed what a client can receive, the lowest-ranked ones
are dropped and the result says how many:

```json
{ "memories": [ /* … */ ], "omitted": 29 }
```

The top hit is always returned, however large. In practice the default
`limit` of 10 never reaches the budget — only an explicitly high `limit` does.
Narrow the query or lower `limit` to see what was dropped.

## Shared and private context \[#shared-and-private-context]

`memory__remember` accepts `scope: "shared" | "private"`:

* `private` is the default and can be read only by the member who created it.
* `shared` must be asked for explicitly, and can then be read by agents
  operating inside the same organization boundary.

Member state is always organization-scoped. Turning memory off in one
organization cannot affect the same user in another organization.

## Links between memories \[#links-between-memories]

A link is a durable, directed edge from a memory you own to any memory you can
see, named by its two ids and a `kind` — `"related"` unless you choose another,
such as `"depends-on"`. `"supersedes"` is reserved: archiving writes it. The `related_ids` argument of
`memory__remember`, `memory__ingest`, and `memory__update` writes
`related` links; `memory__link` writes any kind, with an optional
`weight` from 0 to 1.

Linking is safe to repeat: the same call again changes nothing, and a call with
a new weight replaces the old one. `memory__unlink` removes exactly the
link its key names. `memory__list_links` reads a memory's links back,
newest first, and lists only links whose two memories you can see — a link to
a teammate's private memory stays invisible to you, as that memory does.

The graph in [Dashboard → Memory](https://app.corespeed.io/memory) draws every
link. A memory can hold up to 1,000 outgoing links and 16 kinds toward any one
other memory; past a bound the call answers `link_capacity_exceeded`.

## Keeping shared memory accurate \[#keeping-shared-memory-accurate]

Memory maintenance — archive and restore, proposals, and version history — is
rolling out organization by organization. Until yours has it, the archive,
restore, and proposal tools are not in `tools/list`, a teammate's memory is
changed only by its author, and the dashboard shows none of it.

A shared memory is read by every agent in the organization, so a stale one
misleads all of them — and a correction saved next to it does not stop the old
one being retrieved. Retire it instead:

* **Archive.** `memory__archive` takes the memory out of search, lists,
  and the memory index every session starts with. `superseded_by` names the
  memory that replaces it; reading the archived one by id says so. Nothing is
  deleted, and `memory__restore` brings it back.
* **Your own memories** are archived, restored, or corrected at once. So are
  an agent's memories for the member accountable for that agent.
* **A teammate's memory** changes through a proposal. `memory__update`,
  `memory__archive`, and `memory__restore` on it take a `reason`
  and answer `status: "proposed"`. The memory's author — or an org admin —
  merges or rejects it in [Dashboard → Memory → Proposals](https://app.corespeed.io/memory/proposals),
  like a pull request. An agent can propose but never merge.
* **Needs my review** holds only what others proposed. Your own pending
  proposals stay under **Mine**. On a wide screen, `j` and `k` move between
  proposals, and `m` and `r` open the focused one's Merge or Reject.
* A proposal is written against the memory's current version. If the memory
  changes before review, merging records the proposal as `outdated` and
  applies nothing; nothing is ever rebased.

Every change keeps the memory's three most recent prior versions, with who
replaced each; the memory's page lists them and can restore one. Pending
proposals expire after 30 days, and resolved ones leave after another 30.

## Pricing and holds \[#pricing-and-holds]

Saving costs **1 credit per memory**, and one memory holds at most 4,000
characters: save longer text as several memories. That covers each memory
`memory__remember` saves, each memory `memory__ingest` saves, and a
`memory__update` that changes a memory's text. Everything else costs nothing:
search, reads and lists, an update that changes only the pin, scope,
category, tags or links, proposals, and delete, archive, restore and link.
Every charge appears in the activity log. An update that repeats text already
saved is not charged again.

When the organization runs out of credit, or an API key reaches its monthly
spend cap, every memory call is refused with `payment_required` or
`key_spend_limit_exceeded`, reads included, until credit is added or the month
rolls over. A suspended organization is refused everything. Storage quotas and rate limits protect the shared service.

## Inspect and remove memory \[#inspect-and-remove-memory]

Use [Dashboard → Memory](https://app.corespeed.io/memory) to browse memories,
search, inspect the graph, open a detail view, and delete content — and, with
memory maintenance, archive memories and review proposals. Disabling the
memory capability hides its MCP tools but preserves existing data; deletion is
a separate explicit action.

## What belongs in memory \[#what-belongs-in-memory]

Save context that will improve a later action: a preference, a product
decision, a named relationship, or an operating constraint. Do not use memory
as a transcript archive, a secret store, or a substitute for application data.