How to write and read facts#
This guide shows you how to create an entity, write single- and multi-valued field facts onto it, and read those values back, either through an entity snapshot or directly by field. Use it once you have a schema and a FactGraph instance and want to populate and inspect data.
Prerequisites#
- A
FactGraphinstance built from your schema classes. See How to define a schema and the factgraph reference for constructor options. - Each schema class declares at least one
Identity()field and zero or moreField()fields. See the schema reference.
The examples below use this schema:
from factgraph.sdk import Entity, FactGraph, Field, Identity
class User(Entity):
user_id: str = Identity()
tenant_id: str = Identity()
name: str = Field()
tags: list[str] = Field()
fg = FactGraph.create(schema_classes=[User])Steps#
Create the entity and obtain a managed
e_ref.fg.entities.createtakes the entity class plus the full identity bundle as keyword arguments and returns the entity reference string:e_ref = fg.entities.create(User, user_id="alice", tenant_id="acme")createemits the Identity claims eagerly and atomically. It does not write any field values yet. A missing identity keyword raisesSDKStoreError(“missing identity field: …”), and creating the same identity bundle twice raisesEntityAlreadyExistsError(codeENTITY_ALREADY_EXISTS). See the errors reference.Write a single-valued field with
fg.fields.set. Pass theFielddescriptor (for exampleUser.name), thee_ref, and the value. It returns the assertion id of the write:asrt_id = fg.fields.set(User.name, e_ref, "Alice")Calling
setagain on the same single field overwrites the visible value: the latest write wins.Append a multi-valued field with
fg.fields.add. Each call adds one value and returns its assertion id:fg.fields.add(User.tags, e_ref, "red") fg.fields.add(User.tags, e_ref, "blue")Use
setonly for single-cardinality fields andaddonly for multi-cardinality fields. Callingseton a multi field (oraddon a single field) raisesCardinalityError(codeFIELD_CARDINALITY_MISMATCH).To attach provenance to a write, pass a
metadictionary. Bothsetandaddacceptmeta=Noneby default:fg.fields.add(User.tags, e_ref, "green", meta={"source": "import_job"})Read one field value back with
fg.fields.get, passing theFielddescriptor ande_ref. A single field returns its current value, orNonewhen no active claim exists. A multi field returns a sorted tuple of its active values, or()when empty:fg.fields.get(User.name, e_ref) # "Alice" fg.fields.get(User.tags, e_ref) # ("blue", "red")To read a whole entity at once, call
fg.entities.getwith the entity class and its identity values. It returns anEntitySnapshot(orNoneif the entity is not visible). Field values are read off the snapshot as attributes:snap = fg.entities.get(User, user_id="alice", tenant_id="acme") snap.name # "Alice" snap.tags # ("blue", "red")The snapshot is read-only: assigning to an attribute raises
FrozenSnapshotError.snap.identityreturns the known identity kwargs, andsnap.refis thee_ref.To verify:
snap.nameequals the value you set, andsnap.tagscontains every value you added.
Variations#
- Lazy materialization instead of explicit create.
fg.entities.ref(User, user_id="alice", tenant_id="acme")returns a managede_refwithout writing to the ledger. The firstfg.fields.setorfg.fields.addon thate_refthen materializes the Identity claims along with the field claim. Usecreatewhen you want the entity to exist before any field is written. - Entity-reference fields. When a field’s value type is another entity, first obtain a managed
e_reffor the value entity (viareforcreate), then pass thate_refas the value tosetoradd. Reading the field back returns the value entity’se_ref. - Writing to an unmanaged
e_ref.set,add, andgetresolve thee_refthrough thisFactGraphinstance. Passing ane_refthat this instance did not produce raisesSDKStoreErrorwith codeUNRESOLVABLE_E_REF; callfg.entities.ref(...)orfg.entities.create(...)first.
See also: Three-layer API reference for the full fg.entities / fg.fields surface, How to find and match entities, and Append-only ledger and provenance for why writes accumulate as assertions.