Skip to main content

GrayMatter Architecture & Design

GrayMatter is a durable, relational memory substrate designed to give AI agents persistent, queryable context that survives sessions, models, and infrastructure restarts.

The Problem We Solve

Traditional AI systems suffer three critical limitations:

  1. Transient context: Information lives in prompt windows and evaporates between sessions.
  2. Opacity: Memory decisions are invisible to the agent; retrieval quality cannot be measured or improved.
  3. Waste: Agents repeat contextual work, hallucinate over forgotten preferences, and accumulate low-signal data.

GrayMatter inverts this model: memory structures are durable, inspectable, and operationally managed.

4D Memory Matrix

At its heart, GrayMatter organizes memory along four orthogonal dimensions:

1. Objects (Entity Layer)

Each memory item is a typed, durable object persisted in a relational database.

  • MemoryEntry: base memory atom
    • id: unique identifier
    • type: context | decision | artifact | configuration | preference | todo
    • title: human-readable label
    • text: raw content
    • tags: semantic indexing
    • metadata: operational signals (confidence, source, lineage)
    • createdAt, updatedAt: temporal anchors

Why not embeddings-only?

  • Embeddings are stateless and lossy.
  • Objects enable governance, encryption, auditing, and precise updates.
  • Queries return structured data, not just soft matches.

2. Properties (Structured Data Lattice)

Each memory object has layered properties where data and inference outputs co-exist:

  • rawContent: the original memo
  • derivedSummary: LLM-computed synopsis
  • embeddings: semantic vector (cached)
  • computedProperties: derived values produced by deterministic services or generated object logic
  • inferredTags: generated semantic categories
  • computedRelevance: time-based relevance decay function

Why: Separates concerns into observable, auditable properties. Gridheim Rune formulas live as OpenAPI extensions on ThorAPI-generated model properties; GrayMatter can observe RBAC-visible calculated objects, but it should not treat Rune definitions as memory prompts.

3. Relationships (Graph Connectivity)

Objects link and contextualize each other through the RBAC-visible api-0 schema:

  • references: "this instruction depends on that preference"
  • contradicts: "this newer fact supersedes that older one"
  • suggests: "this artifact is relevant when this other object is active"
  • causality: "this preference was set because of that experience"

Why: Graph queries enable contextual retrieval, not just vector similarity. Agents obey superseding updates and understand implicit constraints. Current production code treats the live OpenAPI document as the object-graph source of truth and resolves business objects through normal ThorAPI/RBAC paths.

4. Time (Temporal Axis)

The first three dimensions fold into a timeline:

  • Snapshots capture full memory state at each decision epoch.
  • Diffs track what changed between snapshots.
  • Replay enables root-cause analysis: "why did the agent forget this?"

Why: Temporal queries answer "what was true when?" and "what changed while I was offline?" Essential for mulitple-session continuity and forensic debugging.

Runtime Lifecycle: Capture → Port

[1] Capture    → Raw input becomes MemoryEntry
[2] Structure → Object + properties defined, relationships inferred
[3] Secure → Encrypted at rest, ACLs applied, audit trail started
[4] Compute → Derived properties refreshed and object graph context resolved
[5] Adapt → Temporal snapshots, relevance decay, suggestions generated
[6] Port → Export for migration, cold-start, or external analysis

RDBMS-Backed Durability

GrayMatter data lives in PostgreSQL via JPA/Hibernate:

  • Durability: Survives restarts, crashes, and infrastructure changes.
  • Queryability: SQL enables complex filters, aggregations, and analytics.
  • Scalability: Indexes on tags, timestamps, and full-text search.
  • Governability: ACLs, encryption, and audit tables are native.

Not in-memory, not append-only logs: Those are caches; memory is structured state.

Generated APIs & Surfaces

Each memory operation is exposed through three layers:

1. REST API (ThorAPI-generated)

  • GET /v1/memory/entries — Query memory with filters
  • POST /v1/memory/entries — Create new memory
  • PATCH /v1/memory/entries/{id} — Update memory
  • DELETE /v1/memory/entries/{id} — Retire memory
  • GET /v1/memory/stats — Observe quality metrics
  • POST /v1/memory/compact — Optimize storage and retrieval

2. Generated Clients (TypeScript, Python, etc.)

Auto-generated SDK methods mirror REST endpoints:

const entries = await memoryService.queryEntries({
tags: ["project-planning"],
type: "decision",
});

3. Operational Dashboards (React/TypeScript)

React components use RTK Query hooks to fetch, cache, and subscribe to memory state:

const { data: stats } = useGetMemoryStatsQuery();
const [compact] = usePostMemoryCompactMutation();

Security: Encryption + ACLs + Audit

GrayMatter inherits Valhalla's security model:

Encryption

  • SecureField aspect: Sensitive memory properties (e.g., API keys embedded in instructions) are encrypted at-rest with AES-256.
  • Transparent decryption: Objects are decrypted in-memory on load; encryption is transparent to business logic.

Access Control (ACL)

  • Granular permissions: READ, WRITE, DELETE on individual memory entries.
  • Role-based grouping: GRAYMATTER_USER, GRAYMATTER_ADMIN, GRAYMATTER_AUDITOR.
  • Principal isolation: Each user sees only their own memory objects unless explicitly shared.

Audit Trail

  • EventLog: Every create/update/delete writes an immutable record.
  • Temporal provenance: Who changed what, when, and from which principal.
  • Forensic queries: "Show me all memory updates in the last hour" or "Who deleted that preference?"

Cost Model & Credits

Memory is not free. GrayMatter operations incur measurable, runtime-configured costs. Current rates live on the main site Pricing page, where the active credit pricing matrix is presented.

OperationPricing BasisUnit
Read entryRuntime configuredper entry retrieved
Write entryRuntime configuredper entry created/updated
CompactRuntime configuredper run (pays dividend in retrieval savings)
ReindexRuntime configuredper run (improves quality)
PruneRuntime configuredper run (removes stale data)
ExpandRuntime configuredper capacity increment

Ledger-based economics: Balance = Sum(Payments) - Sum(Usage). No negative balances. Idempotency keys prevent duplicate charges.

Retrieval Quality Metrics

GrayMatter tracks four core signals:

  1. Hit Rate (hitRate): Fraction of queries that return relevant results.

    • Target: >90%
    • If <70%, trigger reindex or expand.
  2. Context Utilization (usedPct): Percentage of stored memory actively used.

    • Target: 60-80%
    • If >85%, trigger compact or prune.
  3. Waste (wastePct): Fraction of memory matching queries but not used.

    • Target: <20%
    • High waste → run compact.
  4. Burn Rate (burnRate): Credits spent per session hour.

    • Monitor for unexpected spikes.
    • Adjust read/write volume as needed.

Integration Points

With ValkyrAI Workflows

Workflows can read/write memory at task boundaries:

workflow:
- task: "Plan project"
module: "memory_read"
config:
query: "project:acme"
- task: "Execute plan"
module: "your_logic"
- task: "Store learnings"
module: "memory_write"
config:
type: "decision"
text: "{{output.learnings}}"

With ValorIDE Agents

Agents store/retrieve preferences, task histories, and domain knowledge:

// Inside agent execute() method
const prefs = await memory.query({
tags: ["agent-preference"],
type: "PREFERENCE",
});
// Use prefs to customize behavior

With External Systems

OpenClaw compatibility aliases make memory accessible via standard HTTP:

curl -X POST /v1/memory/entries/read \
-H "Authorization: Bearer $TOKEN" \
-d '{"query": "billing:stripe", "limit": 10}'

Data Model Diagram

┌─────────────────────────────────────────┐
│ MemoryEntry (Core) │
├─────────────────────────────────────────┤
│ id: UUID │
│ type: context|decision|artifact|... │
│ title: String │
│ text: String (SecureField optional) │
│ tags: List<String> │
│ metadata: JSON │
│ createdAt, updatedAt, retiredAt │
│ principalId: UUID (owner) │
│ encryptionKeyId: UUID │
└─────────────────────────────────────────┘
↓ (resolved through RBAC-visible api-0 schema)
┌─────────────────────────────────────────┐
│ api-0 Object Graph │
├─────────────────────────────────────────┤
│ Agent, Workflow, Task, Application, ... │
│ Customer, Opportunity, Product, ... │
│ Workbook, Gridheim Runes, Sheetster Grid │
│ SwarmOps coordination state │
└─────────────────────────────────────────┘
↓ (snapshotted in)
┌─────────────────────────────────────────┐
│ MemorySnapshot (Temporal Axis) │
├─────────────────────────────────────────┤
│ id: UUID │
│ snapshotTime: Timestamp │
│ entries: List<UUID> (included entries) │
│ stats: MemoryStats (at that moment) │
│ diff: JSON (what changed since last) │
└─────────────────────────────────────────┘

Summary: Why This Architecture Wins

PropertyTraditional LLMGrayMatter
DurabilityPrompt window (ephemeral)RDBMS (persistent)
QueryabilityVector search onlySQL + semantic search
ObservabilityBlack boxDashboards, metrics, logs
GovernanceNoneACLs, encryption, audit
Cost controlPer tokenPer operation + ledger
AdaptabilityStatic contextTemporal snapshots + replay

GrayMatter flips the script: Memory is not a side effect of prompts; it's a first-class system.