# client.memory

> client.memory — the memory operations.

`client.memory` — the `memory` operations.

On `AsyncKindgi` every method is the same, awaited.

## `client.memory.list_facts()`

```python signature
list_facts(
    *,
    limit: int | None = None,
    cursor: str | None = None,
    type: str | None = None,
    scope: str | None = None,
    scope_kind: Literal['tenant', 'org', 'project'] | None = None,
    scope_id: str | UUID | None = None,
    inherit: bool | None = None,
    as_of: str | None = None,
    timeout: float | None = None,
) -> FactCollectionPage
```

List facts. `GET /v1/memory/facts`

Cursor-paginated: the current revision of each fact the caller may see. That is tenant-wide facts, the projects they may read (with those projects' orgs), their own user facts, and every end user's and conversation's facts in the projects they may write; a tenant admin sees every fact. Filters: `?type=` (exact match on `Fact.type`), `?scope=` (URL-encoded JSON partial memory `Scope`), `?scopeKind + ?scopeId + ?inherit` (discriminated `PlatformScope` triplet — threaded into the binding as `platformScope`; both fields coexist), `?asOf=` (memory as it stood then). Sort order is binding-defined.

## `client.memory.write_fact()`

```python signature
write_fact(
    body: WriteFactBody | Mapping[str, Any] | None = None,
    /,
    *,
    idempotency_key: str | None = None,
    timeout: float | None = None,
    **fields: Any,
) -> Fact
```

Write a fact. `POST /v1/memory/facts`

Persists a new fact. `type` selects the retrieval policy (which indexes populate). Semantic-indexed types require an embedding provider bound on the deployment; if unavailable, the route returns `400 bad-input`. The caller needs write where the scope says: `write` on its project (an end user's or a conversation's fact included), `write` on its conversation outside a project, `admin` on its org for an org-wide fact, being that user for a user's fact, and tenant `admin` for a tenant-wide fact. The fact records who wrote it (`attributedTo`).

## `client.memory.get_fact()`

```python signature
get_fact(
    fact_id: str | UUID,
    /,
    *,
    version: int | None = None,
    as_of: str | None = None,
    timeout: float | None = None,
) -> Fact
```

Fetch a fact. `GET /v1/memory/facts/{factId}`

Its current revision; `?version=` reads one revision, `?asOf=` the revision current at that time. A fact the caller may not see is not found.

## `client.memory.delete_fact()`

```python signature
delete_fact(
    fact_id: str | UUID,
    /,
    *,
    expect_version: int | None = None,
    timeout: float | None = None,
) -> Fact
```

Delete a fact. `DELETE /v1/memory/facts/{factId}`

Closes the current revision (`invalidationReason: deleted`): the fact is no longer listed, fetched or retrieved, and its history stays readable until the retention sweep removes it.

## `client.memory.list_fact_revisions()`

```python signature
list_fact_revisions(
    fact_id: str | UUID,
    /,
    *,
    timeout: float | None = None,
) -> FactRevisionList
```

List a fact's revisions. `GET /v1/memory/facts/{factId}/revisions`

Every revision of the fact, newest first, superseded and deleted ones included: who changed it, when and why (`invalidatedBy`, `invalidatedAt`, `invalidationReason`).

## `client.memory.supersede_fact()`

```python signature
supersede_fact(
    fact_id: str | UUID,
    body: SupersedeFactBody | Mapping[str, Any] | None = None,
    /,
    *,
    idempotency_key: str | None = None,
    timeout: float | None = None,
    **fields: Any,
) -> Fact
```

Change a fact's content. `POST /v1/memory/facts/{factId}/supersede`

Writes the next revision (same fact id, `version` one more) and closes the current one; the old revision stays readable with `?version=`, `?asOf=` and in the history until the retention sweep removes it. `expectVersion` refuses if someone changed it first.

## `client.memory.verify_fact()`

```python signature
verify_fact(
    fact_id: str | UUID,
    body: VerifyFactBody | Mapping[str, Any] | None = None,
    /,
    *,
    idempotency_key: str | None = None,
    timeout: float | None = None,
    **fields: Any,
) -> Fact
```

Mark a fact verified. `POST /v1/memory/facts/{factId}/verify`

A person who may write in its scope checked it: the next revision has `trust: verified`, `verifiedBy` and `verifiedAt`, and the same content.

## `client.memory.retrieve()`

```python signature
retrieve(
    body: RetrieveMemoryBody | Mapping[str, Any] | None = None,
    /,
    *,
    idempotency_key: str | None = None,
    timeout: float | None = None,
    **fields: Any,
) -> RetrieveMemoryResult
```

Retrieve facts by intent. `POST /v1/memory/retrieve`

Retrieval over the facts the caller may see (as for listing), current revisions only. `mode`: `list` (newest first, no query), `keyword` (full-text), `semantic` (by meaning), or `both` (the two searches fused by rank: reciprocal rank fusion). Searching by meaning needs embeddings on the deployment (`KINDGI_MEMORY_EMBEDDINGS`); without them `semantic` and `both` answer `422 semantic-unavailable`.

## `client.memory.list_erasures()`

```python signature
list_erasures(
    *,
    limit: int | None = None,
    cursor: str | None = None,
    timeout: float | None = None,
) -> MemoryErasurePage
```

List erasures. `GET /v1/memory/erasures`

Cursor-paginated, newest first: each erasure, how far it got and what it cleared. A completed one shows no selector. Requires `admin` on the tenant.

## `client.memory.create_erasure()`

```python signature
create_erasure(
    body: CreateMemoryErasureBody | Mapping[str, Any] | None = None,
    /,
    *,
    idempotency_key: str | None = None,
    timeout: float | None = None,
    **fields: Any,
) -> MemoryErasureCreated
```

Erase a person's words. `POST /v1/memory/erasures`

Starts erasing, in the background, one fact (`factId`), a person (`subject`: an app's end user `participant`, or an `external` subject facts name) or one conversation (`conversationId`): their facts, conversations (messages, recall rows), the runs that served them (input, output, journal, snapshots) and the free text they left in provenance; facts written from them go to review. Answers `202` with the erasure; follow it with `GET /v1/memory/erasures/{erasureId}`. A completed erasure keeps no identifier, only a keyed hash for a replay after a backup restore; `warnings` says when this deployment can't keep one (`erasure-unmatchable`: no erasure ledger key, `KINDGI_ERASURE_LEDGER_KEY`). Requires `admin` on the tenant.

## `client.memory.export_erasures()`

```python signature
export_erasures(*, timeout: float | None = None) -> MemoryErasureLedger
```

Export the erasure ledger. `GET /v1/memory/erasures/export`

The whole ledger, oldest first, content-free: each erasure's selector kind, the keyed hash of whom it erased, who asked and when. Keep it off-box: restoring a backup rolls the ledger back too, and `POST /v1/memory/erasures/replay` with it runs the erasures again. Requires `admin` on the tenant.

## `client.memory.replay_erasures()`

```python signature
replay_erasures(
    body: ReplayMemoryErasuresBody | Mapping[str, Any] | None = None,
    /,
    *,
    idempotency_key: str | None = None,
    timeout: float | None = None,
    **fields: Any,
) -> ReplayMemoryErasuresResult
```

Replay erasures after a backup restore. `POST /v1/memory/erasures/replay`

Takes the ledger `GET /v1/memory/erasures/export` gave, puts back the rows the restore lost, and finds each erasure's person (or fact, or conversation) again by its keyed hash: those run again (`replayed`); ones nothing in the tenant matches are only restored (`restored`); ones with no keyed hash, or a key this deployment doesn't hold, are `unmatched`. Requires `admin` on the tenant.

## `client.memory.resume_erasure()`

```python signature
resume_erasure(
    erasure_id: str | UUID,
    body: ResumeMemoryErasureBody | Mapping[str, Any] | None = None,
    /,
    *,
    idempotency_key: str | None = None,
    timeout: float | None = None,
    **fields: Any,
) -> MemoryErasure
```

Resume an erasure. `POST /v1/memory/erasures/{erasureId}/resume`

Tries an unfinished erasure again now. With `force: true`, an erasure `waiting-on-run` (a turn of the person's in a flow that serves other people) stops waiting: the run is cancelled and the erasure goes on; without it, it waits until its deadline (`waitingOn.until`). A finished erasure comes back as it is. Requires `admin` on the tenant.

## `client.memory.get_erasure()`

```python signature
get_erasure(erasure_id: str | UUID, /, *, timeout: float | None = None) -> MemoryErasure
```

Get an erasure. `GET /v1/memory/erasures/{erasureId}`

One erasure: its status (`pending`, `running`, `completed`, `failed`), phase, what each store cleared (`counts`), and `lastError` (a code, or `not-yet:<reason>` while it waits for a run to finish). Requires `admin` on the tenant.
