# Memory

Memory helps Enso remember what happened: what you asked, what you agreed, what the
agent reported doing, and what remains unfinished. Ask about recent work or an earlier
conversation without having to repeat all its context.

Memory is **episodic**: a dated account of an event. [Knowledge](/docs/knowledge/) is
maintained reference material. Tuesday's discussion about deploying a website belongs
in Memory; the current deployment checklist belongs in Knowledge. They have separate
storage, commands, and viewer pages. Refining Memory never automatically changes Knowledge.

## Availability

This guide describes the Memory implementation in Enso's beta source. The `enso memory`
commands, Memory viewer, and bundled job and skill are not included in
[v0.1.2](https://github.com/geekforbrains/enso/releases/tag/v0.1.2), the latest published
release checked on September 15, 2026.

Run `enso memory --help` to check whether your installation includes it. If the command
is unknown, use a release that includes it when available or an intentionally installed
development build. A normal managed update installs published releases, not unreleased
development work.

## How it works

1. **Capture the conversation.** During an Enso chat turn, Enso saves the original user
   request and readable agent reply in `enso.db`. Each exchange retains its workspace,
   chat platform (the *transport*), channel, thread, sender, the provider session that
   answered, and the completion state. Enso records when the request arrived and when
   processing finished.
2. **Refine useful memories.** Every 15 minutes, the bundled `enso-memory` job reads a
   small batch of new exchanges. Its agent writes concise summaries of useful requests,
   decisions, reported outcomes, corrections, and unfinished work. Routine acknowledgements
   need no memory. Each summary links to its original exchanges; Enso derives its dates
   and origin from those sources.
3. **Recall when relevant.** The agent searches or lists memories, then reads the source
   exchanges when it needs exact wording. The bundled `enso-memory` skill explains how.
   Memory is not automatically loaded into every conversation.

Related exchanges can become one summary only when they belong to the same workspace,
conversation, transport, channel, and thread. The job can process several workspaces in
one run without merging their context. Failed refinement leaves exchanges available for
a later attempt; a successfully recorded batch is not processed again. When no new
exchanges need refinement, the job makes no model call.

## Ask Enso to remember

For example:

> What did we discuss this week in the personal workspace?

> Show me my last ten memories.

> What did we decide about the website launch? Check the original conversation.

The agent uses the same commands available in your terminal:

```bash
enso memory list --workspace personal --since week
enso memory list --limit 10
enso memory search "website launch" --workspace website
enso memory show MEM-000001 --sources
```

Replace the example ID with one returned by a list or search. Results are newest event
first. Lists show brief previews; `show` returns the complete summary, and `--sources`
adds the original clean exchanges, their times, origin, and outcome.

References such as `MEM-000001` stay with the memory. Six digits is minimum padding,
so `MEM-999999` is followed by `MEM-1000000`; deleted numbers are not reused.

### Workspace, channel, and search filters

Inside an Enso workspace, list and search default to `ENSO_WORKSPACE`. When that
environment variable is absent, they include all workspaces. Set `--workspace` to
choose one or `--all-workspaces` to broaden the query. These filters organize context;
they are not an access-control boundary.

```bash
enso memory list --all-workspaces --limit 10
enso memory list --workspace website --transport slack --channel C0123456789
enso memory search "launch" --workspace website --since 7d --limit 10 --json
```

Search matches text in summaries, not the full source exchanges. Both `list` and
`search` accept workspace, transport, channel, date, and pagination filters. Channel
means the platform's exact channel ID. The default page contains 20 entries; `--limit`
allows up to 100, and `--offset` skips earlier results. `--json` gives agents structured
results, including the total number of matches.

### Dates and timezones

Dates describe **when the conversation happened**, separately from when the job wrote
its summary. A conversation from Tuesday still appears under Tuesday if refinement
finishes on Wednesday. `show` displays both event and recording times.
For a summary spanning several exchanges, filters use its start time: the earliest
source request. They do not match every date crossed by the event's full time range.

| Filter value | Meaning |
| --- | --- |
| `today` | Start of today |
| `week` | Monday at the start of this calendar week |
| `month` | First day of this calendar month |
| `24h`, `7d`, `4w` | The preceding duration in hours, days, or weeks |
| `2026-09-14` | Midnight on that date |
| `2026-09-14T09:00:00+01:00` | An exact timestamp with a UTC offset |

Use these values with `--since` or `--until`. The start is included and the end is
excluded. A plain date is read in the Memory timezone, while an exact timestamp must
carry its own offset. Calendar boundaries and displayed dates use the Memory timezone;
stored timestamps use UTC. The default timezone is the machine's local timezone. To
choose one explicitly:

```bash
enso config set memory.timezone Europe/London
```

## Browse in the web viewer

Open **Memory** in the [web viewer](/docs/web/), or visit `/memory` at your viewer's
address. On a phone, it is under **More**. The timeline groups memories by event date;
use search and the workspace, transport, channel, and date filters to narrow it.

Open an entry to read its full summary, event and recording times, source exchanges,
and origin details. The viewer is read-only. Continue through chat or the CLI to manage
Memory, and reload the page to see new entries.

## What gets captured

Capture starts when Memory is installed and enabled. It covers conversations run
through Enso, without scraping Slack, Telegram, or provider history files. Standalone
CLI sessions and old conversations are not imported. Job output, heartbeat output,
and Knowledge changes do not become Memory automatically.

The saved exchange excludes tool calls and results, reasoning, progress events,
injected instructions, repeated chat history, and the quoted replies and shared-message
context a chat platform adds around your words. A message you forward into a Telegram
chat arrives as your own text, so it is captured as the request. Attachment references
remain available, but Memory does not store a transcript of everything the provider saw
or did. Built-in chat commands, such as clearing a session, are not captured as
conversation exchanges, and neither is a message Enso never starts a conversation for,
such as one from an unbound chat or one whose attachment could not be prepared.

Failed, timed-out, or stopped exchanges keep their outcome and may become memories of
unfinished work; a turn interrupted by restarting Enso is recorded as stopped. An agent
saying it completed an action is a reported outcome, not independent proof; inspect the
relevant system when verification matters.

Stored requests and replies are each limited to 64 KiB, with truncation marked. To keep
refinement small, the job receives excerpts of up to 4 KiB per request or reply and at
most 40 exchanges per batch, within a 48 KiB total limit. Each summary is capped at
2,000 characters and links back to the retained sources. Missing or omitted material
cannot supply reliable context.

## Setup and controls

On an installation that includes this feature, setup installs `jobs/enso-memory/` and
`skills/enso-memory/`. Managed upgrades add new bundles and preserve local changes
according to the [bundle rules](/docs/customizing/#the-bundled-skills). An existing
home with custom instructions may need a pointer to the new skill added manually.

Memory is enabled by default. The job uses the default agent selected at setup and
runs in the default workspace; each captured exchange still carries its own origin.
Edit `jobs/enso-memory/JOB.md` to change the agent or 15-minute schedule, following
[Jobs](/docs/jobs/).

```bash
enso memory status
enso config set memory.enabled false
enso config set memory.enabled true
```

`status` reports saved memories, exchanges awaiting refinement, and the current
settings. `memory.enabled` and `memory.timezone` are the only two Memory settings; they
live in the `memory` section of [`config.json`](/docs/configuration/#memory). Disabling
Memory stops new capture and refinement while preserving existing history and read
commands. Changes apply on the next turn or job invocation without a restart. Disabling
only the job leaves capture on, so exchanges accumulate until refinement resumes.

## Corrections and forgetting

An agent can find and remove a memory when you ask it to forget something. It should
identify the relevant entry before using:

```bash
enso memory forget MEM-000001 --yes
```

This permanently deletes the selected memory, its source exchanges, and any other
memories connected through shared source exchanges. It can therefore remove more than
one summary. The CLI requires `--yes` to acknowledge that scope. It does not erase
provider logs, chat-platform history, or existing backups.

There is currently **no edit command**. A correction made in chat may become a new
memory, but does not rewrite the incorrect one. Ask Enso to inspect the sources and
forget the wrong entry when removal is appropriate.

Memory has no automatic expiry or pruning. Clearing a provider session or pruning job
runs does not erase it. Refinement retains original exchanges even when it creates no
summary for them; there is currently no command to remove one of those exchanges
individually without a saved memory reference.

Include `enso.db` in your normal database backup: saving only
Markdown files does not back up Memory. Disable capture if future conversations
should not enter Memory.
