Engram schema
This page is the full specification of the engram schema. It is generated from and stays in sync with @plur-ai/core/src/schemas/engram.ts — the Zod schema is the source of truth. If you find a discrepancy, the schema wins; please open an issue.
The schema uses .passthrough() at runtime so unknown fields are preserved during parsing — this prevents data loss when new fields are added by hand or by future versions.
If you’re new to engrams, start with the Engrams concept page. This is the deep dive.
At a glance
Section titled “At a glance”id: ENG-2026-0518-001 # requiredversion: 2 # default 2status: active # requiredtype: procedural # requiredscope: project:my-app # requiredstatement: "..." # required, ≥ 1 char# everything else optionalFive required fields. Everything else slots into one of: classification, content, lineage, activation, relations, provenance, feedback, temporal, usage, episodic, exchange, commitment, version history, retrieval hints, polarity.
Identity
Section titled “Identity”| Field | Type | Required | Default | Constraints |
|---|---|---|---|---|
id | string | yes | — | Regex ^(ENG|ABS|META)-[A-Za-z0-9-]+$. ENG- for engrams, ABS- for abstractions, META- for meta-engrams. |
version | int | no | 2 | ≥ 1. The schema version of this engram payload — not to be confused with engram_version (content revision). |
status | enum | yes | — | active · dormant · retired · candidate |
consolidated | bool | no | false | True after this engram has been merged into a META engram. |
type | enum | yes | — | behavioral · terminological · procedural · architectural |
scope | string | yes | — | Hierarchical namespace, e.g. global, project:myapp, group:acme/platform. See Scope conventions. |
visibility | enum | no | private | private (scope only) · public (exportable across orgs) · template (intended for reuse via packs) |
Status lifecycle
Section titled “Status lifecycle”candidate → active → dormant → retiredAuto-extraction creates candidate engrams that need promotion (typically by recurring 3× or an explicit plur_promote). Activation decay can move active → dormant automatically. retired is reachable explicitly (plur_forget) or via supersession by a more recent engram. History is preserved across every transition.
Content
Section titled “Content”| Field | Type | Required | Constraints |
|---|---|---|---|
statement | string | yes | ≥ 1 char. The claim. Must be self-contained. Indexed verbatim by both BM25 and the embedder. |
rationale | string | no | Why this is true / what incident produced it. Indexed alongside the statement — surfaces in recall when the statement alone isn’t enough context. |
contraindications | string[] | no | When this engram does not apply. Reduces false-positive injection. |
A good statement is self-contained. Don’t write “always use it” — write “always validate user input at API boundaries.” The recall pipeline embeds the statement; ambiguous statements embed badly.
Lineage
Section titled “Lineage”How this engram came to be — useful for audit, deduplication, and pack tracking.
| Field | Type | Required | Default |
|---|---|---|---|
source | string | no | — |
source_patterns | string[] | no | — |
derivation_count | int | no | 1 |
pack | string | null | no | null |
abstract | string | null | no | null |
derived_from | string | null | no | null |
Classification
Section titled “Classification”| Field | Type | Required | Default |
|---|---|---|---|
knowledge_type | {memory_class, cognitive_level} | no | — |
domain | string | no | — |
tags | string[] | no | [] |
knowledge_type
Section titled “knowledge_type”knowledge_type: memory_class: semantic # semantic | episodic | procedural | metacognitive cognitive_level: apply # Bloom's: remember | understand | apply | analyze | evaluate | createMemory class follows the cognitive-science taxonomy: semantic knowledge (“X is true”), episodic (“X happened on date D”), procedural (“to do Y, run Z”), metacognitive (“when reasoning about Y, beware of bias B”). Cognitive level uses Bloom’s taxonomy as a coarse difficulty/abstraction axis.
Activation (ACT-R model)
Section titled “Activation (ACT-R model)”Each engram tracks four numbers; together they drive recall priority.
activation: retrieval_strength: 0.7 # default. 0 ≤ x ≤ 1. Decays with time-since-last-access. storage_strength: 1.0 # default. 0 ≤ x ≤ 1. Set at creation; how durable. frequency: 0 # increments on each successful recall. last_accessed: 2026-05-25 # ISO date. Drives decay calculation.| Field | Range | Purpose |
|---|---|---|
retrieval_strength | 0–1 | Drives recall priority. Power-law decay since last_accessed. |
storage_strength | 0–1 | Floor on durability. Set lower for transient context (e.g. session-local notes). |
frequency | int ≥ 0 | Bumped on each successful recall. Used as a strengthening signal. |
last_accessed | ISO date | Time anchor for decay. Updated on recall. |
Conceptual model: Activation & decay. Formula: A(t) = ln(Σ tᵢ^-d) where tᵢ is the time since the i-th access and d is the decay rate (default 0.5).
Relations — hand-curated taxonomy
Section titled “Relations — hand-curated taxonomy”relations: broader: [ENG-2026-0501-007] # parent concepts narrower: [ENG-2026-0510-022] # children / specialisation related: [ENG-2026-0512-014] # siblings / cross-reference conflicts: [ENG-2026-0403-009] # explicit contradiction — must reconcileAll four arrays default to []. Conflicts are picked up by tension detection — saving a new engram that contradicts an existing one produces a warning and (optionally) a forced reconciliation.
Associations — system-observed links
Section titled “Associations — system-observed links”associations: - target_type: engram # engram | document target: ENG-2026-0515-031 strength: 0.82 # 0 ≤ x ≤ 0.95 type: semantic # semantic | temporal | causal | co_accessed updated_at: 2026-05-16 # ISO date, optionalConstraint: strength cannot reach 1.0 — there is always some uncertainty in system-derived associations. Key distinction from relations: relations are what a human says is true; associations are what the system has observed.
Association types:
semantic— embedding similarity.temporal— these engrams accumulate together in time.causal— A is recurrently followed by B in episode history.co_accessed— both retrieved together for related tasks.
Knowledge anchors — pointers to ground truth
Section titled “Knowledge anchors — pointers to ground truth”knowledge_anchors: - path: src/cadastre/migration.ts relevance: primary # primary | supporting | example (default supporting) snippet: "if (parcel.legacy) ..." # optional, ≤ 200 chars snippet_extracted_at: 2026-05-12 # optionalAnchors let an engram refer to a specific code/document location. Recall can inline the snippet; the path lets a reader verify the engram is still accurate. Use sparingly — anchors that drift (paths that no longer exist) signal stale engrams.
Dual coding — example + analogy
Section titled “Dual coding — example + analogy”dual_coding: example: "Parcel #41/2-K.O. Beograd has a legacy split — handle via migration v3.7." analogy: "Like a git rebase: replay the new shape onto the old data."Schema constraint: at least one of example or analogy must be present if dual_coding is set. Use when the statement is abstract; helps both human reviewers and embedding-based retrieval.
Provenance — audit-grade lineage
Section titled “Provenance — audit-grade lineage”provenance: origin: plur_learn:gregor:2026-05-16T12:34Z chain: [ENG-2026-0510-022] # default [] signature: "sha256:abc..." # default null license: cc-by-sa-4.0 # default cc-by-sa-4.0The chain walks back through engrams the current one was derived from. The signature enables tamper detection for high-integrity scopes. The default cc-by-sa-4.0 license allows transfer between scopes — override (e.g., proprietary) to mark engrams non-portable.
Feedback signals
Section titled “Feedback signals”feedback_signals: positive: 12 # default 0 negative: 2 # default 0 neutral: 0 # default 0Drives ROI computation in Enterprise dashboards and pack-export valuations. Updated by plur_feedback.
Temporal anchoring (bi-temporal)
Section titled “Temporal anchoring (bi-temporal)”temporal: learned_at: 2026-05-16 # required if temporal is set valid_from: 2026-01-01 # optional valid_until: 2026-12-31 # optional ingested_at: 2026-05-16 # optionalTwo time axes: when we learned it (learned_at, ingested_at) vs when the claim is true (valid_from, valid_until). Recall can filter by valid time, so date-bound facts (“the deploy freeze runs Nov 15–Jan 5”) expire on their own.
Entities — structured extraction
Section titled “Entities — structured extraction”entities: - name: Apache AGE type: technology # person | organization | technology | concept | project | tool | place | event | standard | other uri: https://age.apache.org # optional, must be a valid URLAuto-extracted from statements at ingest time. Enables graph queries (engrams that mention organization:IGEA). The type enum is closed; unknown things go in other.
Usage tracking
Section titled “Usage tracking”usage: injections: 47 # default 0 hits: 34 # default 0 misses: 13 # default 0 last_hit_at: 2026-05-15T18:22Z # optionalUpdates automatically as the engram is injected and as feedback comes in. Drives the quality slopegraph in the admin Insights view and feeds the decay/retire pipeline.
Episodic fields
Section titled “Episodic fields”episodic: emotional_weight: 7 # 1-10, default 5 confidence: 9 # 1-10, default 5 trigger_context: "post-incident, after Friday rollback" # optional journal_ref: "notes/journals/2026-05-15.md#incident-3" # optionalFor experiential knowledge. High-weight, high-confidence engrams retrieve earlier in episodic-tagged recall. journal_ref lets the engram link back to its conversation/incident of origin.
Exchange metadata — marketplace fitness
Section titled “Exchange metadata — marketplace fitness”exchange: fitness_score: 0.78 # optional, 0-1 environmental_diversity: 12 # default 0. Distinct scopes that adopted it. adoption_count: 47 # default 0. Downloads/installs via packs. contradiction_rate: 0.04 # default 0, 0-1. Fraction of adopters that retired it.Populated when an engram travels via a pack and is re-imported elsewhere. Drives pack-discovery ranking.
Structured data — escape hatch
Section titled “Structured data — escape hatch”structured_data: custom_field_1: "anything" numeric: 42 nested: keys: are: fineRecord<string, unknown> — domain-specific fields the schema doesn’t cover. Survives passthrough validation. Use sparingly; prefer first-class fields when the use case fits.
Polarity
Section titled “Polarity”polarity: do # do | dont | null (default null)Inferred classification of the statement as directive (do) or constraint (dont). Injected separately so the agent doesn’t confuse a rule with an example. Override the inferred value when needed.
Commitment (SP1)
Section titled “Commitment (SP1)”commitment: decided # exploring | leaning | decided | lockedlocked_at: 2026-05-25T14:32:18Z # optionallocked_reason: "Core safety rule — never log secrets" # optionalcontent_hash: "sha256:abc..." # optional| Commitment | Meaning |
|---|---|
exploring | Trying it out, easy to drop. |
leaning | Provisional preference (default for plur_learn). |
decided | Committed for the foreseeable future. |
locked | Meta-rule. Pinned to context regardless of relevance; recorded reason. |
content_hash is a content-addressed fingerprint of the statement (and key derived fields). Used by deduplication to detect “this engram is effectively the same as one we already have.”
Version history (SP2)
Section titled “Version history (SP2)”engram_version: 3 # default 1. Bumps every time the content materially changes.previous_version_ref: event_id: evt-7c3b... changed_at: 2026-05-12T09:14:02Zepisode_ids: [EPS-2026-0512-014, EPS-2026-0513-007] # default []| Field | Purpose |
|---|---|
engram_version | Content revision counter. Bumped on plur_engram update. |
previous_version_ref | Pointer to the event that produced the previous content. |
episode_ids | Sessions where this engram was created or materially updated. |
Retrieval hints (SP3)
Section titled “Retrieval hints (SP3)”summary: "Always validate input at API boundaries" # optional, ≤ 80 charspinned: true # optional| Field | Purpose |
|---|---|
summary | Up to 80 chars — used in injection blocks when full statement is too long. |
pinned | Always-load. Bypasses the term-hits gate in scoreEngram. Pinned engrams are still subject to the token budget but bypass per-pack and per-domain fairness caps in fillTokenBudget. Use sparingly: meta-rules, safety conventions, core operating principles. |
Scope conventions
Section titled “Scope conventions”scope is a string. Common shapes:
| Scope | Meaning |
|---|---|
global | Visible to every authenticated user in the org. |
org:igea | Org-wide; equivalent to global for single-org deployments. |
space:cadastre-RS | A delivered vertical or product. |
project:guardian-v3 | A specific codebase. |
group:igea/backend | A team within a space. |
user:igea:alice | Personal to one user only. |
command:office-hours | Surfaces only when a specific slash-command is invoked. |
agent:miles-on-nightshift | Agent-specific knowledge (avoid overuse; prefer human-readable groups). |
Hierarchy at recall time: a user has access to user:org:self, every group: they belong to, every space:, org:, and global — narrowest first. Permission resolution is in src/permissions/resolver.ts (Enterprise).
Validation behaviour
Section titled “Validation behaviour”- Strict schema is exported as
EngramSchema— TypeScript types are derived from this. - Runtime validation uses
EngramSchemaPassthrough— unknown fields are preserved, not rejected. This is deliberate: forward-compat with hand-edited engrams and future-version migrations. - The
idregex is strict — invalid IDs throw at parse time. Don’t hand-craft IDs; let the engine generate them. - Numeric ranges (0–1, 1–10) and string max-lengths (
summary ≤ 80,snippet ≤ 200) are enforced.
What gets persisted vs computed
Section titled “What gets persisted vs computed”- Persisted (
~/.plur/engrams.yamllocally;engramstable in Enterprise Postgres): everything above, as YAML or JSONB. - Computed at query time: hybrid-search scores, RRF fusion, spreading-activation weights, decay-adjusted retrieval strength.
See docs/injection-formula.md in the Enterprise repo for the full retrieval algorithm.
Related TypeScript types
Section titled “Related TypeScript types”The schema exports these types — useful for SDK consumers:
type Engram = z.infer<typeof EngramSchema>type KnowledgeAnchor = z.infer<typeof KnowledgeAnchorSchema>type Association = z.infer<typeof AssociationSchema>type EntityRef = z.infer<typeof EntityRefSchema>type Temporal = z.infer<typeof TemporalSchema>type UsageStats = z.infer<typeof UsageStatsSchema>type EpisodicFields = z.infer<typeof EpisodicFieldsSchema>type ExchangeMetadata = z.infer<typeof ExchangeMetadataSchema>type PreviousVersionRef = z.infer<typeof PreviousVersionRefSchema>Source of truth: @plur-ai/core/src/schemas/engram.ts.