Assessment, 2026-09-04 · 0.30.1 (a6e026f)
| Read at | a6e026f |
|---|---|
| Repository | github.com/getzep/graphiti |
| Licence | Apache-2.0 |
| Assessed as | stores, derives |
| Reaches | no level yet |
| Read by | Troy Brandon Clifford |
| Level | Meets | What the level asks |
|---|---|---|
| TR-1 Recorded | 4/5 | The record exists and is append-only. |
| TR-2 Explained | 3/5 | Every belief resolves to its evidence, and disagreements survive. |
| TR-3 Gated | n/a | Actions carry a verdict, and approvals carry a name. |
| TR-4 Verifiable | 0/3 | The record can be shown not to have changed. |
A count is requirements fully met out of those that apply. This system is assessed as stores, derives, and requirements outside that are not counted against it.
Graphiti is bi-temporal by design and it shows in almost every answer here. A fact that stops being true is not removed: resolve_edge_contradictions stamps invalid_at and expired_at on the existing edge and keeps it, so both sides of a disagreement remain in the graph and a query about a past moment can still be answered. Facts also point at the episodes they were extracted from, and the raw episode content is retained as a separate node type, which means the told and the inferred can never be confused for one another. This is the strongest showing of the systems assessed so far and it was arrived at independently of this specification, which is the most useful kind of agreement. The single thing standing between it and TR-1 is that deletion, when it does happen, leaves no record that it happened.
Twenty requirements, each stated as a capability rather than a format, so a system that holds the information in its own shape counts as having it. An absent verdict cites where the assessor looked and did not find it, which is the difference between a measurement and an accusation.
The record exists and is append-only.
R1.1 · present. When the system stores a fact, does it durably record when that happened?
The separation of transaction time from valid time is exactly the distinction the specification draws between when an entry was written and when the fact held, and graphiti keeps both.
R1.2 · present. When a stored fact changes, is the previous version still readable?
R1.3 · present. Does the ordinary write path ever destroy what was previously recorded?
A correction is a new edge plus a closed interval on the old one, which is what the specification asks for. Hard deletion exists but is an explicit administrative call rather than part of this path, and is assessed at R1.5.
R1.4 · present. Are entries distinguishable by kind, or is everything one undifferentiated blob of text?
R1.5 · absent. When data must be destroyed for a legal reason, is the destruction itself recorded?
This is the one requirement keeping graphiti below TR-1, and it is narrow. Everything about the ordinary write path is append-only and bi-temporal. What is missing is that when a deletion does occur, whether for privacy or housekeeping, the graph afterwards is indistinguishable from one where the data never existed. A tombstone carrying the deleted uuid, the time and the requester, without the content, would close it.
Every belief resolves to its evidence, and disagreements survive.
R2.1 · present. Can the source a stored fact came from be recovered from the store, by following a link rather than by guessing?
The link is bidirectional and followable, and the raw material is retained rather than discarded after extraction. This is the requirement most systems miss and it is the one graphiti answers best.
R2.2 · present. Can a fact the system inferred be told apart from one it was told?
The distinction is structural rather than a flag, which is stronger: a consumer cannot accidentally read an extracted fact as something a person said, because the two are not the same kind of object.
R2.3 · present. When two stored facts about the same proposition disagree, do both survive?
R2.4 · partial. Is the disagreement itself queryable, or must a reader diff rows to notice it?
A disagreement is discoverable: query the edges between one pair of nodes and look for a closed interval. It is not recorded as such, so an edge invalidated by a contradiction and one invalidated because the fact simply lapsed look identical, and nothing points from the loser to the winner.
R2.5 · partial. When a conflict is resolved, does the record say who resolved it and by what method?
That the conflict was resolved is recorded. Who resolved it is not. The decision runs through an LLM extraction step and then the temporal comparison in this function, and the graph afterwards carries neither the model, the prompt version nor the reason.
Actions carry a verdict, and approvals carry a name.
R3.1, R3.2, R3.3, R3.4, R3.5, R3.6, R3.7 are not assessed here, because this system is not in that business and marking it down for that would be dishonest.
The record can be shown not to have changed.
R4.1 · absent. Does the system publish a scheme under which the record's past state can be verified?
R4.2 · absent. Can an independent party run that verification without the vendor's cooperation, and without the operator's?
R4.3 · absent. Would alteration of a past entry be detectable after the fact?
The bi-temporal design means the ordinary code path does not lose history, which is a different and weaker property than being able to show that nobody went around the code path.
Read of graphiti_core/edges.py, graphiti_core/nodes.py and graphiti_core/utils/maintenance/edge_operations.py at a6e026f, cloned from the public repository. Line numbers are that commit's.
Then it is wrong in the ordinary way readings are wrong, and every verdict cites a file and a line at a pinned commit precisely so that being wrong is cheap to demonstrate. The remedy is a pull request against the subject file, and it does not involve persuading anybody. Nobody applied for this and it is not a certification.
The standing register carries every system side by side, and the rubric is the twenty requirements in full, free to apply to anything, including to this assessment.