Memory Model
Record Structure
This page walks through every column on the memories table — what it holds, who can write it, what it defaults to, and which other systems read it. Field names match the model definition exactly.
Identity and ownership
| Field | Type | Notes |
|---|---|---|
id | Integer (PK) | The only stable handle. Stable across all caches and indexes. |
user_id | Integer (FK, indexed) | Hard owner. Cascade-deletes when the user is removed. |
project_id | Integer (FK, indexed, nullable) | Soft scope. SET NULL on cascade so memory survives a project rename. |
environment | String(20), default "production" | Check constraint: must be one of development | staging | production. |
Content fields (encrypted at rest)
| Field | Type | Notes |
|---|---|---|
text | LargeBinary (column name text_ciphertext) | Required. Stored encrypted; decrypted only on the read path with the tenant key. |
summary | LargeBinary (column name summary_ciphertext), nullable | Populated by the summarizer for memories that belong to a cluster of three or more. |
Vector fields
| Field | Type | Notes |
|---|---|---|
vector | Array of Float, nullable | Persisted in the durable store as a backup of what is in the index. Null until embedding succeeds. |
vector_id | String(64), unique, nullable | Stable handle for the vector inside the index. Rewritten on every content update. |
embedding_version | String(32), nullable | Lets the platform tell which generation of embedding model produced this vector and re-embed selectively when models advance. |
User-supplied metadata
| Field | Type | Notes |
|---|---|---|
metadata_json | JSON, nullable | Free-form key/value blob. Not validated against a schema, but bounded in size — oversized payloads are rejected with HTTP 413. |
tags | Array of String, nullable | Caller-chosen labels. Used as an OR filter at recall time. |
source | String(64), indexed, nullable | Origin label, e.g. email, slack, web, api, upload. |
event_type | String(64), indexed, nullable | Trigger label, e.g. meeting, decision, status_update. |
importance | Float, default 0.5 | Range [0, 1]. Caller hint; ranking weights it at 15% by default. |
content_type | String(32), indexed, nullable | Optional category — drives content-aware freshness decay. |
Lifecycle and retention fields
| Field | Type | Notes |
|---|---|---|
retention_status | String(32), default "active", indexed | One of active | archived | soft_deleted | hard_delete_pending | purged. |
retention_expires_at | DateTime (TZ), indexed, nullable | When the active window ends. |
archive_at | DateTime (TZ), indexed, nullable | When the row transitions to read-only archived. |
hard_delete_at | DateTime (TZ), indexed, nullable | When the row is queued for permanent deletion (after the 7-day grace). |
archived_at / soft_deleted_at / hard_delete_queued_at / purged_at | DateTime (TZ), nullable each | Set when each transition fires; never cleared. |
Platform-owned scoring fields
quality_score— semantic quality from the analysis pass, [0, 1], nullable.confidence_score— accuracy confidence, [0, 1], nullable.freshness_score— content-type-aware recency factor, [0, 1], nullable.decay_score— exponential decay over time-without-use, default1.0.usage_count— cumulative recall hits, default0.last_accessed_at— set every time the memory is returned by a query.consistency_score— default1.0; reduced by every recorded contradiction.evidence_count— default0; incremented for every supports/extends edge.
Intelligence and extraction identity
importance_score— deterministic 0–100 score from the gating pass, nullable until evaluated.intelligence_status—pending | processed | batched | skipped | failed; defaultpending.estimated_cost_micros— projected processing cost in micro-USD, used by the cost gate.last_evaluated_at/reevaluation_count— when and how often the gate re-scored.extracted_type— semantic category (fact,event,decision, …).extracted_key— canonical dedup key.extraction_attempt_id— link to the extraction run that produced this memory.
Relational and tier fields
parent_id(Integer, indexed, nullable) — when a memory is a fragment of another.summary_of(JSON array of ids) — when this row is itself a summary, the list of source memory ids it consolidates.is_summary(Boolean, defaultfalse) — flips when the summarizer produced this row.tier(String(16), default"hot", indexed) — one ofhot | warm | cold; controls indexing strategy and recall SLA.