Why Immutable Typed Facts
What this page is
Why Stigmem stores knowledge as immutable, typed atomic facts —
(entity, relation, value, source, timestamp, hlc, confidence, scope)
— and why mutable key-value stores fail at federation.
The problem
An AI agent needs to remember things — a user's role, a project's
status, a preference. The simplest model is a key-value store:
set("alice.role", "CEO"). But the moment a second agent, a second
node, or a second point in time enters the picture, key-value breaks
down.
Which write wins? Who wrote it? When? Can you prove the value wasn't tampered with?
Key-value stores answer none of these questions without bolting on layers of metadata — at which point you've reinvented a fact model, just poorly.
Naive approaches and why they fail
Our model
Stigmem stores knowledge as atomic facts. Each fact is a single assertion:
(entity, relation, value, source, timestamp, hlc, confidence, scope)
A fact is immutable once written. Updates are new facts. Retractions
are facts with confidence = 0.0. This gives you:
string, text, number, boolean, datetime, ref, null (Spec-01-Fact-Model typed values).source + timestamp1.0 = certain, 0.5 = uncertain, 0.0 = retracted.local, team, company, or public — governs visibility and federation.Worked example · asserting and retracting a fact
# Assert: Alice is CEO
curl -X POST $STIGMEM_URL/v1/facts \
-H "Authorization: Bearer $STIGMEM_API_KEY" \
-d '{
"entity": "stigmem://company.example/user/alice",
"relation": "memory:role",
"value": {"type": "string", "v": "CEO"},
"source": "stigmem://company.example/agent/assistant",
"confidence": 1.0,
"scope": "company"
}'
# → 201 { "id": "fact_01J...", "hlc": "1746230400000.001", ... }
# Retract: Alice is no longer CEO
curl -X POST $STIGMEM_URL/v1/facts \
-d '{
"entity": "stigmem://company.example/user/alice",
"relation": "memory:role",
"value": {"type": "string", "v": "CEO"},
"source": "stigmem://company.example/agent/assistant",
"confidence": 0.0,
"scope": "company"
}'
# → 201 { "id": "fact_02J...", "confidence": 0.0, ... }
Both facts exist in the store. The original assertion is never
deleted. Querying memory:role for Alice now returns the retraction
(confidence 0.0), and any query with min_confidence > 0 filters it
out naturally.
Entity URI structure
Entities use a formal URI scheme that binds identity to the owning node:
stigmem://{authority}/{type}/{id}
For example: stigmem://company.example/user/alice,
stigmem://company.example/agent/cto. This prevents identity
collisions across federated nodes — two peers can each have a
user/alice without ambiguity. Entity URIs are normalized to
lowercase on ingest (Spec-01-Fact-Model entity normalization) to
prevent silent fragmentation.
Why this is non-obvious
Immutability seems wasteful
Storing every version sounds expensive. But mutable state with conflict resolution or distributed locking is more expensive in a federated system. Immutability eliminates an entire class of distributed systems problems: you never need distributed locks, two-phase commits, or merge algorithms. Contradiction detection becomes a simple comparison.
Retracting via confidence = 0.0 seems indirect
But it preserves the retraction as a first-class event with its own provenance. You can answer "who retracted this, and when?" — which matters for compliance (GDPR Art. 17) and debugging. A DELETE operation would destroy that information.
Seven value types seem arbitrary
They're the minimum set that covers practical agent-memory needs without requiring schema registration. string for labels, text for narrative, number/boolean/datetime for structured data, ref for entity-to-entity links (powers the graph index), null for explicit "unknown."
What it costs
Storage
Every update creates a new row. For high-churn relations, the facts table grows proportionally. The decay sweeper (Spec-X9) mitigates this by automatically retracting stale facts based on configurable TTL and half-life policies.
Query complexity
Finding the "current" value for an entity-relation pair requires ordering by HLC and filtering by confidence — not a simple key lookup. The node handles this internally, but implementers should index on (entity, relation, scope).
No partial updates
You can't change one field of a fact. You assert a complete new fact. For the atomic assertions Stigmem models, this is acceptable; for document-shaped data, use ref-type values to point to external storage.