predicates
A curated registry of 133 verbs — 25 enshrined, 108 proposed — each defined once with machine-readable semantics and a precomputed deterministic ID.
@0xintuition/predicates answers the third question in the data model — what triples do we support? It ships a curated registry of verbs — 25 enshrined, 108 proposed, 133 in all across 14 categories — for connecting atoms: createdBy, sameAs, hasTag, listedIn, endorse, trust, authoredBy, and the rest. The full registry is browsable at /predicates.html, one page per verb — e.g. createdBy, sameAs, use.
A schema.org property becomes a predicate only once promoted. schema.org can inform which predicates Intuition adds, but it never auto-creates them — promotion means Intuition deliberately adopts the verb and decides its object model. That curation is what keeps the graph's grammar shared instead of sprawling.
Two tiers: proposed and enshrined#
Every predicate in the registry sits in one of two tiers, and the difference is about how settled the verb is — not whether it exists:
| Tier | Count | What's settled | What it means for you |
|---|---|---|---|
| Proposed | 108 | Stable definition + deterministic atom ID, already | The verb is in the registry today and its ID won't change; its semantics are still being refined before promotion. |
| Enshrined | 25 | Object model decided | Safe to build on — the atom ID is what's stored onchain. |
The 25 enshrined keys today: hasType, sameAs, hasTag, hasCategory, follow, like, endorse, trust, distrust, recommend, vouchFor, contain, listedIn, curatedBy, alternativeTo, createdBy, linkedAccount, url, imgUrl, hasDescription, agreeWith, disagreeWith, bullishOn, bearishOn, betterThan.
Promotion is a one-way move from proposed to enshrined, and it changes nothing about identity — a proposed predicate's atom ID is already deterministic, so triples written against it survive the promotion untouched. What promotion adds is commitment: the object model is decided, and the verb becomes part of the vocabulary the protocol stands behind.
Machine-readable semantics#
A predicate isn't just a name with an ID. Every predicate — proposed or enshrined — carries a typed semantic record:
marketPattern—attributive|depositional|comparative. Is this a fact about the subject, a position someone takes, or a ranking between two things?objectKind—entity|claim|literal(with aliteralTypewhen literal). What belongs in the object slot: another atom, a claim, or a raw value like a string or URL?polarity— whether the verb carries positive, negative, or neutral sentiment.temporalNature—permanent|state|event. Does the claim hold forever, until revised, or describe a moment?claimType—factual|evaluative. Is this checkable against the world, or an opinion?- Structural flags —
isTransitive,isSymmetric,isHierarchical. inversePredicate— optional pointer to the verb that reads the edge the other way.
This is what lets an app handle an edge it has never seen. A renderer that knows nothing about betterThan can still read marketPattern: comparative and claimType: evaluative and present it as a contested ranking rather than a fact. A graph traversal can follow isTransitive verbs safely, flip edges through inversePredicate, and know from objectKind whether the object resolves to an atom or a literal. Generic tooling works across all 133 verbs because the semantics travel with the predicate, not with the app.
One file per predicate, tree-shakeable#
Each predicate has its own standalone import, so only the verbs you use ship in your bundle:
import { multiVaultCreateTriples } from "@0xintuition/protocol";
import { useId } from "@0xintuition/predicates/use";
import { createdById } from "@0xintuition/predicates/createdBy";
import { calculateAtomId } from "@0xintuition/ids";
import { parseEther } from "viem";
const reactId = calculateAtomId("https://react.dev");
const vercelId = calculateAtomId("https://vercel.com");
const per = parseEther("0.1");
const txHash = await multiVaultCreateTriples(cfg, {
args: [
[id, id ], // subjects
[useId, createdById ], // predicates — registry atom IDs
[reactId, vercelId ], // objects
[per, per ], // value per triple
],
value: per * 2n,
});
Here createdBy is enshrined and use is proposed — both resolve to deterministic atom IDs from the same registry. Prefer the aggregate import? import { PREDICATE_IDS } from "@0xintuition/predicates" still works.
The lifecycle of a predicate#
- Defined once. One file per predicate, one canonical record. Each export carries its key, spec, semantic metadata, and a precomputed atom ID (derived via
@0xintuition/idsfrom canonical bytes — never hand-copied into source). - Used everywhere. Every triple references the same canonical predicate atom ID. Joins line up; queries return consistent shapes across apps that have never coordinated.
- Stable onchain. When a triple is committed, the predicate atom ID is what's stored. No translation between offchain and on.
Same key, same predicate atom ID, everywhere. This is what makes claims portable: a
createdBytriple written by one app is the same edge a second app queries for, because both resolved the verb through this package.
Two columns, decided separately#
The same schema.org property can matter to atom data and to triples — but each decision is made on its own:
// Atom-data column → classifications.fields
// embedded in the atom at creation time
Book atom data: name, author, isbn, sameAs
// Triple-metadata column → predicates (registry verbs)
// recommended for claims about the atom later
Book triple metadata: authoredBy, hasCategory, hasDescription, sameAs
// A schema.org property can matter to both columns,
// but each decision is made on its own.
The atom-data column belongs to classifications; this package owns the triple-metadata column. The two are formally connected: every classification ships metadataPredicates — its recommended verbs — plus a typed matrix declaring what kind of object each verb expects for that classification. See the classifications page for the matrix and its accessors.
Where predicates take you#
Predicates are the grammar; Triples & Predicates covers the full claim model, including counter-triples for disagreement. buildTripleByName in @0xintuition/primitives/triple resolves predicates by name when you want ergonomics over explicit imports, and Offchain to Onchain shows the verbs at work in a full lifecycle. Browse the whole registry at /predicates.html.