# memory — Manual

## What it does
Stores facts about the user that outlive the session: who they are, what they prefer, which hosts and tools they run, what they are working on. Anything true tomorrow but not worth rediscovering belongs here; anything true only for this turn belongs in `scratchpad`.

Facts are scoped to the user. A save is an **upsert** on `(category, key)` — writing the same key again overwrites it rather than adding a second fact, so correct a wrong fact by saving over it.

## Parameters

| Parameter | Used by | Description |
|-----------|---------|-------------|
| `action` | required | `save` \| `search` \| `forget` \| `list`. |
| `query` | `search` | Keywords describing what to look for. |
| `category` | `save`, `forget` | `profile` \| `preferences` \| `technical` \| `projects` \| `other`. |
| `key` | `save`, `forget` | `snake_case` identifier, unique within the category. |
| `value` | `save` | The fact, one concise plain-text statement. |
| `source` | `save` | `conversation` (default) \| `tool_call` \| `auto_discovery` \| `user_explicit`. |
| `confidence` | `save` | 0–100, default 70. |
| `expires_days` | `save` | Days until the fact expires. Omit for "never". |
| `source_context` | `save` | Provenance, e.g. `found via ip addr on localhost`. |

Categories: `profile` = who they are, `preferences` = likes/dislikes, `technical` = OS/tools/servers, `projects` = ongoing work, `other` = everything else.

## Actions

### `save`
Requires `category`, `key` and `value`; omitting any of the three fails the call with a specific message. An invalid `category` is rejected; an invalid `source` is silently coerced to `conversation`, and `confidence` is clamped to 0–100.

```json
{"action": "save", "category": "preferences", "key": "response_language",
 "value": "Prefers all answers in Russian", "source": "user_explicit",
 "confidence": 95, "source_context": "user asked directly in session"}

{"action": "save", "category": "technical", "key": "prod_server_ip",
 "value": "Production runs on 192.168.1.168 (branch master, docker postgres)",
 "source": "tool_call", "confidence": 95, "expires_days": 7,
 "source_context": "found via ssh_exec hostname/ip addr"}
```

Calibrate the two numbers honestly — they are what makes a fact worth trusting later:

| How you learned it | `source` | `confidence` |
|---|---|---|
| Ran a tool and read the output | `tool_call` | 95 |
| The user told you | `user_explicit` | 80–95 |
| Extracted from the conversation | `conversation` | 70 |
| Read it on the web | `auto_discovery` | 50 |
| Inferred / guessed | `conversation` | 30 |

**System facts expire.** An IP, a running service, a host's disk layout — set `expires_days: 7`. A stale host address is worse than no address, because it is trusted. Durable preferences and identity never expire.

### `search`
Requires `query`. Returns up to 15 matching facts, each with its category, key, value and provenance (`src`, `conf`, `ctx`). This is the read path — search before saving, so you update an existing key instead of inventing a near-duplicate.

```json
{"action": "search", "query": "server ip"}
{"action": "search", "query": "language preference"}
```

### `forget`
Requires `key`; `category` optionally narrows it. Returns how many facts were deleted; deleting nothing is an error (`not found`), not a silent success.

```json
{"action": "forget", "key": "prod_server_ip", "category": "technical"}
```

### `list`
Returns the **categories** that hold facts, not the facts themselves:

```json
{"action": "list"}
```

Use it to see the shape of what is stored; use `search` to read the content.

## Rules

- Do not store what the code or the session already says — no facts about the current conversation's files, and nothing recoverable from one tool call.
- One fact per key. `home_server_ip` and `prod_server_ip` are different facts; `server` holding three sentences is one unusable blob.
- `value` is a statement, not a field name: "Home server is 192.168.1.168", not "192.168.1.168".
- Search before saving. The upsert only overwrites when the key matches exactly.
- Never save secrets — passwords, tokens, keys. Record where they live, not what they are.
