Declare an entity-and-relationship ontology for graphiti's custom entity extraction.
A consumer writes:
defmodule MyOntology do
use Gralkor.Ontology, entities: :strict, relationships: :scoped
entity Teammate, "A person the agent works with." do
field :handle, :string, required: true, doc: "stable login handle"
field :timezone, :string, doc: "IANA tz"
end
entity WorkingPreference, "A way a teammate prefers to work." do
field :description, :string, required: true
end
from Teammate do
prefers WorkingPreference do
field :since, :string, doc: "date first observed"
end
trusts Teammate
end
endThe macro produces MyOntology.__ontology__/0 — a payload the Pythonx
layer translates into graphiti's entity_types, edge_types,
edge_type_map, and excluded_entity_types. The Elixir side never
constructs Pydantic classes.
An entity's optional description becomes the extracted type's own description. graphiti's extractor reads it to decide when to mint the entity, so a type whose name alone is ambiguous is extracted far more reliably with one.
Entity and edge type names are unrestricted, but field names are not:
graphiti rejects any custom entity attribute colliding with its own
EntityNode fields — uuid, name, group_id, labels, created_at,
summary, attributes, name_embedding. This DSL does not check that at
compile time, so such a field raises EntityTypeValidationError from
Python on the first write through the owning Lens.
See test-trees/unit/gralkor-ontology_TEST_TREES.md.