<!--
  Full-page Markdown export (rendered HTML → GFM).
  Source: https://neotoma.io/pt/primitives/relationships
  Generated: 2026-04-27T12:50:30.852Z
-->
# Relationships

Relationships are first-class typed edges between entities, not hard-coded foreign keys. They are stored as observations and snapshots, so multiple sources can contribute to the same edge, every edge carries full provenance, and the graph stays open-ontology and queryable.

Sits next to entities. Sources produce relationship observations the same way they produce entity observations; the relationship reducer composes them into a relationship snapshot.

## Schema[#](#schema)

Relationship pattern

SQL / TS

Schema or pattern reference for this primitive.

Source → Relationship Observations → Relationship Reducer → Relationship Snapshot // Multiple sources can write the same relationship. // Each write is an immutable observation with its own provenance. // The snapshot merges them with deterministic rules. Source A (Invoice PDF): SETTLES → metadata: { amount: 1500, currency: "USD" } Source B (Bank Record): SETTLES → metadata: { amount: 1500, payment\_method: "wire" } Snapshot (merged): metadata: { amount: 1500, currency: "USD", payment\_method: "wire" } provenance: { amount: "obs\_A", currency: "obs\_A", payment\_method: "obs\_B" }

## Core relationship types[#](#core-types)

PART\_OF (hierarchical containment, e.g. invoice\_line\_item PART\_OF invoice). CORRECTS (corrections supersede originals). REFERS\_TO (mentions / references). SETTLES (payment settles invoice). DUPLICATE\_OF (entity dedupe). DEPENDS\_ON (task ordering). SUPERSEDES (versioning). EMBEDS (container embeds reusable asset, e.g. blog post EMBEDS image).

◆

## Open ontology, not hard-coded hierarchies[#](#open-ontology)

Neotoma does not hard-code parent-child columns or a fixed schema of edge types. Hierarchies emerge from edges, which means out-of-order ingestion, multiple parents, overlapping summaries, and corrections all compose without schema changes. New edge types can be introduced without migrating data.

◆

## Observation-snapshot pattern[#](#observation-pattern)

Each write to a relationship is an immutable observation that carries metadata and provenance. The reducer merges all observations for the same (source\_entity, target\_entity, type) into a single snapshot. The provenance map records, per metadata field, which observation produced which value, exactly the same shape as entity snapshots.

◆

## Queryable in both directions[#](#queryability)

Relationships are first-class rows that can be queried by source entity, target entity, type, or metadata. Read paths support traversals (find all PART\_OF children of an invoice) and reverse lookups (find every entity that REFERS\_TO this contract). Same RLS rules apply, only relationships whose source/target you own are visible.

## Invariants[#](#invariants)

Every relationship satisfies the following constraints:

MUST

-   Be stored as immutable observations + a deterministically computed snapshot
-   Carry full provenance, every metadata field traces to the observation that set it
-   Be typed (PART\_OF / CORRECTS / REFERS\_TO / SETTLES / DUPLICATE\_OF / DEPENDS\_ON / SUPERSEDES / EMBEDS, …)
-   Respect source-ownership RLS on every read path

MUST NOT

-   Be modeled as foreign keys on entity tables
-   Be mutated in place, corrections and supersessions create new observations
-   Be created without explicit source\_entity\_id, target\_entity\_id, and type
-   Bypass the relationship reducer for ad-hoc snapshot writes

## Related[#](#related)

-   [Relationships subsystem doc](https://github.com/markmhendrickson/neotoma/blob/main/docs/subsystems/relationships.md) , Types, graph patterns, query examples
-   [Observations](/primitives/observations) , Underlying primitive each relationship observation builds on
-   [Entity merge](https://github.com/markmhendrickson/neotoma/blob/main/docs/subsystems/entity_merge.md) , DUPLICATE\_OF mechanics and merge handling
-   [Architectural decisions](https://github.com/markmhendrickson/neotoma/blob/main/docs/architecture/architectural_decisions.md) , Why relationships are first-class and the graph is open-ontology

## 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