# Context Memory

For the end-user explanation of what context memory is and how it behaves in chat, see [Context Memory in Unique AI Chat](https://docs.unique.ai/users/spaces/unique-ai-chat/context-memory-in-unique-ai-chat).

# Functionality

Context Memory (also called **User Memory** in the space configuration) gives every user a single, persistent memory profile that is shared across all of their chats and across all spaces where the feature is enabled. The profile is a compact, structured Markdown file that captures durable user context — identity, communication preferences, work context, skills, recent topics, and open follow-ups.

The feature is implemented in the Unique AI orchestrator as a combination of **context loading** at the start of each turn and a **post-processing step** after each turn:

1. **Load.** When a turn starts in a space with context memory enabled, the orchestrator resolves the user's private memory folder, downloads `memory.md` (if it exists), and enforces the configured token budget.

2. **Inject.** The loaded memory text is injected verbatim into the agent's system prompt under a section titled **“What I know about you”**. The agent is instructed to treat it as durable user context and to adapt tone, examples, and depth to it. If no memory file exists yet (first turn), the section is omitted entirely.

3. **Answer.** The agent answers normally. It can read the memory while answering but cannot edit it during the response — memory updates happen only in post-processing.

4. **Consolidate (post-processing).** After the final assistant response of the turn, the **user memory postprocessor** runs silently (in parallel with evaluation checks, alongside other postprocessors such as follow-up questions). It sends the existing memory plus the latest user/assistant exchange to a language model, which either returns `NOOP` (nothing durable to remember — the write is skipped entirely) or a complete rewritten profile.

5. **Upload.** If the profile changed, the updated `memory.md` is uploaded back to the user's private folder with ingestion skipped and the content hidden from chat. The next turn — in any chat or space with context memory enabled — loads the updated profile.

The memory postprocessor never modifies the assistant's visible answer; it only maintains the profile in the background.

# Storage Model and Access Control

Memory profiles are stored in the company Knowledge Base as Markdown:

```
user-memory/            ← company-wide root folder (auto-provisioned)
  <userId>/             ← private per-user folder (created on first use)
    memory.md           ← the user's single memory profile
```

| **Level** | **Access** |
| --- | --- |
| `user-memory` root folder | Created automatically when a space admin enables context memory for a space. The company **Root Group** is granted READ and WRITE — but deliberately **not** MANAGE — so that every user can create their own subfolder while per-user folders stay private. |
| `user-memory/<userId>` | Created on demand at turn time with **access inheritance disabled**, so the Root Group access to the parent does not leak into it. Only the owning user is granted READ and WRITE. **There is strictly no access to a user's memory for any other user.** |
| `memory.md` | Uploaded with `SKIP_INGESTION` (never indexed for search). The same logical file is upserted on every update. |

Because there is exactly **one memory file per user**, every space with context memory enabled loads the same profile — memory is a property of the user, not of the space or the chat.

# Memory Profile Format

The profile is a Markdown file with YAML frontmatter followed by six fixed sections, always in the same order. Empty sections carry the literal placeholder `_(empty)_`.

## Example `memory.md`

```markdown
---
user_id: user_123
schema_version: 1
last_updated: 2026-06-17T12:00:00+00:00
turn_count: 12
---

# User Memory

## Identity
- Works as a credit risk analyst at a Swiss private bank, based in Zurich (CET).
- Native German speaker; communicates with the assistant in English.

## Communication Preferences
- Prefers concise answers with concrete examples.
- Wants tables for numeric comparisons instead of prose.

## Work Context
- Preparing the quarterly IFRS 9 impairment report.
- Migrating team reporting from Excel to a Python-based pipeline.

## Skills & Expertise
_(empty)_

## Recent Topics
- 2026-06-17 11:40 UTC: Discussed expected-credit-loss staging rules.

## Open Questions / Follow-ups
- Wants to revisit the scenario-weighting approach next week.
```

## Frontmatter Fields

| **Field** | **Meaning** |
| --- | --- |
| `user_id` | The owning user's ID. Preserved exactly across rewrites. |
| `schema_version` | Profile schema version (currently `1`). Preserved across rewrites. |
| `last_updated` | UTC timestamp of the last consolidation that changed the profile. |
| `turn_count` | Incremented by 1 on each consolidation that rewrites the profile. |

## Sections and Their Meaning

| **Section** | **What it captures** |
| --- | --- |
| `## Identity` | Stable facts about who the user is: name, role, employer, team, timezone, language. |
| `## Communication Preferences` | Preference-shaped facts: communication style, formatting, depth, tone, language, expertise level, examples over theory. |
| `## Work Context` | Contextual but durable facts: current focus areas, active projects, multi-week goals, deadlines mentioned by the user. |
| `## Skills & Expertise` | The user's competences and technical stack (tools, languages, proficiency levels). |
| `## Recent Topics` | Recently discussed subjects, as dated bullets prefixed with `YYYY-MM-DD HH:MM UTC:`. |
| `## Open Questions / Follow-ups` | Explicit hand-offs: “let's revisit X later”, “remind me about Y”, “I'll come back to Z”. |

## Update Rules

On every turn, the consolidation model decides one operation per candidate fact from the latest exchange:

| **Operation** | **When** |
| --- | --- |
| `ADD` | The fact is new and stable enough to remember. Added as a bullet in the most appropriate section. |
| `UPDATE` | The fact refines, supersedes, or contradicts an existing bullet. The existing bullet is overwritten in place — the newest statement always wins, and two contradictory bullets never coexist. |
| `DELETE` | The new turn explicitly invalidates an existing bullet not worth keeping. |
| `NOOP` | The turn contains no durable facts about the user (small talk, factual questions, code requests, abstract discussion). The memory is kept unchanged and no write happens. |

**Size control.** The complete profile is kept within the configured token budget (default 2000 tokens). If it grows beyond the budget, a dedicated condensation step compresses it to roughly 90% of the cap by merging duplicates, deleting stale entries, and folding low-signal bullets — without inventing facts. As a last resort the file is hard-truncated with a `<!-- truncated to fit memory budget -->` marker.

# Configure Context Memory for a Space

Context memory is configured per space and applies to Unique AI spaces.

1. **Enable the feature flag.**`FEATURE_FLAG_ENABLE_CONTEXT_MEMORY_UN_22033` must be enabled for the company (see Feature Flags below). Without it, no context memory UI is shown and the setting is ignored at runtime.

2. **Open the Space configuration** and go to **Advanced Settings → General**.

3. **Toggle “Context memory”.** The setting defaults to **enabled** for new spaces (and is treated as enabled when the key is absent).

4. **Save the space.** When context memory is effectively enabled, the admin app automatically ensures the company-wide `user-memory` root folder exists in the Knowledge Base.

## Interaction with Web Search

Context memory and web search are **mutually exclusive by default**. If the Web Search tool is enabled for the space, the Context memory switch is shown disabled with the tooltip:

> Context memory is unavailable while web search is enabled, to keep user data out of external search queries.

Operators can lift the restriction per company with the `ALLOW_CONTEXT_MEMORY_WITH_WEB_SEARCH_UN_22591` flag, after which both features can be enabled together.

## User-Level Opt-Out

Independently of the space setting, each user controls context memory for their own account in **Settings → Context Memory**. If the user disables it, memory is not loaded and not updated in any space, regardless of space settings. The user-facing dialog states that disabling permanently deletes the memory.

## Effective Enablement

Context memory is active for a given turn only when **all** of the following hold:

| **Condition** | **Level** | **Default** |
| --- | --- | --- |
| `FEATURE_FLAG_ENABLE_CONTEXT_MEMORY_UN_22033` enabled for the company | Operator | Off |
| Space setting `Context Memory` not disabled | Space admin | Enabled (when flag is on) |
| Web search disabled for the space, _or_`ALLOW_CONTEXT_MEMORY_WITH_WEB_SEARCH_UN_22591` enabled | Space admin / operator | Web search blocks memory |
| User setting `User Memory` not disabled | End user | Enabled |

The resulting decision is passed to the AI backend, and the orchestrator activates memory loading and the post-turn consolidation only when it is true.

# Advanced Configuration

The consolidation behavior is configured per space under **Unique AI Services → User Memory (Experimental)** in the assistant's advanced JSON/module configuration.

| **Setting** | **Default** | **What it controls** |
| --- | --- | --- |
| Use Orchestrator Language Model | `true` | When true, post-turn memory consolidation uses the orchestrator's language model and the configured Language Model is ignored. When false, the configured Language Model is used. |
| Language Model | `AZURE_GPT_4o_2024_1120` | The language model used for post-turn memory consolidation when “Use Orchestrator Language Model” is false. |
| Max Tokens | `2000` (range 500–8000) | Maximum size of the memory profile in tokens. Profiles over the budget are condensed, then hard-truncated as a last resort. |

# Limitations

- **One memory per user, company-wide.** There is no per-space or per-chat memory. Users who want space-specific behavior should put it in the space instructions instead.

- **Not editable during a response.** The agent can read the memory while answering but updates happen only in the post-processing step after the final answer. The agent is explicitly instructed not to claim it can edit memory mid-response.

- **Web search exclusivity.** By default the feature is unavailable in spaces with web search enabled (override flag available).

- **Token budget.** The profile is capped (default 2000 tokens); older or low-signal content is compacted or dropped.
