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

# Scope ladder

> The scope chain is a ladder of named levels, and the familiar Client, Customer, User chain is the default three rungs. This page explains what a level is, why a level's name can change and its key cannot, which direction a read travels, and exactly which parts of custom depth you can reach today.

<Note>
  Read [Identifiers & Scopes](/concepts/memory-scopes) first. This page assumes
  you know what `customer_id` and `user_id` do.
</Note>

<Tip>
  If your account uses the default `Client → Customer → User` chain, nothing here
  changes how you integrate. This page matters when that shape does not describe
  your business.
</Tip>

## What a level is

A scope is a position on a ladder. Your account is the top rung, and each rung
below it narrows who a memory belongs to. The default ladder has three:

```
client     your account
  customer   an organization you serve
    user       one person inside it
```

Every memory is filed at exactly one rung, and it carries that rung plus every
rung above it. That stored list is what a read filters on.

## Which direction a read travels

This is the rule worth reading twice, because it is easy to hold backwards.

**A request sees its own rung and every rung above it. It never sees a rung
below, and never a neighbour.**

So on the default ladder:

| A request identifying | Can read memories filed at              |
| --------------------- | --------------------------------------- |
| a user                | that user, their customer, your account |
| a customer            | that customer, your account             |
| your account only     | your account                            |

A memory filed at the user level is **not** visible to a request that identifies
only the customer. One person's private context does not surface for their
colleague, and it does not surface for a customer-wide question.

<Warning>
  A memory's stored chain is the path down **to** it. That is the list of rungs
  the memory can be read **from**, not a list of places the memory is visible.
  A fact filed at the user rung carries `client, customer, user`, and it is still
  readable only by that user.
</Warning>

## Ranking: closer material wins

Filtering decides what a request is allowed to read. Ranking decides what it sees
first. Among the memories a request may read, the ones filed closer to the person
asking rank above the ones filed further up.

A person's own preference outranks a fact that is true of their whole
organization, when both match the question equally well. This is a ranking
adjustment only: it never makes a memory readable that was not, and it never
hides one that was.

## A level's name can change, its key cannot

Every level has two parts.

* The **label** is what people read: "Customer", "Practice", "Region". Change it
  whenever you like. Nothing stored depends on it.
* The **key** is what stored memories resolve through: `customer`, `user`. It
  never changes, because every memory already filed under it would stop
  resolving.

For the same reason a level can never be deleted, only **deprecated**. A
deprecated level stops being offered for new structure, and everything already
filed under it stays readable.

## Sending a scope path

Requests normally identify a scope with `customer_id` and `user_id`, and Synap
maps those onto the default three rungs. That is what almost every integration
does, and it needs no change.

To address a level beyond those three, send an explicit `scope` map on a context
fetch, naming each rung by its key:

```json theme={null}
POST /v1/context/user/fetch
{
  "search_query": ["what did we agree on pricing"],
  "max_results": 10,
  "scope": {
    "customer": "acme",
    "team": "payments",
    "user": "d-42"
  }
}
```

Two rules apply, and both fail loudly rather than guessing:

* **Every rung must be named.** A path that skips a level is refused, and the
  error names the level you left out. Synap never infers a missing id, because a
  wrong guess at or above the organization level would cross a tenant boundary.
* **The feature must be enabled for your instance.** If it is not, sending a
  `scope` map is an error rather than being ignored. Ignoring it would widen the
  request to the whole organization when you asked to narrow it to one team.

<Warning>
  **The SDKs cannot send a `scope` map yet.** The `scope` argument on an SDK fetch
  names which method you called (`user`, `customer`, `client`), not a path. Today
  an explicit path is only reachable by calling the HTTP API directly. gRPC cannot
  carry one either.
</Warning>

## What you can reach today

Being precise about this matters more than making the feature sound finished.

|                                               | Available now                      |
| --------------------------------------------- | ---------------------------------- |
| The default three-rung ladder                 | Yes, on every account, from signup |
| Reading and ranking across those rungs        | Yes                                |
| Sending an explicit `scope` path              | Over the HTTP API only             |
| Sending one from an SDK or gRPC               | No                                 |
| Adding a level beyond the default three       | Through the API, not the dashboard |
| Renaming a level's label                      | Through the API, not the dashboard |
| Deleting a level                              | Never; deprecate instead           |
| Sharing between levels that are not ancestors | No                                 |

The honest summary: **Synap's scoping is correct and safe on the shape accounts
already use. It does not yet let you drive a different shape from an SDK.**

## Adding a level

A level can be added above, below, or between existing ones. Adding one in the
middle is a migration rather than a setting: every node beneath the insertion
point is re-parented under a new node at the new level, in one transaction, and
Synap creates one placeholder parent per existing group so nothing is left
without one. Those placeholders are yours to rename.

Reads are unaffected while this happens. Memories above the insertion point are
never touched, and no memory changes the group it belongs to.

<Warning>
  One thing lags. Existing memories do not immediately carry the new level as
  one of their ancestors, so a query asking for everything beneath the new level
  is incomplete until Synap finishes stamping them. Ordinary retrieval is not
  affected. Ask us to run the backfill after you add a level.
</Warning>
