<!--
  Full-page Markdown export (rendered HTML → GFM).
  Source: https://neotoma.io/ru/primitives/observations
  Generated: 2026-04-27T12:50:29.462Z
-->
# Observations

An observation is a granular, source-specific statement about an entity at a point in time. Observations are the only thing the reducer reads to compute an entity snapshot, and they are the only place ground truth lives. Snapshots are derived; observations are durable.

Source → Interpretation → Observation → Snapshot. Observations are the third layer, the immutable atoms of truth. Reducers merge them deterministically into snapshots.

## Schema[#](#schema)

Observation shape (conceptual)

SQL / TS

Schema or pattern reference for this primitive.

interface Observation { id: string; entity\_id: string; entity\_type: string; schema\_version: string; source\_id: string; // which raw artifact interpretation\_id: string; // which extraction run (NULL for structured writes) observed\_at: Date; specificity\_score: number; // how specific this observation is source\_priority: number; // 0 = AI, 100 = structured, 1000 = correction fields: Record<string, unknown>; user\_id: string; }

| Field | Type | Purpose |
| --- | --- | --- |
| entity\_id | string | The entity this observation is about (resolved during ingestion, user-scoped) |
| schema\_version | string | Active entity schema version at extraction time |
| source\_id | string | What raw content produced this observation |
| interpretation\_id | string | null | Which extraction run produced this; NULL for structured store\_structured writes |
| observed\_at | Date | When this observation was made (or extracted from the source) |
| specificity\_score | number | Reducer tie-break: how specific this observation is for its fields |
| source\_priority | number | 0 (AI) / 100 (structured agent) / 1000 (user correction). Corrections always win. |
| fields | object | The actual granular facts, whatever the schema admits at this version |

## The three-layer truth model[#](#three-layer)

Source carries raw bytes. Interpretation carries the audit trail of how those bytes were read. Observations carry granular facts that link back to both. Snapshots are deterministically composed from all observations for an entity by the reducer. This separation is what lets Neotoma reinterpret without rewriting history and replay snapshots at any point in time.

◆

## Immutability and provenance[#](#immutability)

Observations are never mutated. Every observation links to its source\_id and interpretation\_id, so any field on any snapshot can be traced back to the exact bytes and extractor that produced it. Reinterpretation, correction, and re-ingest always produce new observations, the audit trail grows monotonically.

◆

## Source priority and merging[#](#priority-and-merging)

When two observations disagree about the same field, the reducer picks the winner using (source\_priority, specificity\_score, observed\_at). User corrections write at priority 1000 and always win. Structured agent writes are at 100. AI interpretations are at 0. This priority is deterministic and surfaceable: the Inspector shows which observation produced each snapshot field.

◆

## Where observations come from[#](#writes)

Three writers create observations: structured store\_structured calls (source\_priority 100, interpretation\_id NULL), AI interpretation pipelines on completion (source\_priority 0, interpretation\_id set), and explicit user corrections via correct() (source\_priority 1000). All writes flow through service\_role on the MCP server.

## Invariants[#](#invariants)

Every observation satisfies the following constraints:

MUST

-   Link to a non-null source\_id and a resolved entity\_id
-   Be immutable, corrections and reinterpretations create new observations, not edits
-   Carry a source\_priority that determines reducer tie-breaks deterministically
-   Pass attribution policy enforcement before write

MUST NOT

-   Be mutated after creation
-   Be created without a corresponding sources row (structured writes still own a synthetic source)
-   Use confidence directly in reducer merge logic, that is reserved for source\_priority and specificity\_score
-   Be returned across user boundaries; every read filters through source ownership

## Related[#](#related)

-   [Observation architecture](https://github.com/markmhendrickson/neotoma/blob/main/docs/subsystems/observation_architecture.md) , Three-layer model, lifecycle, snapshot computation, provenance
-   [Sources](/primitives/sources) , Raw artifact each observation links back to
-   [Interpretations](/primitives/interpretations) , Extraction run each AI-produced observation belongs to
-   [Relationships](/primitives/relationships) , Edges follow the same observation-snapshot pattern
-   [Versioned history](/versioned-history) , Why immutable observations matter for agent memory

## Where to go next[#](#more)

-   [All primitive record types](/primitives) , index of sources, interpretations, observations, relationships, and timeline events
-   [Architecture](/architecture) , how the primitives compose into Neotoma's deterministic state
-   [Terminology](/terminology) , canonical glossary of terms used across Neotoma docs