Skip to main content

GrayMatter Agent Memory Quickstart

This is the five-minute OmegaRAG path for an authenticated application or agent. It writes one durable memory and recalls it through the same generated, receipt-backed contract. Principal, tenant, owner, ACL scope, provider credentials, and disclosure policy are resolved by the server; the client does not send them.

1. Activate and verify access (one minute)

Use the hosted login, Keychain-backed session, or approved operator flow. Never paste a bearer token into chat or commit one to a file.

scripts/gm-activate
scripts/gm-status
scripts/gm-invariant-preflight ValkyrAI GrayMatter security rbac acl thorapi testing

Stop if activation or invariant preflight fails. Local fallback notes are not shared durable memory.

2. Call the generated one-shot SDK methods (three minutes)

The generated TypeScript client exposes rememberOmegaMemory and recallOmegaMemory. In a ValkyrAI application, the shared Redux request interface supplies the authenticated session because both generated operations declare bearer auth.

import { requestAsync } from "redux-query";
import store from "./redux/store";
import {
recallOmegaMemory,
rememberOmegaMemory,
} from "@thorapi/api/OmegaRetrievalOperationsApi";
import { OmegaRememberRequestTypeEnum } from "@thorapi/model/OmegaRememberRequest";
import type { OmegaRememberResponse } from "@thorapi/model/OmegaRememberResponse";
import type { OmegaQueryResponse } from "@thorapi/model/OmegaQueryResponse";
import { OmegaRetrievalMode } from "@thorapi/model/OmegaRetrievalMode";

type Result<T> = { value?: { body?: T } };
const dispatchRequest = store.dispatch as unknown as (
action: unknown,
) => Promise<unknown>;

const rememberedResult = (await dispatchRequest(
requestAsync(
rememberOmegaMemory({
omegaRememberRequest: {
text: "Use exact embedding profiles during index migrations.",
type: OmegaRememberRequestTypeEnum.DECISION,
tags: ["omegarag", "indexing"],
sourceChannel: "sdk:quickstart",
idempotencyKey: "quickstart-remember-001",
},
}),
),
)) as Result<OmegaRememberResponse>;

const remembered = rememberedResult.value?.body;
if (
!remembered?.memoryRef ||
!remembered.receiptRef ||
!remembered.scopeHash ||
!remembered.classification?.revisionRef
) {
throw new Error("Remember did not return durable scope and receipt lineage");
}

const recalledResult = (await dispatchRequest(
requestAsync(
recallOmegaMemory({
omegaQueryRequest: {
query: "What embedding migration rule did we decide?",
mode: OmegaRetrievalMode.Balanced,
includeEvaluator: true,
allowRemoteExpansion: false,
idempotencyKey: "quickstart-recall-001",
},
}),
),
)) as Result<OmegaQueryResponse>;

const recalled = recalledResult.value?.body;
if (
!recalled?.retrievalReceiptRef ||
!recalled.receipt?.tenantId ||
!recalled.receipt.authContextHash
) {
throw new Error("Recall did not return authorized receipt scope");
}

console.log({
memoryRef: remembered.memoryRef,
rememberReceipt: remembered.receiptRef,
scopeHash: remembered.scopeHash,
classification: remembered.classification,
recallReceipt: recalled.retrievalReceiptRef,
contextPageRef: recalled.contextPageRef,
answerPolicy: recalled.answerPolicy,
});

Use a new idempotency key for a new logical operation. Reuse the same key only to retry that exact operation; the server scopes and fingerprints it before replay.

Automatic type formation and correction

Omit type when the server should classify the memory as working, episodic, semantic, procedural, preference, decision, todo, artifact, business fact, configuration, or context. The response then includes classification.revisionRef, type, confidence, classifierVersion, evidenceHash, and receiptRef. Low-confidence deterministic classifications carry a review-recommended policy flag.

If the selected type is wrong, correct the same authorized memory through the generated client:

import { correctOmegaMemoryClassification } from "@thorapi/api/OmegaRetrievalOperationsApi";
import { OmegaMemoryClassificationCorrectionRequestTypeEnum } from "@thorapi/model/OmegaMemoryClassificationCorrectionRequest";

const correctionResult = (await dispatchRequest(
requestAsync(
correctOmegaMemoryClassification({
memoryId: remembered.memoryRef,
omegaMemoryClassificationCorrectionRequest: {
type: OmegaMemoryClassificationCorrectionRequestTypeEnum.DECISION,
reasonCode: "classifier_wrong",
idempotencyKey: "quickstart-classification-001",
},
}),
),
)) as Result<
import("@thorapi/model/OmegaMemoryClassification").OmegaMemoryClassification
>;

const corrected = correctionResult.value?.body;
if (!corrected?.revisionRef || !corrected.receiptRef) {
throw new Error(
"Classification correction lacks revision and receipt lineage",
);
}

The correction endpoint derives tenant, owner, reviewer, previous type, and scope from the authenticated memory. It reindexes through the canonical MemoryEntry patch path and appends a content-free revision; it never accepts replacement memory text or identity fields.

Govern duplicate, merge, supersession, and conflict findings

formationCandidates are signals for an authorized steward, never automatic mutations. List the review queue, inspect the two ACL-visible memories, then use decideOmegaFormationReview with an explicit lifecycle action only when the finding is verified:

import { decideOmegaFormationReview } from "@thorapi/api/OmegaRetrievalOperationsApi";
import { OmegaFormationReviewDecisionRequestDecisionEnum } from "@thorapi/model/OmegaFormationReviewDecisionRequest";
import { OmegaMemoryLifecycleAction } from "@thorapi/model/OmegaMemoryLifecycleAction";

const candidateReviewRef = remembered.formationCandidates[0]?.reviewRef;
if (!candidateReviewRef) {
throw new Error("Remember did not produce a formation candidate to review");
}

const decisionResult = (await dispatchRequest(
requestAsync(
decideOmegaFormationReview({
reviewId: candidateReviewRef,
omegaFormationReviewDecisionRequest: {
decision: OmegaFormationReviewDecisionRequestDecisionEnum.ACCEPT,
lifecycleAction: OmegaMemoryLifecycleAction.MergeSourceIntoCandidate,
reasonCode: "steward_verified_overlap",
idempotencyKey: "formation-review-merge-001",
},
}),
),
)) as Result<
import("@thorapi/model/OmegaFormationReviewItem").OmegaFormationReviewItem
>;

const lifecycle = decisionResult.value?.body?.lifecycle;
if (
!lifecycle?.relationRef ||
!lifecycle.provenanceRelationRef ||
!lifecycle.canonicalMemoryRef ||
!lifecycle.supersededMemoryRef
) {
throw new Error("Logical merge lacks complete immutable lineage");
}

Directional deduplicate, merge, and supersede actions identify which review endpoint becomes non-canonical. corroborate and contradict retain both as peer evidence. A logical merge never rewrites or deletes either MemoryEntry: it appends DERIVED_FROM followed by SUPERSEDES, with server-derived timestamps, graph/schema/policy versions, confidence, authority, and provenance. Reject or dismiss a bad finding without lifecycleAction; accepting without one records a review-only decision. Retry only with the same decision, lifecycle action, and idempotency key.

An objectLinks hint is an assertion, not a relationship write. After the target type appears in the caller's RBAC-visible ThorAPI schema, the server re-reads the target through its generated service and scores only schema-admitted searchableFields. The optional hint confidence is a ceiling: it can lower a server score but can never promote an unsupported link.

linkedObjects crossed the versioned server threshold and were attached to the new MemoryEntry. candidateLinks remain content-free, unattached suggestions on that scoped memory. A denied, missing, or schema-invisible target appears in neither list, so the endpoint does not become an object-existence oracle. Inspect confidenceSource, confidenceVersion, evidenceHash, assertionCeilingApplied, schemaVersion, and policyVersion before explaining why a link was accepted.

3. Check the receipt before using the memory (one minute)

Treat these response fields as the confidence gate:

  • Remember: memoryRef, receiptRef, scopeHash, formationStatus, classification, policyFlags, and replayed.
  • Recall: retrievalReceiptRef, contextPageRef, status, answerPolicy, warnings, and receipt.authContextHash.
  • Typed links: linkedObjects are server-verified; candidateLinks and formationCandidates remain review-only and do not silently mutate business objects.

If recall is partial, stale, conflicting, policy-blocked, or recommends clarification, narrow the query or disclose the limitation. Never present the remembered text alone as proof that it is current business truth.

Optional CLI operator path

The plugin scripts remain the fastest route for an interactive Codex/OpenClaw operator:

scripts/gm-write decision \
"Use exact embedding profiles during index migrations." \
codex:workspace:ValkyrAI \
"graymatter,omegarag,indexing"

scripts/gm-query "embedding migration rule" --show-receipt

The CLI and generated SDK converge on the same server-owned tenant/RBAC boundary. Do not supply owner IDs, tenant IDs, ACL grants, provider credentials, or raw secrets in memory text.

Safety and next steps

  • Store durable decisions, preferences, procedures, tasks, artifacts, and approved business facts—not every chat turn.
  • Use typed object-link hints only when you know the target type and ID; the server re-reads every target through generated authorization and derives attachment confidence from RBAC-visible safe fields.
  • Use /v1/api-docs or the GrayMatter schema tools before assuming a business object exists.
  • Use explicit forget/retention workflows for deletion; editing a local note does not delete shared durable memory or its indexes.
  • Preserve receipt references in agent handoffs and workflow traces.

For advanced schema inspection, run scripts/gm-openapi-sync and scripts/gm-openapi-summary. For connector, graph, evaluation, or distributed retrieval work, start from the effective MemoryProfile and the receipt-bound OmegaRAG APIs rather than widening scope client-side.