> ## Documentation Index
> Fetch the complete documentation index at: https://docs.memanto.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Memory Lifecycle

> Every memory is active or expired. Expiry is policy-driven, auditable, and reversible.

# Memory Lifecycle

A memory is in exactly one of two states:

| State         | Meaning                                                                                           |
| ------------- | ------------------------------------------------------------------------------------------------- |
| **`active`**  | Live. Returned by recall, counted by every sweep. This is where every memory starts.              |
| **`expired`** | Retired. Content is fully intact and still recallable, but clearly labelled as no longer current. |

There is no third state. Expiring is **reversible** — the memory keeps its content, its
timestamps, and an audit trail of why it was retired. Deleting is a separate,
permanent operation.

<Note>
  Nothing expires on its own. A memory becomes `expired` only when an expiry
  **policy sweep** runs, a **conflict resolution** retires it, or you expire it by
  hand. An agent with no policy set will never expire anything.
</Note>

## The expiry stamp

When a memory moves to `expired`, three fields are written together:

<ParamField body="status" type="string">
  Becomes `expired`.
</ParamField>

<ParamField body="expired_at" type="string">
  ISO-8601 timestamp of when it expired.
</ParamField>

<ParamField body="expired_by" type="string">
  Why it expired — a policy rule name (`scratch-notes`), a retention-table entry
  (`retention.context`), `manual`, or `conflict-resolution`.
</ParamField>

Restoring clears all three. Because `status == "expired"` always carries a *when*
and a *why*, recall can tell you exactly which rule retired a memory and when:

```
[EXPIRED] Deploys are manual via ssh
Expired Aug 18, 2026 03:56 PM · policy: retention.context
```

## Recall shows both states

By default recall returns active **and** expired memories together, each labelled.
Expired memories are surfaced to the reader, not hidden from them. Narrow with the
`status` filter (`--active` / `--expired` on the CLI):

```bash theme={null}
memanto recall "deploy process"             # both, labelled
memanto recall "deploy process" --active    # active only
memanto recall "deploy process" --expired   # expired only
```

Point-in-time recall is unaffected: [`--as-of`](/cli/search/recall) reconstructs
what was true at a past date, so a memory that was live then is returned as
`active` even if it has expired since. This is why the expiry stamp is a stored
fact rather than something recomputed on every read.

## Expiry policies

A policy has two complementary halves, stored per agent at
`~/.memanto/policies/<agent-id>.yaml`:

```yaml theme={null}
version: 1
retention:                 # broad strokes, per memory type
  context: 7d
  event: 30d
  preference: never
rules:                     # sharper; first match wins over the table
  - name: pinned
    match: {tags: [pinned]}
    expire_after: never    # pins a memory the table would otherwise expire
  - name: low-confidence-imports
    match:
      provenance: [imported]
      confidence_below: 0.5
    expire_after: 7d
purge_expired_after: never
```

**`retention`** maps a [memory type](/reference/memory-types) to a maximum age.
**`rules`** are named match blocks checked in order — the first one that matches
wins and short-circuits the table, so a rule with `expire_after: never` acts as a
pin. A rule's `name` is what gets stamped as `expired_by`.

### Match conditions

Every condition you set must match (AND). An empty `match` block matches everything.

| Condition          | Matches on                                                 |
| ------------------ | ---------------------------------------------------------- |
| `type`             | List of memory types                                       |
| `tags`             | Memory has any of these tags                               |
| `source`           | List of writer labels (`user`, `cursor`, `claude_code`, …) |
| `provenance`       | List of provenance values (`imported`, `inferred`, …)      |
| `confidence_below` | Stored confidence strictly below this number               |

### Durations

`30m`, `12h`, `7d`, `2w`, `3mo`, `1y`, or `never`. A month is 30 days — calendar
months have no fixed length, and an expiry window does not need one.

<Note>
  Age is measured from `updated_at`, falling back to `created_at`. Editing a memory
  is evidence it is still live, so an edit resets its expiry clock.
</Note>

## Running a sweep

Saving a policy changes nothing on its own. A sweep is what stamps memories:

```bash theme={null}
memanto policy apply --dry-run   # show the policy and every match, then stop
memanto policy apply             # same preview, then asks to confirm
```

The nightly [`memanto schedule enable`](/cli/schedule/enable) job runs the sweep
for you after the daily summary and conflict detection.

## Purging

`purge_expired_after` is the **only** destructive automatic step, and it is off by
default. It permanently deletes memories that have *already been expired* for
longer than the given window.

<Warning>
  Purging is irreversible and unrelated to what the retention table expires.
  `retention` decides what becomes `expired`; `purge_expired_after` decides when an
  already-expired memory is destroyed. A policy where `apply` reports 0 matches can
  still have memories eligible for purge — the two act on different populations.
</Warning>

## Presets

Three bundles ship as starting points, adoptable in one command and editable
afterwards:

| Preset         | Shape                                                                         |
| -------------- | ----------------------------------------------------------------------------- |
| `conservative` | Only fast-rotting state ages out. Nothing is ever purged.                     |
| `balanced`     | Transient state in weeks, semantic knowledge in months, durable truths never. |
| `aggressive`   | Tight working set; expired memories purged after a year.                      |

In all three, `preference`, `instruction`, and `relationship` never expire on a
timer, and anything tagged `pinned` is exempt.

```bash theme={null}
memanto policy list-preset
memanto policy apply-preset balanced
```

## Next Steps

* [`memanto policy apply`](/cli/policy/apply) — run a sweep
* [`memanto memory expire`](/cli/data/expire) — retire one memory by hand
* [Get Expiry Policy](/api-reference/policy/get-policy) — the REST surface
* [Memory Types Reference](/reference/memory-types)
