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:
- Transient context: Information lives in prompt windows and evaporates between sessions.
- Opacity: Memory decisions are invisible to the agent; retrieval quality cannot be measured or improved.
- 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 atomid: unique identifiertype: context | decision | artifact | configuration | preference | todotitle: human-readable labeltext: raw contenttags: semantic indexingmetadata: 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 memoderivedSummary: LLM-computed synopsisembeddings: semantic vector (cached)computedProperties: derived values produced by deterministic services or generated object logicinferredTags: generated semantic categoriescomputedRelevance: 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 filtersPOST /v1/memory/entries— Create new memoryPATCH /v1/memory/entries/{id}— Update memoryDELETE /v1/memory/entries/{id}— Retire memoryGET /v1/memory/stats— Observe quality metricsPOST /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.
| Operation | Pricing Basis | Unit |
|---|---|---|
| Read entry | Runtime configured | per entry retrieved |
| Write entry | Runtime configured | per entry created/updated |
| Compact | Runtime configured | per run (pays dividend in retrieval savings) |
| Reindex | Runtime configured | per run (improves quality) |
| Prune | Runtime configured | per run (removes stale data) |
| Expand | Runtime configured | per 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:
-
Hit Rate (
hitRate): Fraction of queries that return relevant results.- Target: >90%
- If <70%, trigger reindex or expand.
-
Context Utilization (
usedPct): Percentage of stored memory actively used.- Target: 60-80%
- If >85%, trigger compact or prune.
-
Waste (
wastePct): Fraction of memory matching queries but not used.- Target: <20%
- High waste → run compact.
-
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
| Property | Traditional LLM | GrayMatter |
|---|---|---|
| Durability | Prompt window (ephemeral) | RDBMS (persistent) |
| Queryability | Vector search only | SQL + semantic search |
| Observability | Black box | Dashboards, metrics, logs |
| Governance | None | ACLs, encryption, audit |
| Cost control | Per token | Per operation + ledger |
| Adaptability | Static context | Temporal snapshots + replay |
GrayMatter flips the script: Memory is not a side effect of prompts; it's a first-class system.