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

# How it works

> Memory model, processing pipeline, scoping, and search ranking.

## The memory model

A memory is a text fact associated with an **agent** and a **user**. You write it by sending a `content` string along with `agent_id` and `user_id` identifiers. Everything else is optional.

```json theme={null}
{
  "content": "User is in the Europe/Berlin timezone.",
  "agent_id": "support-agent",
  "user_id": "user-42"
}
```

Write short, factual sentences. One clear idea per memory is significantly more effective for retrieval than long paragraphs.

```
✓  User prefers weekly email digests.
✓  User's primary language is German.
✗  User said they prefer emails and they live in Berlin and their name is Max and they use dark mode.
```

***

## Scoping

Every memory belongs to three nested scopes. This hierarchy is enforced by the API and cannot be overridden by the caller.

| Scope            | Source            | Notes                                                                            |
| ---------------- | ----------------- | -------------------------------------------------------------------------------- |
| **Organization** | From your API key | Automatically applied — never sent in the request body                           |
| **`agent_id`**   | Your request      | Identifies which agent owns the memory. Max 256 chars, charset `[A-Za-z0-9._:-]` |
| **`user_id`**    | Your request      | Your application's user identifier. Same constraints as `agent_id`               |

A search for `agent_id=support-agent` and `user_id=user-42` will only return memories written with that exact combination. Memories from other agents or users are never returned.

An API key can never read another organization's data. Isolation is enforced at the database level, not the application layer.

***

## The write pipeline

When you call `POST /v1/memories`, the API responds with `202 Accepted` immediately — the memory is persisted to a queue and the response includes the assigned UUID.

```
POST /v1/memories
         │
         ▼
   202 Accepted  ←─── You get this immediately
   {"id": "...", "status": "queued"}
         │
         ▼ (background, ~1–5 seconds)

   ┌─────────────────────────────────────────┐
   │  Cognition Worker                        │
   │                                          │
   │  1. LLM fact extraction (if extract=true)│
   │     Transforms raw text into clean,      │
   │     discrete, retrievable facts.         │
   │                                          │
   │  2. Deduplication                        │
   │     Merges or supersedes memories that   │
   │     conflict with existing ones.         │
   │                                          │
   │  3. Importance scoring                   │
   │     Assigns a 0–1 score used in ranking. │
   │                                          │
   │  4. Compression (Level 1)                │
   │     Derives higher-level summaries from  │
   │     related raw memories when warranted. │
   │                                          │
   │  5. Store                                │
   │     Writes to vector DB + relational DB. │
   │     Warms the search cache.              │
   └─────────────────────────────────────────┘
```

### The `extract` flag

The `extract` field (default `true`) controls whether the cognition worker runs LLM fact extraction before storing the content.

| `extract`        | Behaviour                                                    | Best for                                                                            |
| ---------------- | ------------------------------------------------------------ | ----------------------------------------------------------------------------------- |
| `true` (default) | LLM extracts discrete facts from the raw text before storage | Conversation turns, unstructured observations, anything written by users or models  |
| `false`          | Content is stored verbatim — no LLM call is made             | Pre-formatted, clean facts you already control; lower latency, zero extraction cost |

***

## Memory levels

The cognition worker assigns a `level` to each memory based on its abstraction:

| Level | Name        | Description                                                                   |
| ----- | ----------- | ----------------------------------------------------------------------------- |
| `0`   | Raw         | An individual fact or observation as submitted (possibly after extraction)    |
| `1`   | Abstraction | A concise summary derived from the raw content, stored alongside the original |

Level-1 memories are more compact and rank well for broad queries. Level 0 is the most granular and preserves the original phrasing.

You can filter search results to a specific level using the `level` parameter.

***

## Memory fields

Every memory record has the following fields:

| Field        | Type              | Description                                                                |
| ------------ | ----------------- | -------------------------------------------------------------------------- |
| `id`         | string (UUID)     | Unique identifier assigned on creation                                     |
| `org_id`     | string            | Your organization identifier                                               |
| `agent_id`   | string            | The agent that owns this memory                                            |
| `user_id`    | string            | The user this memory belongs to                                            |
| `content`    | string            | The memory text (only in `GET /v1/memories/{id}` and search results)       |
| `level`      | integer           | `0` = raw, `1` = abstraction                                               |
| `status`     | string            | `active` (searchable) or `deprecated` (soft-deleted, excluded from search) |
| `importance` | float (0–1)       | Importance score assigned by the cognition worker                          |
| `confidence` | float (0–1)       | Confidence in the memory's accuracy. Defaults to `1.0` if not provided     |
| `source`     | string            | Where the memory came from (e.g. `"agent"`)                                |
| `created_at` | ISO 8601 datetime | When the memory was created                                                |
| `updated_at` | ISO 8601 datetime | When the memory was last updated                                           |

<Note>
  `content` is intentionally excluded from `GET /v1/memories` (list) responses to keep paginated payloads small. Use `GET /v1/memories/{id}` to retrieve the full record including content.
</Note>

***

## The search pipeline

`POST /v1/memories/search` is synchronous — it returns ranked results in a single request.

```
POST /v1/memories/search
         │
         ▼
   ┌─────────────────────────────────────────┐
   │  1. Hot cache check                     │
   │     Identical queries for the same      │
   │     org/agent/user return a cached      │
   │     result instantly (cache_hit: true). │
   │                                         │
   │  2. Embed the query                     │
   │     The query string is converted to a  │
   │     vector embedding.                   │
   │                                         │
   │  3. Vector search                       │
   │     Retrieves semantically similar      │
   │     memories for the org/agent/user.    │
   │                                         │
   │  4. Multi-signal fusion ranking         │
   │     Re-ranks candidates by combining:   │
   │      • Semantic similarity score        │
   │      • Memory importance (0–1)          │
   │      • Recency                          │
   │      • task_context match (if provided) │
   │                                         │
   │  5. Return top-k results                │
   └─────────────────────────────────────────┘
         │
         ▼
   200 OK {"results": [...], "latency_ms": 42, "cache_hit": false}
```

The `score` field in each result is the final fusion score, not raw cosine similarity. Use it to compare results within a single response.

### Using `task_context`

`task_context` is an optional string that provides the ranker with a hint about what the agent is currently trying to do. It improves relevance when the user's query alone does not convey enough intent.

```python theme={null}
results = client.search(
    query="what does the user prefer",
    agent_id="support-agent",
    user_id="user-42",
    task_context="composing a notification preferences summary email",
)
```

***

## Deleting memories

**Soft delete** (default) marks a memory as `deprecated`. It is immediately excluded from all search results but remains in the database. This is the standard delete operation.

**Hard delete** (`?hard=true`) permanently removes the memory from all stores — the relational database, the vector database, and the search cache. This is irreversible and intended for GDPR erasure requests.

See [`DELETE /v1/memories/{id}`](/api-reference/memories/delete) for the full reference.
