Skip to content

client.memory

View as Markdown

client.memory — the memory operations.

On AsyncKindgi every method is the same, awaited.

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
Signature

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.

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

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).

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

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.

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

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.

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

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).

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
Signature

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.

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
Signature

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.

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

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.

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

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.

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

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.

export_erasures(*, timeout: float | None = None) -> MemoryErasureLedger
Signature

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.

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

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.

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
Signature

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.

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

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.