# Memory

Keep what an agent learns beyond its context window, its turn, and its session, without leaking data about one subject into another.

An agent works within a model's context window, and the window is bounded. Over a long session its conversation fills: older messages are summarized and earlier tool results are cleared. Some of what it learns must outlast that, and some must outlast the session itself. And what an agent learns about one subject, such as one account, must not reach the sessions about another unless you mean it to.

Twisp gives agents two mechanisms for this, both recorded and both bounded by the session they belong to:

| Problem                                                                 | Mechanism                                      |
| ----------------------------------------------------------------------- | ---------------------------------------------- |
| A detail from an earlier turn of this session fell out of the context.  | [Session history](https://www.twisp.com/docs/actions/memory.md#session-history)            |
| A fact must outlive the turn, and inform this session's later turns.    | [Agent memory](https://www.twisp.com/docs/actions/memory.md#agent-memory), `SESSION` scope |
| A fact learned in one session should inform the agent's other sessions. | [Agent memory](https://www.twisp.com/docs/actions/memory.md#agent-memory), `AGENT` scope   |

> **Note:**
>
> The [Memory and History reference](https://www.twisp.com/docs/reference/actions/memory.md) lists every field and rule. Both features are configured in the agent's `config.harness`; see [Agent configuration](https://www.twisp.com/docs/reference/actions/agents.md#agent-configuration).

## What stays in context

Before turning to memory, it helps to know what the agent keeps on its own. Within a turn, a tool result larger than the offload threshold is set aside, leaving a preview and a reference the agent retrieves it with. As the conversation fills, older messages are summarized, keeping the latest few word for word. In a session, each new turn continues the conversation, and earlier turns' large tool results are replaced by a note naming the reference that returns them. The session's `state`, which every turn reports, carries forward whole. See `harness.context` in [Agent configuration](https://www.twisp.com/docs/reference/actions/agents.md#agent-configuration).

Design the state to hold what the next turn must know, such as how far the agent has reviewed and which findings are open. Use history and memory for everything else.

## Session history

A summary keeps the gist, not every amount and ID. With `harness.history`, what earlier turns of the session said stays searchable, so the agent can look up a detail instead of guessing or asking again. See [Session history](https://www.twisp.com/docs/reference/actions/memory.md#session-history).

```json
{ "harness": { "history": { "index": "messages_and_tools" } } }
```

| `index`              | What earlier turns keep searchable                                      |
| -------------------- | ----------------------------------------------------------------------- |
| `none` (default)     | Nothing.                                                                |
| `messages`           | Each turn's message, as the agent received it, and the agent's replies. |
| `messages_and_tools` | Also the results of the agent's tools, and their errors.                |

With an index, the agent has `search_history`. It ranks the kept events of the session's earlier turns by meaning, keywords, and recency, and the agent is told to search before guessing at something an earlier turn established. Only what a turn commits is kept: a failed attempt stays in its transcript but is never searchable.

History never crosses sessions: an agent searches only its own session's turns, and an agent without sessions has none. Choose `messages` when the turn messages and replies hold what later turns need. Choose `messages_and_tools` when the agent needs to find earlier tool results, such as an entry it looked up three weeks ago.

## Agent memory

With `harness.memory.enabled`, an agent keeps durable facts it learns as **memory records**. A record belongs to one agent, and an agent never sees another agent's memory. See [Agent memory](https://www.twisp.com/docs/reference/actions/memory.md#agent-memory).

```json
{
  "harness": {
    "memory": {
      "enabled": true,
      "scope": { "read": ["session"], "write": ["session"] },
      "tools": ["add_memory", "read_memory", "delete_memory"],
      "pinned": { "max_tokens": 2000 }
    }
  }
}
```

### Scopes

A record's scope decides which sessions recall it:

- **`SESSION`**: only the session that wrote it. What the agent learns about one account stays with that account's session.
- **`AGENT`**: every session of the agent that reads agent scope, so what it learns in one session informs the next.

`harness.memory.scope` sets which scopes the agent reads and writes. Both default to `["session"]`, which keeps every session's data to itself. Allow `agent` writes only when facts from one session's data may inform every other session, such as guidance an operator gave that applies to all accounts. When `write` includes both, the agent chooses the scope of each record. An agent without a session has no session scope, so it sets both to `["agent"]`.

### How memory is written

**Extraction.** When a turn ends, the agent reviews the conversation for what is worth remembering. It compares each candidate with the most similar records it already has, and adds it, replaces a record it corrects, deletes a record it shows wrong, or skips it, so restated facts do not pile up. `harness.memory.extraction.prompt` replaces the default instructions for what to keep, and `every` sets how often the review runs: every turn, or once enough messages were added. Each review is a model call with purpose `memory` that counts against the turn's limits; `harness.memory.model` can name a cheaper model for it.

**Memory tools.** With `harness.memory.tools`, the agent can also save a fact as it learns it with `add_memory`, read one record with `read_memory`, and delete one with `delete_memory`. `add_memory` can name a record it `replaces`, which becomes `SUPERSEDED`.

Memory is written in the turn's transaction, so a turn that rolls back leaves no record. Only the agent itself writes memory: a subagent helper or a program run by `programmatic_tool_caller` can search memory but never write it.

### How memory is used

**Recall.** Before each model call, the agent recalls the records that best match its current work. Recalled memory reaches the model marked as memory, and is data, never instructions.

**Search.** The agent can search its memory with `search_memory`, by query or by filters on kind, labels, or IDs. Search combines meaning, keywords, and recency. `harness.memory.search` tunes it: `mode` (`hybrid`, `lexical`, or `vector`), `max_results` per recall, and `min_score` for matches by meaning alone.

**Pins.** With `harness.memory.pinned`, the agent may pin a record, and every turn's instructions list the summary and ID of each pinned record it reads. Pins are for the few facts every turn must see, such as an operator's standing ruling. `max_tokens` is their budget: a pin that would exceed it is refused, and the agent is told to consolidate several pins into one.

Every recall and search whose records reached the model is recorded as a `RETRIEVED` [output use](https://www.twisp.com/docs/reference/actions/skills.md#output-uses), so you can see which memories informed a decision.

### Kinds and labels

Each record has a one-line `summary` the agent can act on, and optional `content` with the evidence. Its `kind` is one of the kinds the agent declares in `harness.memory.kinds`, by default `guidance`, `fact`, `event`, and `reference`. **Labels** are exact values that searches filter on, such as a customer ID. Declare each label with a fixed `number` and a description the agent reads:

```json
"labels": { "customer_id": { "number": 5, "description": "The customer the memory is about." } }
```

Once a version declares a label, later versions keep it with the same number.

### Memory in preview mode

An agent in [preview mode](https://www.twisp.com/docs/reference/actions/executions.md#preview-calls) writes memory marked `preview`. Later preview turns read it, but a live turn never does, so once the agent goes live it does not act on what it learned of effects that never happened. A preview turn never changes a record a live turn wrote: it writes a preview record that names the record it would replace or delete, so `Action.memories` shows exactly what the preview would have changed. Preview history is likewise searched only by preview turns.

### Reviewing and deleting memory

`Action.memories` lists an agent's records, newest first, and `agentMemory` reads one with its history. Each record names the execution, agent version, and session that wrote it. `deleteAgentMemory` removes a record from recall; the record and its versions stay readable. To list and read records, grant `SELECT` on `financial.AgentMemory.indexes.*` and `financial.AgentMemory.document`; to delete them, also grant `UPDATE`. The agent itself needs none of these: its memory is its own record, so neither its policies nor those of whoever starts or calls it need to grant them for it to use its memory.

## Choosing settings

| If                                                                     | Then                                                                                                                                                     |
| ---------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| The next turn needs a fact to do its work                              | Put it in the session's `state`, or compute it with [computed state](https://www.twisp.com/docs/reference/actions/agents.md#computed-state).                                          |
| A long session loses details to summaries                              | Enable `harness.history`; use `messages_and_tools` if the details are in tool results.                                                                   |
| Each session is about one subject whose data must stay with it         | Enable memory with the default scopes, `session` only.                                                                                                   |
| What one session learns should inform all of them                      | Add `agent` to `scope.read` and `scope.write`, and tell the agent in `extraction.prompt` which facts belong in agent scope.                              |
| The agent should record facts as it learns them, not only after a turn | Add `add_memory` to `harness.memory.tools`.                                                                                                              |
| A few facts must be in front of every turn                             | Set `pinned.max_tokens`, small enough to keep the list short.                                                                                            |
| Records are about identifiable things you search by                    | Declare labels for those IDs.                                                                                                                            |
| Extraction costs too much                                              | Set `extraction.every` to `{"messages": N}`, or name a cheaper `harness.memory.model`.                                                                   |
| An agent runs without a session                                        | Set both scopes to `["agent"]`. Every run then shares one memory, so declare labels for the subjects records are about, and let searches filter on them. |

## Next

- [Agent memory tutorial](https://www.twisp.com/docs/tutorials/actions/agent-memory.md): Give an agent memory, and watch what it keeps and recalls.
- [Sessions](https://www.twisp.com/docs/actions/sessions.md): The durable identity that scopes history and session memory.
- [Memory and History reference](https://www.twisp.com/docs/reference/actions/memory.md): Every field, operation, and rule.
