The Memory Multigraph

por Frank de Alcantara em 23/07/2026

The Memory Multigraph

Lia tells Aurora that she prefers tea without sugar. Two days later, Aurora recommends tea and Lia accepts. Weeks later, Lia says that she avoids caffeine at night, then resumes drinking coffee in the morning. A table can store these sentences. A vector index can retrieve similar passages. Neither structure alone tells us what is an entity, what is a claim, which observation supports it, which action produced an outcome, or why two apparently incompatible statements may both be valid.

We need a data model in which experience remains inspectable after the original conversation leaves the context window. The model must preserve repeated relations between the same participants, give every important object a stable identity, and let retrieval reconstruct evidence instead of returning isolated text.

In this article, we build that model as a typed property multigraph. We will decide which objects become vertices, which relations remain edges, and when a relation must itself become a vertex. We will derive schema invariants, implement a compact C++23 reference, use two interactive laboratories, and solve 65 exercises.

This article depends on two earlier results in the series. Multigraphs: Parallel Edges and Distinct Paths established that endpoints do not identify an edge. Memory for Agents: From Context to Persistent Experience established that memory is a selective cycle of writing, management, reading, and use. Here we join those results.

1. Why memory needs a multigraph

Suppose we represent Lia and tea as two vertices. Between them, at least four relations may occur:

  1. Lia states a preference for tea on day 0;
  2. Aurora recommends tea on day 2;
  3. Lia accepts tea on day 2;
  4. Lia qualifies her consumption by avoiding caffeine at night on day 52.

A simple graph permits at most one edge between a given ordered pair. If we collapse these observations into a generic related_to edge, the graph preserves connectivity and destroys meaning. If we retain only the latest edge, it preserves a current fragment and destroys history. If we store a list property on one edge, the observations survive physically but lose independent identity.

Let $u$ represent Lia and $v$ represent tea. In a multigraph, the endpoint function may map several edges to the same ordered pair:

\[s(e_0)=s(e_1)=u,\qquad t(e_0)=t(e_1)=v,\qquad e_0\ne e_1.\]

The distinction $e_0\ne e_1$ is not cosmetic. It lets us attach different event times, sources, confidence values, permissions, validity intervals, and deletion states. One occurrence can be corrected without rewriting another.

Try both views in the laboratory. Add the day 52 observation, then collapse the graph.

The laboratory exposes a general rule:

Repeated endpoints do not imply duplicate meaning.

We should deduplicate ingestion retries, not legitimate multiplicity. Two records are duplicates only under an explicit equivalence key such as source event identifier, extractor version, and payload hash. Similar text is insufficient.

1.1 Solved exercises

Exercise 1.1. Lia says “tea, please” twice on different days. Must the two observations become one edge?

Solution. No. They are two occurrences with different event identities and times. A later consolidation process may infer a stable preference, but the episodes remain separate evidence.

Exercise 1.2. A client retries the same write request three times with the same event identifier. How many occurrence edges should remain?

Solution. One. The shared event identifier makes the writes ingestion duplicates rather than three independent observations. Idempotency and multigraph multiplicity solve different problems.

Exercise 1.3. What is lost if prefers, accepted, and avoids_at_night become one related_to edge?

Solution. Relation type, event role, temporal scope, and explanatory value are lost. The graph can answer whether Lia and tea are connected but not why or under which conditions.

Exercise 1.4. Can two edges have the same source, target, label, and day and still be distinct?

Solution. Yes. They may come from different sources or record separate events during the same day. Whether to merge them depends on a declared identity rule, not endpoint equality.

Exercise 1.5. Why not place every observation in an array property on Lia?

Solution. The array hides graph structure. Individual observations cannot be targeted by provenance, version, authorization, or traversal edges without introducing an external addressing scheme.

2. A typed property multigraph

We define the memory graph as

\[\mathcal M= (V,E,s,t,\lambda_V,\lambda_E,X_V,X_E).\]

The components are:

  • $V$, a finite set of vertices;
  • $E$, a finite set of edge occurrences;
  • $s:E\rightarrow V$, the source function;
  • $t:E\rightarrow V$, the target function;
  • $\lambda_V:V\rightarrow L_V$, the vertex-type function;
  • $\lambda_E:E\rightarrow L_E$, the edge-type function;
  • $X_V:V\rightarrow\mathcal P$, vertex properties;
  • $X_E:E\rightarrow\mathcal P$, edge properties.

Here $\mathcal P$ is a space of finite key-value maps. A vertex may carry a canonical name or content hash. An edge may carry event time, confidence, extraction method, and access scope. We use a directed graph because roles are asymmetric: a claim has a subject, a message asserts a claim, and an action produces an outcome.

The model is a multigraph because $s$ and $t$ need not be injective. Several edges can share endpoints. It is a property graph because vertices and edges carry properties. It is typed because $\lambda_V$ and $\lambda_E$ restrict the vocabulary.

For our canonical example:

\[\lambda_V(v_{\text{Lia}})=\texttt{Person}, \qquad \lambda_V(v_{C0})=\texttt{Claim},\] \[\lambda_E(e_0)=\texttt{SUBJECT}, \qquad s(e_0)=v_{C0}, \qquad t(e_0)=v_{\text{Lia}}.\]

The claim also declares its semantic predicate:

\[X_V(v_{C0})[\texttt{predicate}]=\texttt{prefers}.\]

Without this property or an equivalent predicate vertex, subject and object would not distinguish “Lia prefers tea” from “Lia rejects tea.”

Typing serves three purposes. First, it makes illegal structures detectable. Second, it makes traversals meaningful. Third, it documents what the system believes it is storing. A generic Node and Edge API may implement the structure, but the application still needs a schema.

We distinguish the schema graph from the instance graph. The schema says that SUBJECT may connect Claim to Person or Entity. The instance says that claim C0 has Lia as subject. Confusing the two causes either an unvalidated data swamp or an ontology so rigid that ordinary experience cannot enter it.

2.1 Solved exercises

Exercise 2.1. Which component gives an edge its relation type?

Solution. $\lambda_E$. It maps every edge occurrence in $E$ to a label in the edge-type vocabulary $L_E$.

Exercise 2.2. Which equation permits parallel edges?

Solution. No special equation is required. Parallel edges are possible because distinct $e_i,e_j\in E$ may satisfy $s(e_i)=s(e_j)$ and $t(e_i)=t(e_j)$.

Exercise 2.3. Is confidence part of $\lambda_E$?

Solution. Usually not. SUPPORTED_BY is a type, while confidence is a property in $X_E(e)$. Mixing continuous values into the type vocabulary creates unnecessary labels.

Exercise 2.4. Why include edge properties if claims are vertices?

Solution. Occurrence-level facts still belong to edges. The confidence of one source link, the time of one participation, or the extractor responsible for one relation should not be copied onto an entire claim vertex.

Exercise 2.5. Can the same physical store contain several logical memory graphs?

Solution. Yes. Tenant, user, agent, workspace, or policy scope can partition a physical store. The logical graph must still enforce isolation so traversal does not cross an unauthorized boundary.

3. Identity comes before labels

The string Lia is a label, not an identity. Two people may share that name, and one person may appear as Lia, lia@example, and customer-1842. If identity is inferred from display text, the graph silently merges users or fragments one user into several vertices.

We therefore separate:

\[\operatorname{id}(v)\ne \operatorname{label}(v).\]

A stable identifier should survive label changes and remain unique within its authority. It may be an application UUID, a namespaced database key, or a deterministic identifier derived from a trusted external key. The choice is operational, but three rules are stable:

  1. identity keys need an explicit authority and scope;
  2. display labels are mutable properties;
  3. entity resolution produces evidence, not metaphysical certainty.

Suppose an extractor proposes that Lia in message $m_0$ and customer 1842 are the same person. We should not rewrite every reference immediately. We can create an IDENTITY_CANDIDATE object with a score and evidence, or a qualified SAME_AS relation. A human decision or a high-confidence policy may later accept the merge.

Edges also need stable identities. A tuple such as

\[(\text{source},\text{type},\text{target})\]

cannot identify an edge in a multigraph because several legitimate occurrences share that tuple. An edge identifier must distinguish the day 2 recommendation from the day 52 recommendation.

Messages and external documents benefit from content hashes, but a hash alone is not always an event identity. Two separate messages can contain identical text. The event identifier distinguishes occurrences, while the content hash helps detect repeated payloads.

3.1 Solved exercises

Exercise 3.1. Lia changes her display name to Amelia. Should her vertex identifier change?

Solution. No. The label property changes while the stable identity remains. Changing the identifier would break historical edges and could create a false second person.

Exercise 3.2. Two users have the label “Alex.” May they share a vertex?

Solution. Not on label evidence alone. The graph needs a scoped identity key or supported entity-resolution decision.

Exercise 3.3. Two messages have identical text and different message identifiers. Are they duplicates?

Solution. They are distinct message events with duplicate content. A retrieval layer may group them, but provenance should preserve both occurrences unless policy says otherwise.

Exercise 3.4. Can (Aurora, recommends, tea) be an edge primary key?

Solution. No. It would reject the second recommendation or overwrite the first. The tuple can be an index key, but not the occurrence identity.

Exercise 3.5. An entity resolver has confidence $0.61$ that two records refer to Lia. What should the graph do?

Solution. Preserve the proposed match and its evidence as uncertain state. A threshold may prevent automatic merging, especially when a false merge would cross user boundaries.

4. The vertex vocabulary

A memory graph should not turn every noun into the same kind of node. We start with eight vertex types:

Type Represents Example
Person a human identity Lia
Agent an acting computational identity Aurora
Entity a domain object or concept tea without sugar
Message an immutable source occurrence day 0 utterance
Episode a situated event container day 2 recommendation
Claim an addressable proposition Lia prefers tea
Action an intentional operation recommend tea
Outcome an observed result recommendation accepted

These types separate five questions that a flat triple cannot answer by itself:

  • Who or what existed?
  • What was said?
  • What proposition was extracted?
  • What happened?
  • What result followed?

The separation also prevents a common error: treating source text as knowledge. A Message records that a payload arrived. A Claim records the proposition attributed to that source. The message may be authentic while the claim is false, sarcastic, hypothetical, or extracted incorrectly.

Episode is an event container rather than a transcript chunk. It groups participants, actions, objects, circumstances, and outcomes that belong to one situated interaction. Its boundary is a modeling decision. A useful rule is that an episode should support one coherent answer to “what happened and with what result?”

Action and Outcome remain separate because an agent can perform the same action with different results. If we store only successful actions, procedural learning becomes survivorship bias.

This vocabulary is deliberately small. Domains may add Organization, Location, Goal, Procedure, or Policy. Extension is safer than placing everything in a generic node and relying on prose labels.

4.1 Solved exercises

Exercise 4.1. “Lia said that Aurora prefers coffee.” Is the message itself a Claim?

Solution. No. The source occurrence is a Message. The extracted proposition about Aurora is a separate Claim linked to that message.

Exercise 4.2. Aurora recommends tea, but Lia rejects it. Which vertices are required?

Solution. At minimum, an Episode, an Action for the recommendation, and an Outcome for rejection, plus participant and object vertices. This preserves action from result.

Exercise 4.3. Should tea without sugar be text on the claim or an Entity?

Solution. It can appear in display text, but an entity vertex is preferable when several claims, actions, or episodes refer to the same object. The shared identity enables traversal and aggregation.

Exercise 4.4. When is an Episode too broad?

Solution. When it groups unrelated actions and outcomes so that causal or participant roles become ambiguous. A week-long session summary may need several episodes.

Exercise 4.5. Why is Agent distinct from Person if both can perform actions?

Solution. They have different authority, accountability, and policy semantics. A typed edge can still permit both as participants while access control and provenance distinguish them.

5. Edges are first-class occurrences

An edge connects two vertices, but it also records one occurrence of a relation. We use role-oriented types:

Edge type Allowed pattern Meaning
SUBJECT Claim -> Person/Agent/Entity claim subject
OBJECT Claim -> Entity/Claim claim object
ASSERTED_BY Claim -> Message/Source attributed source
SUPPORTED_BY Claim -> Episode/Message supporting evidence
PARTICIPANT Episode -> Person/Agent event participant
RECOMMENDS Agent -> Entity recommendation occurrence
ACCEPTS Person -> Entity acceptance occurrence
PRODUCES Episode/Action -> Action/Outcome event structure
QUALIFIES Claim -> Claim/Entity contextual restriction
SUPERSEDES Claim -> Claim version relation

Each edge receives its own identifier and properties. A recommendation edge may store

id = E6
event_day = 2
confidence = 0.96
extractor = relation-extractor-v3
scope = lia-private

If Aurora recommends tea again on day 52, we add E7. We do not mutate E6. The parallel pair expresses repeated action and allows independent evaluation.

The direction of an edge should encode a stable reading. We read Claim -[SUBJECT]-> Person as “the claim has this subject,” not as “the person is claimed by.” Consistent direction reduces query branching.

An edge should remain an edge when it is binary, its metadata belongs to one occurrence, and other domain facts rarely need to point to it. It should become or gain an addressable vertex when it participates in further relationships. This is the boundary we explore in the next section.

5.1 Solved exercises

Exercise 5.1. What distinguishes E6 from E7 if both are Aurora -[RECOMMENDS]-> tea?

Solution. Their edge identifiers and occurrence properties. In the reference example, their days and confidence values differ.

Exercise 5.2. Where should the extractor version live?

Solution. On the generated claim or edge, or on an explicit extraction activity linked by provenance. It should not be inferred from the current software version.

Exercise 5.3. Why use PARTICIPANT from episode to person instead of the reverse?

Solution. The chosen direction makes the episode a traversal hub. One outgoing expansion enumerates all participants. The reverse could work if used consistently, but mixed direction complicates queries.

Exercise 5.4. Must all edge types permit properties?

Solution. The implementation may permit them uniformly, but the schema should define which properties are required or allowed. For example, an occurrence edge may require event time, while a structural SUBJECT edge may inherit time from its claim.

Exercise 5.5. Is a second identical edge automatically stronger evidence?

Solution. No. It may be a retry, copied source, correlated observation, or independent evidence. Confidence aggregation requires provenance-aware dependence, not edge count alone.

6. Claims as vertices

The compact representation

Lia -[PREFERS]-> tea

is useful when the relation is uncomplicated. It becomes insufficient when we need to ask:

  • Who asserted the preference?
  • Which message expressed it?
  • Which episode supports it?
  • Is it valid only in the morning?
  • Which claim corrects it?
  • Who may read or delete it?

Most property-graph systems allow properties on edges, so we could attach source and time directly. The difficulty appears when other facts must point to the proposition. A portable property graph connects edges to vertices, not ordinary edges to other edges.

We therefore reify an important proposition by giving it a vertex:

\[v_{C0}=\text{“Lia prefers tea without sugar”}.\]

Then:

\[C0\xrightarrow{\texttt{SUBJECT}}\text{Lia}, \qquad C0\xrightarrow{\texttt{OBJECT}}\text{tea without sugar},\] \[C0\xrightarrow{\texttt{ASSERTED\_BY}}m_0, \qquad C0\xrightarrow{\texttt{SUPPORTED\_BY}}E_1.\]

The vertex property predicate=prefers completes the proposition. A richer ontology may instead connect C0 to an independently identified predicate vertex.

Reification does not assert truth. It creates an addressable object representing a proposition, assertion, belief, or extraction. This distinction aligns with RDF 1.2 triple terms and reifiers, where a referenced proposition need not itself be asserted.

The cost is structural. A direct relation uses one edge. Our reified claim uses one vertex and at least two role edges, plus evidence links. Traversals become longer and storage grows. We should reify selectively when provenance, qualification, versioning, permissions, or evidence justify the cost.

Use the laboratory to attach an episode and a qualified version in both representations.

6.1 Solved exercises

Exercise 6.1. Does creating a claim vertex mean that the claim is true?

Solution. No. It means the proposition is addressable. Truth status, confidence, source, and validity remain separate.

Exercise 6.2. How many role edges are minimally needed for a binary claim?

Solution. Usually two: one SUBJECT and one OBJECT. Attribution and evidence add further edges.

Exercise 6.3. When is a direct edge preferable?

Solution. When the relation is simple, does not need independent inbound links, and its occurrence metadata fits naturally on the edge. Reifying every relation makes the graph unnecessarily verbose.

Exercise 6.4. A claim has three sources. Do we duplicate the claim vertex?

Solution. Not if the sources support the same proposition under the same scope. We can attach three distinct source or evidence edges. If the assertions differ in meaning, time, or authority, separate claim or assertion vertices may be safer.

Exercise 6.5. Why is edge identity still necessary after claims become vertices?

Solution. The links to sources and evidence may themselves occur multiple times and carry independent properties. Reification solves addressability of the proposition, not multiplicity of every relation.

7. Episodes model n-ary events

The sentence “Aurora recommended tea to Lia on day 2 and Lia accepted” contains more than a binary relation. It has an agent, recipient, object, action, time, and outcome. Encoding all of this as Aurora -[RECOMMENDS]-> tea loses Lia’s role and the outcome.

An episode vertex converts the n-ary event into a star of binary relations:

\[E_1\xrightarrow{\texttt{PARTICIPANT}}\text{Aurora}, \qquad E_1\xrightarrow{\texttt{PARTICIPANT}}\text{Lia},\] \[E_1\xrightarrow{\texttt{PRODUCES}}A_1, \qquad A_1\xrightarrow{\texttt{PRODUCES}}O_1.\]

The action $A_1$ is “recommend tea,” and the outcome $O_1$ is “accepted.” Tea is connected to the action as its object. The episode carries the situated boundary and event time. Role-specific edges can replace generic PARTICIPANT when the domain needs ACTOR, RECIPIENT, or OBSERVER.

Why not use a hypergraph? A hyperedge can connect more than two vertices directly and is mathematically natural for n-ary events. We choose an event vertex because property-graph stores, graph query languages, and ordinary adjacency structures operate on binary edges. The event vertex also offers an identity to which sources, summaries, permissions, and later reflections can attach.

Episode identity must not depend solely on its participants. Aurora and Lia can interact many times. A stable source event identifier, transaction identifier, or application-generated UUID is more appropriate.

Episodes also protect causal analysis. We should not infer that an action caused an outcome merely because their times are close. The PRODUCES or FOLLOWED_BY link records the modeled relation and can carry confidence.

7.1 Solved exercises

Exercise 7.1. Why is (Aurora, Lia, tea) not enough to identify an episode?

Solution. The same participants and object may recur across many sessions. Event identity also needs an occurrence key or trusted source identifier.

Exercise 7.2. Lia rejects the recommendation. Which object changes?

Solution. The Outcome vertex becomes a rejection outcome. The action remains “recommend tea,” which preserves the difference between behavior and result.

Exercise 7.3. When should one conversation become several episodes?

Solution. When it contains distinct action-outcome units or unrelated goals. Episode boundaries should preserve coherent causal and contextual interpretation.

Exercise 7.4. What advantage does a hyperedge have?

Solution. It represents an n-ary relation directly without introducing a hub vertex. Its disadvantage is weaker support in common property-graph tooling and fewer ordinary objects to attach provenance to.

Exercise 7.5. Can an episode support several claims?

Solution. Yes. One interaction may support a preference claim, an outcome claim, and a procedural observation. Each support edge remains independently addressable.

8. Evidence and provenance are subgraphs

A confidence number without provenance is difficult to interpret. A value of $0.92$ may come from Lia’s direct statement, an extractor’s classifier output, ten copied summaries, or Aurora’s own inference. The same number represents different epistemic situations.

We model provenance as a subgraph. At minimum, a claim should identify:

  • the source occurrence;
  • the extraction or derivation activity;
  • the responsible agent or software version;
  • supporting and opposing evidence;
  • the time at which each operation occurred.

The W3C PROV model offers three useful starting classes: Entity, Activity, and Agent. A message is an entity, extraction is an activity, and the extractor is an agent or software agent. The claim is generated by the extraction and attributed to its source.

In our smaller vocabulary, we may write:

\[m_0\xrightarrow{\texttt{INPUT\_TO}}x_0, \qquad x_0\xrightarrow{\texttt{GENERATES}}C0, \qquad x_0\xrightarrow{\texttt{RUN\_BY}}\text{extractor-v3}.\]

This extra structure separates source confidence from extraction confidence. Lia may be an authoritative source for her own preference, while the extractor may still misread negation. Conversely, extraction may be certain that a statement was made while the speaker is unreliable about an external fact.

Evidence aggregation must account for dependence. Let $w_i$ be the reliability weight of evidence item $i$. The tempting independent-evidence formula

\[C=1-\prod_{i=1}^{n}(1-w_i)\]

gives $C=0.99$ for two items with $w_1=w_2=0.9$. If both items copy the same message, this result is unjustified. Provenance paths reveal the shared ancestor and prevent double counting.

Provenance also supports deletion. If Lia revokes consent for message $m_0$, a traversal can locate claims, summaries, embeddings, and caches derived from it. A source row alone is not the full deletion surface.

8.1 Solved exercises

Exercise 8.1. A message is trusted with $0.95$, but extraction confidence is $0.70$. Is claim confidence automatically $0.95$?

Solution. No. Source reliability and extraction correctness are separate. A baseline may combine them, but the graph should preserve both components rather than hide them in one number.

Exercise 8.2. Two summaries cite the same message. Are they two independent pieces of evidence?

Solution. No. Their provenance converges on one source. Counting them independently would amplify duplication.

Exercise 8.3. Evaluate $1-(1-0.8)(1-0.5)$ under an independence assumption.

Solution. The result is $1-(0.2)(0.5)=0.9$. The number is valid only if the evidence items are sufficiently independent and the combination rule is calibrated.

Exercise 8.4. Why store the extractor version?

Solution. It allows audits, targeted recomputation, and comparison after model upgrades. Without it, a later system cannot explain how the claim was produced.

Exercise 8.5. Which traversal helps implement derived-data deletion?

Solution. Starting at the revoked source, follow derivation and generation edges to claims, summaries, indexes, and cached packets. Policy then determines whether each dependent object is deleted, recomputed, or retained under another lawful source.

9. Time must not destroy history

Memory contains several notions of time. This article introduces the distinction; the next article develops it fully.

Event time answers when the represented interaction occurred. Validity time answers when a claim was considered true in the modeled world. Transaction time answers when the memory system stored or changed the record.

For a claim $c$, we may store:

\[\operatorname{event}(c)=0, \qquad \operatorname{valid}(c)=[0,52), \qquad \operatorname{recorded}(c)=1.\]

These values need not match. A user can report today that an event happened last week. A correction can arrive after a claim ceased to be valid. If we keep only created_at, temporal questions become ambiguous.

We model updates by adding versions and closing intervals, not by overwriting content:

\[C0\xrightarrow{\texttt{SUPERSEDES}^{-1}}C1, \qquad \operatorname{valid}(C0)=[0,52), \qquad \operatorname{valid}(C1)=[52,\infty).\]

The direction should be documented. In this series, C1 -[SUPERSEDES]-> C0 means the new claim supersedes the old claim.

Not every new observation closes an old interval. “Lia drinks coffee in the morning” does not invalidate “Lia avoids caffeine at night.” The claims have different temporal scopes. Qualification must be checked before contradiction.

A current-state query selects claims whose validity interval contains the query time. A historical query selects a past instant. An audit query additionally constrains transaction time to what the system knew at that moment. These are different questions.

9.1 Solved exercises

Exercise 9.1. An event occurs on day 10 and is recorded on day 14. What are the two times?

Solution. Event time is day 10; transaction or recording time begins on day 14. Conflating them would place the event four days late.

Exercise 9.2. Is created_at sufficient for “what did Lia prefer on day 12?”

Solution. No. Creation time does not state the claim’s validity interval. We need validity time and possibly event time.

Exercise 9.3. A claim is valid on $[0,52)$. Is it valid at day 52?

Solution. No. The interval is half-open: it includes day 0 and excludes day 52. Half-open intervals avoid overlap at a clean version boundary.

Exercise 9.4. Why keep transaction time?

Solution. It distinguishes the modeled past from the database’s knowledge history. An audit can reconstruct what the agent could have known before a late correction arrived.

Exercise 9.5. Does a morning coffee observation supersede a night caffeine restriction?

Solution. No. Their scopes are compatible. A schema that drops qualifiers may create a false contradiction and then perform an invalid update.

10. Qualification, disagreement, and versions

A proposition without scope is often too strong. Compare:

Lia avoids caffeine.
Lia avoids caffeine at night.
Lia avoids caffeine at night while taking medication M.

The second and third claims add qualifiers. We can store common qualifiers as properties when they are atomic and local, such as time_of_day=night. We should model them as vertices when they have their own identity, provenance, hierarchy, or reuse. A Context vertex may combine time, location, task, user state, and policy.

Two claims disagree only after we align:

  1. subject identity;
  2. predicate meaning;
  3. object identity;
  4. temporal and contextual scope;
  5. modality and polarity;
  6. source authority.

If these dimensions match and the propositions are incompatible, we have a contradiction candidate. The graph should preserve both claims, their evidence, and a relation such as CONTRADICTS. A resolver may later create a decision object that selects a current view.

We distinguish four relations:

  • EQUIVALENT_TO: same proposition under the modeled scope;
  • SPECIALIZES: one claim has a narrower scope;
  • CONTRADICTS: claims cannot both hold under aligned scope;
  • SUPERSEDES: a version-management decision makes one the successor.

CONTRADICTS is epistemic; SUPERSEDES is operational. Conflicting sources may remain unresolved without either claim superseding the other. Conversely, a new version may supersede an old record because of policy even when the texts are not logical negations.

Current memory is therefore a view over the version graph:

\[V_{\text{current}}(q,\tau)= \{c\mid \tau\in\operatorname{valid}(c),\ \operatorname{scope}(c)\sim q,\ \operatorname{status}(c)\ne\texttt{retracted}\}.\]

The symbol $\sim$ means compatible with the query context, not textual similarity.

10.1 Solved exercises

Exercise 10.1. “Lia likes tea” and “Lia likes green tea” are necessarily contradictory. True or false?

Solution. False. The second may specialize the first. Ontology and scope determine whether the broader statement is supported, underspecified, or incompatible.

Exercise 10.2. Two sources make incompatible claims with equal authority. Which one should be deleted?

Solution. Neither by default. Preserve both, connect the disagreement, and expose uncertainty until new evidence or policy resolves it.

Exercise 10.3. Does CONTRADICTS imply SUPERSEDES?

Solution. No. Contradiction records incompatibility. Supersession records a version decision. One can exist without the other.

Exercise 10.4. When should a qualifier be a vertex?

Solution. When it needs reuse, hierarchy, provenance, permissions, or incoming relations. A simple local scalar may remain a property.

Exercise 10.5. What makes “night” compatible with a query?

Solution. A context-matching rule. It may compare local time, timezone, user schedule, and policy definitions. Lexical equality alone is not a complete temporal semantics.

11. Retrieval constructs an evidence subgraph

Nearest-neighbor retrieval returns individually similar items. Memory reading must construct a bounded subgraph that supports a decision. For Lia’s day 90 evening request, the initial semantic candidate may be claim C2, “Lia avoids caffeine at night.” The reader should then expand to:

  • the message that asserted C2;
  • the episode or observations supporting it;
  • compatible preference C0;
  • the morning-coffee claim that qualifies the apparent contradiction;
  • relevant policy and authorization state.

Let $S_0$ be seed nodes from lexical, vector, temporal, or keyed lookup. We expand through an allowed relation set $R_q$:

\[S_{k+1}=S_k\cup \{v\mid \exists u\in S_k,\ e\in E: s(e)=u,\ t(e)=v,\ \lambda_E(e)\in R_q\}.\]

Unbounded expansion is dangerous. High-degree entities can pull most of the graph into context. We impose budgets:

\[\lvert V_Q\rvert\le B_V,\qquad \lvert E_Q\rvert\le B_E,\qquad \operatorname{tokens}(Q)\le B_T.\]

The packet should maximize utility while preserving minimum evidence coverage:

\[\max_{Q\subseteq\mathcal M} \sum_{x\in Q}u(x,q) \quad\text{subject to budgets and provenance constraints}.\]

A practical reader performs four stages:

  1. retrieve seed claims and episodes;
  2. expand mandatory provenance and version links;
  3. diversify redundant evidence;
  4. serialize the chosen subgraph with identifiers and source citations.

The serialization should not flatten uncertainty. It can state: C2, confidence 0.99, asserted by message M2, valid at night, compatible with C3 about morning coffee. The generator then receives a structured justification rather than anonymous prose.

11.1 Solved exercises

Exercise 11.1. Why not expand every neighbor of Lia?

Solution. Lia may be a high-degree vertex containing years of unrelated experience. Unrestricted expansion exceeds the context budget and introduces distractors.

Exercise 11.2. What should happen if a seed claim is disputed?

Solution. Mandatory expansion should include the competing claim, provenance, and resolution status. Returning only the seed would hide material uncertainty.

Exercise 11.3. With $B_V=6$, can a seven-vertex explanation be returned unchanged?

Solution. No. The reader must compress, replace some nodes with a cited summary, or raise the budget. Silently dropping mandatory provenance would violate the packet contract.

Exercise 11.4. Why serialize identifiers?

Solution. Identifiers let downstream output cite evidence, support audits, and distinguish similar texts or different versions.

Exercise 11.5. Is a one-hop neighborhood always sufficient?

Solution. No. A claim may reach its source through an extraction activity or its outcome through an episode and action. Depth should follow query semantics, not a universal hop count.

12. Schema invariants and the C++23 reference

A graph that accepts every edge is not a reliable memory. We need invariants that can be checked at write time or in audits:

  1. every node and edge has a unique stable identifier;
  2. every edge endpoint exists;
  3. every edge type obeys its source-target type rule;
  4. a binary claim has a declared predicate and exactly one active subject and one active object per version;
  5. every extracted claim has source or derivation provenance;
  6. event and validity intervals are well formed;
  7. tenant and authorization scope do not leak across edges;
  8. supersession is irreflexive and version cycles are rejected;
  9. ingestion idempotency does not collapse independent occurrences;
  10. confidence values are finite and lie in $[0,1]$.

The memory_multigraph.cpp implementation focuses on structural identity. NodeId and EdgeId are distinct types:

struct NodeId {
    std::uint32_t value{};
    auto operator<=>(const NodeId&) const = default;
};

struct EdgeId {
    std::uint32_t value{};
    auto operator<=>(const EdgeId&) const = default;
};

Adding an edge validates endpoints, day, confidence, and identifier capacity. Crucially, it never treats endpoints as an identity key:

const auto id = EdgeId{static_cast<std::uint32_t>(edges_.size())};
edges_.push_back(Edge{id, from, to, kind, event_day, confidence});
outgoing_[from.value].push_back(id);

Node insertion also rejects a Claim without a predicate. This validation prevents a structurally connected but semantically incomplete proposition.

The adjacency index stores outgoing edge identifiers. This preserves parallel occurrences and lets a query retrieve their independent properties. For Aurora -[RECOMMENDS]-> tea, the verified output is:

nodes=8 edges=11
parallel_recommendations=2
  E6 day=2 confidence=0.96
  E7 day=52 confidence=0.72
claim=C5 predicate=prefers | Lia prefers tea without sugar
  E0 subject -> person:Lia
  E1 object -> entity:tea without sugar
  E2 asserted_by -> message:Lia: I prefer tea without sugar
  E3 supported_by -> episode:evening recommendation on day 2

Suggested GCC compilation:

g++ -std=c++23 -O2 -Wall -Wextra -Wconversion -Wshadow -pedantic \
    memoria_grafos/codigo/memory_multigraph.cpp -o memory_multigraph

With contiguous vectors, insertion is amortized $O(1)$. Outgoing lookup by type costs $O(d^+(v))$ in this baseline, where $d^+(v)$ is the out-degree. Claim incidence scans all $m$ edges and costs $O(m)$ because we built only an outgoing index. A production store adds incoming, type, temporal, source, scope, and vector indexes according to measured workloads.

12.1 Solved exercises

Exercise 12.1. Why use distinct NodeId and EdgeId types?

Solution. They prevent accidental interchange and document API intent without meaningful runtime cost. A raw integer cannot express which identifier space it belongs to.

Exercise 12.2. Why is insertion only amortized $O(1)$?

Solution. std::vector occasionally reallocates and copies or moves existing elements. Across many insertions, the average cost per insertion remains constant.

Exercise 12.3. The graph has $m=10^7$ edges. Is an $O(m)$ incidence scan appropriate for every query?

Solution. No. We should maintain an incoming adjacency index or claim-specific relation index. The baseline favors clarity over production query cost.

Exercise 12.4. Why reject non-finite confidence?

Solution. NaN can pass incomplete range checks and break ordering or aggregation assumptions. A schema should admit only finite values in the declared interval.

Exercise 12.5. Which invariant catches Claim -[PARTICIPANT]-> tea?

Solution. The source-target type rule. PARTICIPANT should originate at an Episode and target an allowed participant type, not connect a claim to an entity.

13. Storage, evaluation, limits, and the frontier

The abstract model does not force one database. A native property-graph store matches typed vertices, identified edges, properties, and traversals. A relational design can use nodes, edges, claims, and episodes tables with foreign keys and indexes. RDF 1.2 offers triple terms and reifiers for statements about propositions. An event log plus materialized graph provides replay and current views.

The choice depends on workload:

Need Useful physical support
exact identity lookup unique key index
neighborhood expansion adjacency index
current-state query validity and status index
semantic seed retrieval vector index
provenance audit source and derivation index
replay and repair immutable event log

We should evaluate the model, not only the database. A schema-level test suite can inject:

  • two parallel edges and verify that both survive;
  • one retried event and verify idempotency;
  • a claim without provenance and verify rejection;
  • compatible time-qualified claims and verify no false contradiction;
  • a supersession cycle and verify rejection;
  • a cross-tenant edge and verify isolation;
  • source deletion and verify the derived-data traversal.

The memory multigraph still has limits. Entity resolution can merge people incorrectly. Extractors can create false claims. Reification increases graph size. Schemas drift. Confidence values can look scientific without calibration. A rich graph can amplify surveillance if consent and deletion are afterthoughts. Structure improves inspectability, not truth by itself.

Current agent-memory systems explore parts of this design space. Zep and Graphiti emphasize temporally aware knowledge graphs over changing conversational data. Mem0 reports a graph-enhanced memory variant. A-MEM builds dynamically linked memory networks inspired by Zettelkasten organization. These systems support the usefulness of structured relations, but no benchmark result determines our ontology or guarantees correct provenance.

The frontier is moving toward bitemporal storage, explicit contradiction handling, learned memory organization, graph and vector hybrid retrieval, and auditable agent tools. The durable contribution of our model is the contract beneath those techniques: independent identity, typed occurrences, addressable claims, episode structure, provenance paths, qualified versions, and bounded evidence reconstruction.

13.1 Solved exercises

Exercise 13.1. Does using a graph database guarantee a multigraph-safe schema?

Solution. No. Application code may still merge edges by endpoints, overwrite versions, or omit provenance. The database supplies capabilities; invariants define correctness.

Exercise 13.2. Which test distinguishes legitimate multiplicity from retries?

Solution. Insert two events with different occurrence identifiers and confirm both survive, then replay one identifier and confirm no additional occurrence is created.

Exercise 13.3. Why keep an immutable event log beside a materialized graph?

Solution. The log supports replay, repair, extractor upgrades, and audits. The graph supports efficient current traversal. Each structure answers a different operational need.

Exercise 13.4. Is a larger graph always a better memory?

Solution. No. Noise, duplicates, unsafe data, and unqualified claims can reduce decision quality. Selective writing and governed forgetting remain necessary.

Exercise 13.5. What does structure fail to guarantee?

Solution. Truth, consent, calibrated confidence, correct entity resolution, and useful retrieval. These require evidence, policy, evaluation, and operation beyond topology.

Conclusion

Agent experience cannot be reduced to one mutable relation between each pair of entities. The same participants meet again. The same action produces different outcomes. Several sources support or dispute one proposition. A later observation may qualify rather than erase an earlier one.

The typed property multigraph preserves these distinctions:

\[\mathcal M= (V,E,s,t,\lambda_V,\lambda_E,X_V,X_E).\]

Vertices give identity to people, agents, entities, messages, episodes, claims, actions, and outcomes. Edges record independently addressable relation occurrences. Reified claims accept provenance, evidence, qualifications, and versions. Episode vertices turn n-ary experience into traversable binary structure. Retrieval then assembles a bounded evidence subgraph instead of returning anonymous text fragments.

The central design rule is simple:

Give an object an identity when the future must refer to that object independently.

This rule tells us why messages, claims, episodes, actions, outcomes, and edges cannot be casually collapsed. It also tells us when not to add a vertex: if a binary occurrence is already independently identified and no other relation needs to target it, an edge may remain the clearest representation.

Our schema is now structurally expressive, but its temporal semantics are still introductory. In the next article, Time, Provenance, and Contradiction, we will separate event time, validity time, and transaction time, define bitemporal queries, preserve competing sources, and derive version-management rules without erasing history.

References

(Updated: )